@workglow/postgres 0.2.34 → 0.2.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +51 -0
  2. package/dist/job-queue/browser.d.ts.map +1 -1
  3. package/dist/job-queue/browser.js +11 -1
  4. package/dist/job-queue/browser.js.map +3 -3
  5. package/dist/job-queue/bun.d.ts.map +1 -1
  6. package/dist/job-queue/common.d.ts.map +1 -1
  7. package/dist/job-queue/node.d.ts.map +1 -1
  8. package/dist/job-queue/node.js +11 -1
  9. package/dist/job-queue/node.js.map +3 -3
  10. package/dist/migrations/PostgresMigrationRunner.d.ts +7 -3
  11. package/dist/migrations/PostgresMigrationRunner.d.ts.map +1 -1
  12. package/dist/migrations/common.d.ts.map +1 -1
  13. package/dist/storage/PostgresTabularStorage.d.ts +14 -2
  14. package/dist/storage/PostgresTabularStorage.d.ts.map +1 -1
  15. package/dist/storage/PostgresVectorStorage.d.ts +1 -5
  16. package/dist/storage/PostgresVectorStorage.d.ts.map +1 -1
  17. package/dist/storage/browser.d.ts.map +1 -1
  18. package/dist/storage/browser.js +50 -106
  19. package/dist/storage/browser.js.map +4 -4
  20. package/dist/storage/bun.d.ts.map +1 -1
  21. package/dist/storage/common.d.ts.map +1 -1
  22. package/dist/storage/node.d.ts.map +1 -1
  23. package/dist/storage/node.js +60 -106
  24. package/dist/storage/node.js.map +5 -5
  25. package/dist/text/PostgresFtsTextIndex.d.ts +108 -0
  26. package/dist/text/PostgresFtsTextIndex.d.ts.map +1 -0
  27. package/dist/text/browser.d.ts +7 -0
  28. package/dist/text/browser.d.ts.map +1 -0
  29. package/dist/text/browser.js +185 -0
  30. package/dist/text/browser.js.map +10 -0
  31. package/dist/text/bun.d.ts +7 -0
  32. package/dist/text/bun.d.ts.map +1 -0
  33. package/dist/text/common.d.ts +7 -0
  34. package/dist/text/common.d.ts.map +1 -0
  35. package/dist/text/node.d.ts +7 -0
  36. package/dist/text/node.d.ts.map +1 -0
  37. package/dist/text/node.js +185 -0
  38. package/dist/text/node.js.map +10 -0
  39. package/package.json +25 -9
@@ -3,12 +3,12 @@
3
3
  "sources": ["../../src/job-queue/PostgresQueueStorage.ts", "../../src/migrations/PostgresMigrationRunner.ts", "../../src/migrations/postgresQueueMigrations.ts", "../../src/job-queue/PostgresRateLimiterStorage.ts", "../../src/migrations/postgresRateLimiterMigrations.ts"],
4
4
  "sourcesContent": [
5
5
  "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { Pool } from \"@workglow/postgres/storage\";\nimport { createServiceToken, getLogger, makeFingerprint, uuid4 } from \"@workglow/util\";\nimport { JobStatus } from \"@workglow/job-queue\";\nimport type {\n IQueueStorage,\n JobStorageFormat,\n PrefixColumn,\n QueueChangePayload,\n QueueStorageOptions,\n QueueSubscribeOptions,\n} from \"@workglow/job-queue\";\nimport {\n assertPrefixesSafe,\n buildPrefixInsertFragments,\n buildPrefixWhereClause,\n getPrefixColumnNames,\n getPrefixParamValues,\n PostgresDialect,\n} from \"@workglow/storage\";\nimport { PostgresMigrationRunner } from \"../migrations/PostgresMigrationRunner\";\nimport { postgresQueueMigrations } from \"../migrations/postgresQueueMigrations\";\n\nexport const POSTGRES_QUEUE_STORAGE = createServiceToken<IQueueStorage<any, any>>(\n \"jobqueue.storage.postgres\"\n);\n\n/**\n * Subset of pg.PoolClient that {@link PostgresQueueStorage.subscribeToChanges}\n * needs. Typed locally so we don't require `pg` types at the storage layer.\n */\ninterface ListenClient {\n query: (sql: string) => Promise<unknown>;\n release: () => void;\n removeAllListeners?: (event: string) => void;\n on: (event: string, listener: (...args: any[]) => void) => void;\n}\n\n/**\n * PostgreSQL implementation of a job queue.\n * Provides storage and retrieval for job execution states using PostgreSQL.\n */\nexport class PostgresQueueStorage<Input, Output> implements IQueueStorage<Input, Output> {\n public readonly scope = \"cluster\" as const;\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for the job queue */\n protected readonly tableName: string;\n\n constructor(\n protected readonly db: Pool,\n protected readonly queueName: string,\n options?: QueueStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n\n // Validate prefix column names to prevent SQL injection in DDL statements\n assertPrefixesSafe(this.prefixes);\n\n // Generate table name based on prefix configuration to avoid column conflicts\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.tableName = `job_queue_${prefixNames}`;\n } else {\n this.tableName = \"job_queue\";\n }\n }\n\n /** WHERE-clause helper specialized for this instance's dialect + prefix values. */\n private buildPrefixWhereClause(startParam: number) {\n return buildPrefixWhereClause(PostgresDialect, this.prefixes, this.prefixValues, startParam);\n }\n\n /** Returns prefix values in column order. */\n private getPrefixParamValues(): Array<string | number> {\n return getPrefixParamValues(this.prefixes, this.prefixValues);\n }\n\n /**\n * Returns the versioned migrations that this storage's table layout depends\n * on. Callers can compose them with other storages' migrations under a\n * shared {@link PostgresMigrationRunner}; otherwise call {@link migrate}.\n */\n public getMigrations() {\n return postgresQueueMigrations(this.tableName, this.prefixes);\n }\n\n /**\n * Applies any pending migrations for this queue's table. Idempotent —\n * already-applied versions are recorded in `_storage_migrations` and\n * skipped on subsequent calls.\n */\n public async migrate(): Promise<void> {\n await new PostgresMigrationRunner(this.db).run(this.getMigrations());\n }\n\n /**\n * Channel name for this storage's LISTEN/NOTIFY. Mirrors the trigger's\n * computation so subscriber and notifier agree.\n */\n private notifyChannelName(): string {\n // md5() returns 32 hex chars; combined with the 7-char prefix this is well\n // under Postgres's 63-byte identifier limit.\n const tableAndQueue = `${this.tableName}${this.queueName}`;\n const hash = createHash(\"md5\").update(tableAndQueue).digest(\"hex\");\n return `wglw_q_${hash}`;\n }\n\n /**\n * Adds a new job to the queue.\n * @param job - The job to add\n * @returns The ID of the added job\n */\n public async add(job: JobStorageFormat<Input, Output>): Promise<unknown> {\n const now = new Date().toISOString();\n job.queue = this.queueName;\n job.job_run_id = job.job_run_id ?? uuid4();\n job.fingerprint = await makeFingerprint(job.input);\n job.status = JobStatus.PENDING;\n job.progress = 0;\n job.progress_message = \"\";\n job.progress_details = null;\n job.created_at = now;\n job.run_after = now;\n\n const prefixColumnNames = getPrefixColumnNames(this.prefixes);\n const { columns: prefixColumnsInsert, placeholders: prefixParamPlaceholders } =\n buildPrefixInsertFragments(PostgresDialect, this.prefixes, 1);\n const prefixParamValues = this.getPrefixParamValues();\n const baseParamStart = prefixColumnNames.length + 1;\n\n const sql = `\n INSERT INTO ${this.tableName}(\n ${prefixColumnsInsert}queue, \n fingerprint, \n input, \n run_after,\n created_at,\n deadline_at,\n max_retries, \n job_run_id, \n progress, \n progress_message, \n progress_details\n )\n VALUES \n (${prefixParamPlaceholders}$${baseParamStart},$${baseParamStart + 1},$${baseParamStart + 2},$${baseParamStart + 3},$${baseParamStart + 4},$${baseParamStart + 5},$${baseParamStart + 6},$${baseParamStart + 7},$${baseParamStart + 8},$${baseParamStart + 9},$${baseParamStart + 10})\n RETURNING id`;\n const params = [\n ...prefixParamValues,\n job.queue,\n job.fingerprint,\n JSON.stringify(job.input),\n job.run_after,\n job.created_at,\n job.deadline_at,\n job.max_retries,\n job.job_run_id,\n job.progress,\n job.progress_message,\n job.progress_details ? JSON.stringify(job.progress_details) : null,\n ];\n const result = await this.db.query(sql, params);\n\n if (!result) throw new Error(\"Failed to add to queue\");\n job.id = result.rows[0].id;\n return job.id;\n }\n\n /**\n * Retrieves a job by its ID.\n * @param id - The ID of the job to retrieve\n * @returns The job if found, undefined otherwise\n */\n public async get(id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `SELECT *\n FROM ${this.tableName}\n WHERE id = $1 AND queue = $2${prefixConditions}\n FOR UPDATE SKIP LOCKED\n LIMIT 1`,\n [id, this.queueName, ...prefixParams]\n );\n\n if (!result || result.rows.length === 0) return undefined;\n return result.rows[0];\n }\n\n /**\n * Retrieves a slice of jobs from the queue.\n * @param num - Maximum number of jobs to return\n * @returns An array of jobs\n */\n public async peek(\n status: JobStatus = JobStatus.PENDING,\n num: number = 100\n ): Promise<Array<JobStorageFormat<Input, Output>>> {\n num = Number(num) || 100; // TS does not validate, so ensure it is a number\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(4);\n const result = await this.db.query<\n JobStorageFormat<Input, Output>,\n Array<string | number | JobStatus>\n >(\n `\n SELECT *\n FROM ${this.tableName}\n WHERE queue = $1\n AND status = $2${prefixConditions}\n ORDER BY run_after ASC\n LIMIT $3\n FOR UPDATE SKIP LOCKED`,\n [this.queueName, status, num, ...prefixParams]\n );\n if (!result) return [];\n return result.rows;\n }\n\n /**\n * Retrieves the next available job that is ready to be processed.\n * @param workerId - Worker ID to associate with the job (required)\n * @returns The next job or undefined if no job is available\n */\n public async next(workerId: string): Promise<JobStorageFormat<Input, Output> | undefined> {\n // Parameters: $1=status, $2=queue, $3=status, $4=worker_id, $5+=prefix params\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(5);\n const result = await this.db.query<\n JobStorageFormat<Input, Output>,\n Array<string | number | JobStatus | null>\n >(\n `\n UPDATE ${this.tableName} \n SET status = $1, last_ran_at = NOW() AT TIME ZONE 'UTC', worker_id = $4\n WHERE id = (\n SELECT id \n FROM ${this.tableName} \n WHERE queue = $2 \n AND status = $3\n ${prefixConditions}\n AND run_after <= NOW() AT TIME ZONE 'UTC'\n ORDER BY run_after ASC \n FOR UPDATE SKIP LOCKED \n LIMIT 1\n )\n RETURNING *`,\n [JobStatus.PROCESSING, this.queueName, JobStatus.PENDING, workerId, ...prefixParams]\n );\n\n return result?.rows?.[0] ?? undefined;\n }\n\n /**\n * Retrieves the number of jobs in the queue with a specific status.\n * @param status - The status of the jobs to count\n * @returns The count of jobs with the specified status\n */\n public async size(status = JobStatus.PENDING): Promise<number> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query<{ count: string }, Array<string | number | JobStatus>>(\n `\n SELECT COUNT(*) as count\n FROM ${this.tableName}\n WHERE queue = $1\n AND status = $2${prefixConditions}`,\n [this.queueName, status, ...prefixParams]\n );\n if (!result) return 0;\n return parseInt(result.rows[0].count, 10);\n }\n\n /**\n * Marks a job as complete with its output or error.\n * Enhanced error handling:\n * - For a retryable error, increments run_attempts and updates run_after.\n * - Marks a job as FAILED immediately for permanent or generic errors.\n */\n public async complete(jobDetails: JobStorageFormat<Input, Output>): Promise<void> {\n const prefixParams = this.getPrefixParamValues();\n\n if (jobDetails.status === JobStatus.DISABLED) {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(4);\n await this.db.query(\n `UPDATE ${this.tableName} \n SET \n status = $1, \n progress = 100,\n progress_message = '',\n progress_details = NULL,\n completed_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $2 AND queue = $3${prefixConditions}`,\n [jobDetails.status, jobDetails.id, this.queueName, ...prefixParams]\n );\n } else if (jobDetails.status === JobStatus.PENDING) {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(7);\n await this.db.query(\n `UPDATE ${this.tableName} \n SET \n error = $1, \n error_code = $2,\n status = $3, \n run_after = $4, \n progress = 0,\n progress_message = '',\n progress_details = NULL,\n run_attempts = run_attempts + 1, \n last_ran_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $5 AND queue = $6${prefixConditions}`,\n [\n jobDetails.error,\n jobDetails.error_code,\n jobDetails.status,\n jobDetails.run_after,\n jobDetails.id,\n this.queueName,\n ...prefixParams,\n ]\n );\n } else {\n const { conditions: prefixConditions } = this.buildPrefixWhereClause(7);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET \n output = $1, \n error = $2, \n error_code = $3,\n status = $4, \n progress = 100,\n progress_message = '',\n progress_details = NULL,\n run_attempts = run_attempts + 1, \n completed_at = NOW() AT TIME ZONE 'UTC',\n last_ran_at = NOW() AT TIME ZONE 'UTC'\n WHERE id = $5 AND queue = $6${prefixConditions}`,\n [\n jobDetails.output ? JSON.stringify(jobDetails.output) : null,\n jobDetails.error ?? null,\n jobDetails.error_code ?? null,\n jobDetails.status,\n jobDetails.id,\n this.queueName,\n ...prefixParams,\n ]\n );\n }\n }\n\n /**\n * Clears all jobs from the queue.\n */\n public async deleteAll(): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n await this.db.query(\n `\n DELETE FROM ${this.tableName}\n WHERE queue = $1${prefixConditions}`,\n [this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Looks up cached output for a given input\n * Uses input fingerprinting for efficient matching\n * @returns The cached output or null if not found\n */\n public async outputForInput(input: Input): Promise<Output | null> {\n const fingerprint = await makeFingerprint(input);\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `\n SELECT output\n FROM ${this.tableName}\n WHERE fingerprint = $1 AND queue = $2 AND status = 'COMPLETED'${prefixConditions}`,\n [fingerprint, this.queueName, ...prefixParams]\n );\n if (!result || result.rows.length === 0) return null;\n return result.rows[0].output;\n }\n\n /**\n * Aborts a job by setting its status to \"ABORTING\".\n * This method will signal the corresponding AbortController so that\n * the job's execute() method (if it supports an AbortSignal parameter)\n * can clean up and exit.\n */\n public async abort(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET status = 'ABORTING' \n WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Releases a claimed job back to PENDING without incrementing run_attempts.\n * @param jobId - The id of the claimed job to release.\n */\n public async release(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `\n UPDATE ${this.tableName}\n SET status = 'PENDING',\n worker_id = NULL,\n progress = 0,\n progress_message = '',\n progress_details = NULL\n WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Retrieves all jobs for a given job run ID.\n * @param job_run_id - The ID of the job run to retrieve\n * @returns An array of jobs\n */\n public async getByRunId(job_run_id: string): Promise<Array<JobStorageFormat<Input, Output>>> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n const result = await this.db.query(\n `\n SELECT * FROM ${this.tableName} WHERE job_run_id = $1 AND queue = $2${prefixConditions}`,\n [job_run_id, this.queueName, ...prefixParams]\n );\n if (!result) return [];\n return result.rows;\n }\n\n /**\n * Implements the abstract saveProgress method from JobQueue\n */\n public async saveProgress(\n jobId: unknown,\n progress: number,\n message: string,\n details: Record<string, any>\n ): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(6);\n await this.db.query(\n `\n UPDATE ${this.tableName} \n SET progress = $1,\n progress_message = $2,\n progress_details = $3\n WHERE id = $4 AND queue = $5${prefixConditions}`,\n [\n progress,\n message,\n details ? JSON.stringify(details) : null,\n jobId,\n this.queueName,\n ...prefixParams,\n ]\n );\n }\n\n /**\n * Deletes a job by its ID\n */\n public async delete(jobId: unknown): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n await this.db.query(\n `DELETE FROM ${this.tableName} WHERE id = $1 AND queue = $2${prefixConditions}`,\n [jobId, this.queueName, ...prefixParams]\n );\n }\n\n /**\n * Delete jobs with a specific status older than a cutoff date\n * @param status - Status of jobs to delete\n * @param olderThanMs - Delete jobs completed more than this many milliseconds ago\n */\n public async deleteJobsByStatusAndAge(status: JobStatus, olderThanMs: number): Promise<void> {\n const cutoffDate = new Date(Date.now() - olderThanMs).toISOString();\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(4);\n await this.db.query(\n `DELETE FROM ${this.tableName} \n WHERE queue = $1 \n AND status = $2 \n AND completed_at IS NOT NULL \n AND completed_at <= $3${prefixConditions}`,\n [this.queueName, status, cutoffDate, ...prefixParams]\n );\n }\n\n /**\n * Subscribe to INSERT/UPDATE notifications via PostgreSQL LISTEN/NOTIFY.\n * Replaces 100ms-poll fallback for cluster Postgres deployments — workers\n * wake within network-latency of an actual change rather than on a timer.\n *\n * Acquires a dedicated client from the pool (LISTEN occupies a connection\n * for its lifetime). On unsubscribe, runs UNLISTEN and releases the client.\n * On connection loss, attempts to reconnect with bounded backoff and\n * re-LISTEN. After every successful (re)connect — including the initial\n * one — emits a synthetic `{ type: \"RESYNC\" }` event so subscribers can\n * re-poll state and pick up any rows inserted during the disconnect window\n * (or between subscribe and the first NOTIFY landing).\n *\n * Throws synchronously when the underlying pool lacks `connect()`\n * (single-connection wrappers like PGLite) so the caller's try/catch can\n * fall back to polling. JobQueueServer.start does this and logs at debug.\n *\n * `options.prefixFilter` follows {@link QueueSubscribeOptions.prefixFilter}:\n * `undefined` means \"use the storage instance's configured prefixValues\",\n * `{}` means \"receive all changes regardless of prefix\".\n */\n public subscribeToChanges(\n callback: (change: QueueChangePayload<Input, Output>) => void,\n options?: QueueSubscribeOptions\n ): () => void {\n type PoolWithConnect = { connect: () => Promise<ListenClient> };\n const poolMaybe = this.db as unknown as Partial<PoolWithConnect>;\n if (typeof poolMaybe.connect !== \"function\") {\n // Detect synchronously so callers can catch and fall back to polling\n // without leaving a dangling unhandled promise rejection behind.\n throw new Error(\n \"PostgresQueueStorage.subscribeToChanges requires a pg.Pool (got a single-connection wrapper)\"\n );\n }\n const pool = poolMaybe as PoolWithConnect;\n\n const channel = this.notifyChannelName();\n // undefined -> default to instance prefixValues; {} -> no filtering;\n // partial -> filter by the provided subset (matches QueueSubscribeOptions docs).\n const effectivePrefixFilter: Readonly<Record<string, string | number>> | null =\n options?.prefixFilter === undefined\n ? this.prefixes.length > 0\n ? this.prefixValues\n : null\n : Object.keys(options.prefixFilter).length === 0\n ? null\n : options.prefixFilter;\n\n let unsubscribed = false;\n let activeClient: ListenClient | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n let backoffMs = 250;\n\n const dispatch = (change: QueueChangePayload<Input, Output>): void => {\n try {\n callback(change);\n } catch (err) {\n // Never let user callbacks tear down the listener loop.\n getLogger().debug(\"PostgresQueueStorage subscribe callback threw\", {\n channel,\n changeType: change.type,\n error: err,\n });\n }\n };\n\n const matchesPrefix = (\n change: QueueChangePayload<Input, Output>,\n filter: Readonly<Record<string, string | number>>\n ): boolean => {\n const row = (change.new ?? change.old) as Record<string, unknown> | undefined;\n if (!row) return false;\n for (const [k, v] of Object.entries(filter)) {\n if (row[k] !== v) return false;\n }\n return true;\n };\n\n // Hydrate the row referenced by a notification. Postgres NOTIFY is capped\n // at 8 KB so we ship only {id, queue, status} in the payload and fetch the\n // full row here — keeps subscriber payloads consistent with other backends\n // (e.g. Supabase realtime, IndexedDb) and lets prefixFilter inspect the\n // prefix columns the row actually has.\n const hydrate = async (id: unknown): Promise<JobStorageFormat<Input, Output> | undefined> => {\n try {\n return await this.get(id);\n } catch {\n return undefined;\n }\n };\n\n const handleNotification = (msg: { channel: string; payload?: string }): void => {\n if (msg.channel !== channel || !msg.payload) return;\n let parsed: { op: string; id: number; queue: string; status: string };\n try {\n parsed = JSON.parse(msg.payload);\n } catch {\n return;\n }\n void (async () => {\n const op = parsed.op;\n const fallback = {\n id: parsed.id,\n queue: parsed.queue,\n status: parsed.status,\n } as unknown as JobStorageFormat<Input, Output>;\n const fullRow = op === \"DELETE\" ? undefined : await hydrate(parsed.id);\n const change: QueueChangePayload<Input, Output> = {\n type: op === \"INSERT\" ? \"INSERT\" : op === \"DELETE\" ? \"DELETE\" : \"UPDATE\",\n new: op === \"DELETE\" ? undefined : (fullRow ?? fallback),\n old: op === \"DELETE\" ? fallback : undefined,\n };\n if (effectivePrefixFilter && !matchesPrefix(change, effectivePrefixFilter)) return;\n dispatch(change);\n })();\n };\n\n const connect = async (): Promise<void> => {\n if (unsubscribed) return;\n try {\n const client = await pool.connect();\n if (unsubscribed) {\n client.release();\n return;\n }\n activeClient = client;\n client.on(\"notification\", handleNotification);\n client.on(\"error\", () => scheduleReconnect());\n await client.query(`LISTEN ${channel}`);\n backoffMs = 250; // reset on successful (re)connect\n // Synthetic resync: any rows inserted between subscribe and LISTEN\n // landing (or during a reconnect window) have no NOTIFY backing.\n // Fire a no-payload event so subscribers can re-poll state.\n dispatch({ type: \"RESYNC\" });\n } catch {\n scheduleReconnect();\n }\n };\n\n const scheduleReconnect = (): void => {\n if (unsubscribed || reconnectTimer) return;\n const c = activeClient;\n activeClient = null;\n try {\n c?.removeAllListeners?.(\"notification\");\n c?.removeAllListeners?.(\"error\");\n c?.release();\n } catch {\n // best-effort\n }\n const delay = Math.min(backoffMs, 30_000);\n backoffMs = Math.min(backoffMs * 2, 30_000);\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n void connect();\n }, delay);\n };\n\n void connect();\n\n return () => {\n unsubscribed = true;\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n const c = activeClient;\n activeClient = null;\n if (c) {\n // Best-effort UNLISTEN; ignore errors (connection may already be dead).\n c.query(`UNLISTEN ${channel}`)\n .catch(() => {})\n .finally(() => {\n try {\n c.removeAllListeners?.(\"notification\");\n c.removeAllListeners?.(\"error\");\n c.release();\n } catch {\n // best-effort\n }\n });\n }\n };\n }\n}\n",
6
- "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Pool } from \"../storage/_postgres/node-bun\";\nimport {\n type IMigration,\n type IMigrationRunner,\n type RunMigrationsOptions,\n MIGRATIONS_TABLE,\n sortMigrations,\n} from \"@workglow/storage\";\n\n/**\n * Minimal \"queryable\" shape implemented by both a checked-out node-postgres\n * client and the PGlite-backed Pool we use in browser/test contexts.\n *\n * The runner programs against this so it can run BEGIN / up() / INSERT /\n * COMMIT through whichever path is available without dragging in pg's full\n * `PoolClient` type.\n */\ninterface PgQueryable {\n query<T = unknown, P extends unknown[] = unknown[]>(\n sql: string,\n params?: P\n ): Promise<{ rows: T[] }>;\n}\n\n/**\n * `Pool.connect()` shape — present on real node-postgres pools, absent on\n * the embedded PGlite pool used in browser/tests. Detected at runtime.\n */\ntype ConnectablePool = Pool & {\n connect?: () => Promise<PgQueryable & { release: () => void }>;\n};\n\n/**\n * Runs versioned migrations against a PostgreSQL pool.\n *\n * Each migration runs inside a single connection's transaction so the\n * bookkeeping INSERT and the migration's DDL commit together. node-postgres\n * pools don't guarantee that two consecutive `pool.query()` calls hit the\n * same client, so we check out a dedicated connection via `pool.connect()`\n * when available. The embedded PGlite pool used in browser/tests has no\n * `connect()` (it is single-client by construction), so we fall back to\n * the raw pool — BEGIN/COMMIT on it still hit the same backing connection.\n *\n * A unique constraint on `(component, version)` makes concurrent runners\n * safe: the loser of a race raises a duplicate-key error (`23505`) and we\n * treat that as \"already applied\".\n */\nexport class PostgresMigrationRunner implements IMigrationRunner<Pool> {\n constructor(private readonly db: Pool) {}\n\n async ensureBookkeepingTable(): Promise<void> {\n await this.db.query(`\n CREATE TABLE IF NOT EXISTS ${MIGRATIONS_TABLE} (\n component TEXT NOT NULL,\n version INTEGER NOT NULL,\n description TEXT,\n applied_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n PRIMARY KEY (component, version)\n )\n `);\n }\n\n async appliedVersions(component: string): Promise<Set<number>> {\n const result = await this.db.query<{ version: number }, [string]>(\n `SELECT version FROM ${MIGRATIONS_TABLE} WHERE component = $1`,\n [component]\n );\n return new Set(result.rows.map((r) => Number(r.version)));\n }\n\n /**\n * Acquires a transaction-scoped queryable. Returns the raw pool when the\n * underlying driver doesn't expose `connect()` (PGlite); the `release()`\n * callback is then a no-op.\n */\n private async acquireClient(): Promise<{ client: PgQueryable; release: () => void }> {\n const pool = this.db as ConnectablePool;\n if (typeof pool.connect === \"function\") {\n const client = await pool.connect();\n return { client, release: () => client.release() };\n }\n return { client: this.db as unknown as PgQueryable, release: () => undefined };\n }\n\n async run(\n migrations: ReadonlyArray<IMigration<Pool>>,\n options: RunMigrationsOptions = {}\n ): Promise<ReadonlyArray<IMigration<Pool>>> {\n await this.ensureBookkeepingTable();\n const sorted = sortMigrations(migrations);\n const applied: IMigration<Pool>[] = [];\n const cache = new Map<string, Set<number>>();\n const onProgress = options.onProgress;\n\n for (const m of sorted) {\n let seen = cache.get(m.component);\n if (!seen) {\n seen = await this.appliedVersions(m.component);\n cache.set(m.component, seen);\n }\n if (seen.has(m.version)) continue;\n\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"starting\",\n description: m.description,\n });\n\n const { client, release } = await this.acquireClient();\n try {\n await client.query(\"BEGIN\");\n // Migrations are written against the `Pool` type but only need a\n // queryable surface. Casting keeps the public signature stable while\n // routing the migration's queries through the dedicated client.\n await m.up(client as unknown as Pool, (fraction) => {\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"running\",\n description: m.description,\n fraction,\n });\n });\n await client.query(\n `INSERT INTO ${MIGRATIONS_TABLE}(component, version, description) VALUES ($1, $2, $3)`,\n [m.component, m.version, m.description ?? null]\n );\n await client.query(\"COMMIT\");\n seen.add(m.version);\n applied.push(m);\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"completed\",\n description: m.description,\n fraction: 1,\n });\n } catch (err: unknown) {\n await client.query(\"ROLLBACK\").catch(() => undefined);\n // Concurrent runner already inserted — treat as success.\n if ((err as { code?: string })?.code === \"23505\") {\n seen.add(m.version);\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"completed\",\n description: m.description,\n fraction: 1,\n });\n continue;\n }\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"failed\",\n description: m.description,\n error: err,\n });\n throw err;\n } finally {\n release();\n }\n }\n\n return applied;\n }\n}\n",
6
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Pool } from \"../storage/_postgres/node-bun\";\nimport {\n type IMigration,\n type IMigrationRunner,\n type RunMigrationsOptions,\n MIGRATIONS_TABLE,\n sortMigrations,\n} from \"@workglow/storage\";\n\n/**\n * Minimal \"queryable\" shape implemented by both a checked-out node-postgres\n * client and the PGlite-backed Pool we use in browser/test contexts.\n *\n * The runner programs against this so it can run BEGIN / up() / INSERT /\n * COMMIT through whichever path is available without dragging in pg's full\n * `PoolClient` type.\n */\ninterface PgQueryable {\n query<T = unknown, P extends unknown[] = unknown[]>(\n sql: string,\n params?: P\n ): Promise<{ rows: T[] }>;\n}\n\n/**\n * `Pool.connect()` shape — present on real node-postgres pools, absent on\n * the embedded PGlite pool used in browser/tests. Detected at runtime.\n */\ntype ConnectablePool = Pool & {\n connect?: () => Promise<PgQueryable & { release: () => void }>;\n};\n\n/**\n * In-process serialization of `run()` calls per `Pool` wrapper. Keyed by\n * the wrapper object (not the underlying database), so two separate pools\n * pointing at the same database — or runners in different processes — do\n * not contend through this map. Cross-instance races are handled by the\n * bookkeeping PK check below (a 23505 from a concurrent INSERT is caught\n * and treated as \"already applied\"). Without this in-process mutex,\n * multiple runners sharing one pool would each invoke `up()` before the\n * 23505 was raised. The map is a WeakMap so disposing the pool releases\n * the entry.\n */\nconst runLocks = new WeakMap<object, Promise<unknown>>();\n\n/**\n * Runs versioned migrations against a PostgreSQL pool.\n *\n * Each migration runs inside a single connection's transaction so the\n * bookkeeping INSERT and the migration's DDL commit together. node-postgres\n * pools don't guarantee that two consecutive `pool.query()` calls hit the\n * same client, so we check out a dedicated connection via `pool.connect()`\n * when available. The embedded PGlite pool used in browser/tests has no\n * `connect()` (it is single-client by construction), so we fall back to\n * the raw pool — BEGIN/COMMIT on it still hit the same backing connection.\n *\n * Concurrent `run()` calls against the same pool are serialized through a\n * JS-layer mutex so racing runners see each others' bookkeeping rows before\n * deciding to invoke `up()`. The unique constraint on `(component, version)`\n * remains a defense-in-depth check a 23505 from a separate process (or a\n * different pool instance backed by the same database) is still treated as\n * \"already applied\".\n */\nexport class PostgresMigrationRunner implements IMigrationRunner<Pool> {\n constructor(private readonly db: Pool) {}\n\n async ensureBookkeepingTable(): Promise<void> {\n await this.db.query(`\n CREATE TABLE IF NOT EXISTS ${MIGRATIONS_TABLE} (\n component TEXT NOT NULL,\n version INTEGER NOT NULL,\n description TEXT,\n applied_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),\n PRIMARY KEY (component, version)\n )\n `);\n }\n\n async appliedVersions(component: string): Promise<Set<number>> {\n const result = await this.db.query<{ version: number }, [string]>(\n `SELECT version FROM ${MIGRATIONS_TABLE} WHERE component = $1`,\n [component]\n );\n return new Set(result.rows.map((r) => Number(r.version)));\n }\n\n /**\n * Acquires a transaction-scoped queryable. Returns the raw pool when the\n * underlying driver doesn't expose `connect()` (PGlite); the `release()`\n * callback is then a no-op.\n */\n private async acquireClient(): Promise<{ client: PgQueryable; release: () => void }> {\n const pool = this.db as ConnectablePool;\n if (typeof pool.connect === \"function\") {\n const client = await pool.connect();\n return { client, release: () => client.release() };\n }\n return { client: this.db as unknown as PgQueryable, release: () => undefined };\n }\n\n async run(\n migrations: ReadonlyArray<IMigration<Pool>>,\n options: RunMigrationsOptions = {}\n ): Promise<ReadonlyArray<IMigration<Pool>>> {\n const key = this.db as unknown as object;\n const prev = runLocks.get(key) ?? Promise.resolve();\n const result = prev.then(() => this.runInternal(migrations, options));\n runLocks.set(\n key,\n result.catch(() => undefined)\n );\n return result;\n }\n\n private async runInternal(\n migrations: ReadonlyArray<IMigration<Pool>>,\n options: RunMigrationsOptions\n ): Promise<ReadonlyArray<IMigration<Pool>>> {\n await this.ensureBookkeepingTable();\n const sorted = sortMigrations(migrations);\n const applied: IMigration<Pool>[] = [];\n const cache = new Map<string, Set<number>>();\n const onProgress = options.onProgress;\n\n for (const m of sorted) {\n let seen = cache.get(m.component);\n if (!seen) {\n seen = await this.appliedVersions(m.component);\n cache.set(m.component, seen);\n }\n if (seen.has(m.version)) continue;\n\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"starting\",\n description: m.description,\n });\n\n const { client, release } = await this.acquireClient();\n try {\n await client.query(\"BEGIN\");\n // Migrations are written against the `Pool` type but only need a\n // queryable surface. Casting keeps the public signature stable while\n // routing the migration's queries through the dedicated client.\n await m.up(client as unknown as Pool, (fraction) => {\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"running\",\n description: m.description,\n fraction,\n });\n });\n await client.query(\n `INSERT INTO ${MIGRATIONS_TABLE}(component, version, description) VALUES ($1, $2, $3)`,\n [m.component, m.version, m.description ?? null]\n );\n await client.query(\"COMMIT\");\n seen.add(m.version);\n applied.push(m);\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"completed\",\n description: m.description,\n fraction: 1,\n });\n } catch (err: unknown) {\n await client.query(\"ROLLBACK\").catch(() => undefined);\n // Concurrent runner already inserted — treat as success.\n if ((err as { code?: string })?.code === \"23505\") {\n seen.add(m.version);\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"completed\",\n description: m.description,\n fraction: 1,\n });\n continue;\n }\n onProgress?.({\n component: m.component,\n version: m.version,\n phase: \"failed\",\n description: m.description,\n error: err,\n });\n throw err;\n } finally {\n release();\n }\n }\n\n return applied;\n }\n}\n",
7
7
  "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Pool } from \"../storage/_postgres/node-bun\";\nimport { JobStatus, type PrefixColumn } from \"@workglow/job-queue\";\nimport {\n buildPrefixColumnsSql,\n getPrefixIndexPrefix,\n getPrefixIndexSuffix,\n type IMigration,\n PostgresDialect,\n} from \"@workglow/storage\";\n\n/**\n * Frozen v1 set of `job_status` enum values, captured at migration creation\n * time. Migration bodies are historical artifacts and MUST NOT read the\n * mutable {@link JobStatus} const directly: a fresh DB created after a value\n * is added to the const would receive the new value, while a DB already at v1\n * would not — silently producing version-skewed enums and runtime errors on\n * insert. Adding a status requires a NEW migration that runs\n * `ALTER TYPE job_status ADD VALUE IF NOT EXISTS '...'`.\n */\nconst JOB_STATUS_V1: readonly string[] = [\n \"PENDING\",\n \"PROCESSING\",\n \"COMPLETED\",\n \"ABORTING\",\n \"FAILED\",\n \"DISABLED\",\n];\n\n/**\n * Sanity check: if a developer adds a status to {@link JobStatus} without\n * also writing a follow-up migration that ALTER TYPE-adds it, queries that\n * insert the new status will fail at runtime against any DB still on v1.\n *\n * Run lazily from {@link postgresQueueMigrations} (NOT at module import) so\n * that consumers re-exporting this module via barrel files don't crash on\n * import when they have no intention of running migrations.\n */\nfunction assertJobStatusMatchesV1(): void {\n const current = new Set(Object.values(JobStatus));\n for (const v of JOB_STATUS_V1) {\n if (!current.has(v as JobStatus)) {\n throw new Error(\n `JobStatus const is missing v1 enum value \"${v}\"; v1 migration values are frozen.`\n );\n }\n }\n for (const v of current) {\n if (!JOB_STATUS_V1.includes(v)) {\n throw new Error(\n `JobStatus contains \"${v}\" which is not in JOB_STATUS_V1. ` +\n `Add a new migration that runs \"ALTER TYPE job_status ADD VALUE IF NOT EXISTS '${v}'\" ` +\n `instead of mutating the v1 enum literal.`\n );\n }\n }\n}\n\n/**\n * Initial migration set for the Postgres queue table identified by `tableName`.\n *\n * Component name is `queue:postgres:<tableName>` so two queues with different\n * table names get tracked independently in `_storage_migrations`. The v1\n * payload covers schema + indexes + LISTEN/NOTIFY plumbing; the trigger is\n * idempotent (`CREATE OR REPLACE FUNCTION` + `DROP TRIGGER IF EXISTS`).\n */\nexport function postgresQueueMigrations(\n tableName: string,\n prefixes: readonly PrefixColumn[]\n): IMigration<Pool>[] {\n assertJobStatusMatchesV1();\n const component = `queue:postgres:${tableName}`;\n const prefixColumnsSql = buildPrefixColumnsSql(PostgresDialect, prefixes);\n const prefixIndexPrefix = getPrefixIndexPrefix(prefixes);\n const indexSuffix = getPrefixIndexSuffix(prefixes);\n\n return [\n {\n component,\n version: 1,\n description: \"Create job_status enum + queue table + indexes + notify trigger\",\n async up(db: Pool) {\n // Enum literal is the frozen v1 set, NOT Object.values(JobStatus).\n // See JOB_STATUS_V1 for why.\n const enumLiteral = JOB_STATUS_V1.map((v) => `'${v}'`).join(\",\");\n // DO block so the existence check + CREATE TYPE happen in one\n // statement. A bare `CREATE TYPE ...` raising duplicate_object inside\n // a transaction would leave it aborted (Postgres state 25P02), and\n // the runner's BEGIN/COMMIT would reject every subsequent statement.\n await db.query(`\n DO $$\n BEGIN\n IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'job_status') THEN\n CREATE TYPE job_status AS ENUM (${enumLiteral});\n END IF;\n END $$;\n `);\n\n await db.query(`\n CREATE TABLE IF NOT EXISTS ${tableName} (\n id SERIAL NOT NULL,\n ${prefixColumnsSql}fingerprint text NOT NULL,\n queue text NOT NULL,\n job_run_id text NOT NULL,\n status job_status NOT NULL default 'PENDING',\n input jsonb NOT NULL,\n output jsonb,\n run_attempts integer default 0,\n max_retries integer default 20,\n run_after timestamp with time zone DEFAULT now(),\n last_ran_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now(),\n deadline_at timestamp with time zone,\n completed_at timestamp with time zone,\n error text,\n error_code text,\n progress real DEFAULT 0,\n progress_message text DEFAULT '',\n progress_details jsonb,\n worker_id text\n )\n `);\n\n await db.query(`\n CREATE INDEX IF NOT EXISTS job_fetcher${indexSuffix}_idx\n ON ${tableName} (${prefixIndexPrefix}id, status, run_after)\n `);\n await db.query(`\n CREATE INDEX IF NOT EXISTS job_queue_fetcher${indexSuffix}_idx\n ON ${tableName} (${prefixIndexPrefix}queue, status, run_after)\n `);\n await db.query(`\n CREATE INDEX IF NOT EXISTS jobs_fingerprint${indexSuffix}_unique_idx\n ON ${tableName} (${prefixIndexPrefix}queue, fingerprint, status)\n `);\n\n // Install LISTEN/NOTIFY plumbing so subscribers can wake on\n // INSERT/UPDATE without polling. Best-effort: in-process\n // Postgres-compatible engines like PGLite may not implement pg_notify\n // or plpgsql. Skip trigger installation in that case — the queue's\n // subscribeToChanges throws synchronously for those engines anyway.\n //\n // Wrapped in a SAVEPOINT because this migration runs inside the\n // runner's BEGIN/COMMIT. Without the savepoint, any error in the\n // trigger DDL would put the outer transaction into aborted state\n // (Postgres 25P02), poisoning the runner's bookkeeping INSERT and\n // failing the whole migration — even though the trigger itself is\n // optional. ROLLBACK TO SAVEPOINT lets us discard just the failed\n // trigger work and keep the rest of the migration committable.\n const fnName = `${tableName}_notify`;\n const trgName = `${tableName}_notify_trg`;\n await db.query(\"SAVEPOINT install_notify_trigger\");\n try {\n await db.query(`\n CREATE OR REPLACE FUNCTION ${fnName}() RETURNS trigger AS $fn$\n DECLARE\n channel TEXT := 'wglw_q_' || md5('${tableName}' || COALESCE(NEW.queue, OLD.queue));\n payload TEXT;\n BEGIN\n payload := json_build_object(\n 'op', TG_OP,\n 'id', COALESCE(NEW.id, OLD.id),\n 'queue', COALESCE(NEW.queue, OLD.queue),\n 'status', COALESCE(NEW.status::text, OLD.status::text)\n )::text;\n PERFORM pg_notify(channel, payload);\n RETURN NULL;\n END;\n $fn$ LANGUAGE plpgsql;\n `);\n await db.query(`DROP TRIGGER IF EXISTS ${trgName} ON ${tableName}`);\n await db.query(`\n CREATE TRIGGER ${trgName}\n AFTER INSERT OR UPDATE ON ${tableName}\n FOR EACH ROW EXECUTE FUNCTION ${fnName}();\n `);\n await db.query(\"RELEASE SAVEPOINT install_notify_trigger\");\n } catch {\n // Engine doesn't support LISTEN/NOTIFY; rewind to the savepoint so\n // the outer transaction stays usable, and let subscribers fall\n // back to polling.\n await db.query(\"ROLLBACK TO SAVEPOINT install_notify_trigger\").catch(() => undefined);\n await db.query(\"RELEASE SAVEPOINT install_notify_trigger\").catch(() => undefined);\n }\n },\n },\n ];\n}\n",
8
8
  "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { createServiceToken } from \"@workglow/util\";\nimport type { Pool } from \"@workglow/postgres/storage\";\nimport type { PrefixColumn } from \"@workglow/job-queue\";\nimport type {\n IRateLimiterStorage,\n RateLimiterStorageOptions,\n RateLimiterStorageScope,\n} from \"@workglow/job-queue\";\nimport {\n assertPrefixesSafe,\n buildPrefixWhereClause,\n getPrefixColumnNames,\n getPrefixParamValues,\n PostgresDialect,\n} from \"@workglow/storage\";\nimport { PostgresMigrationRunner } from \"../migrations/PostgresMigrationRunner\";\nimport { postgresRateLimiterMigrations } from \"../migrations/postgresRateLimiterMigrations\";\n\nexport const POSTGRES_RATE_LIMITER_STORAGE = createServiceToken<IRateLimiterStorage>(\n \"ratelimiter.storage.postgres\"\n);\n\n/**\n * PostgreSQL implementation of rate limiter storage.\n * Manages execution records and next available times for rate limiting.\n */\nexport class PostgresRateLimiterStorage implements IRateLimiterStorage {\n public readonly scope: RateLimiterStorageScope = \"cluster\";\n /** The prefix column definitions */\n protected readonly prefixes: readonly PrefixColumn[];\n /** The prefix values for filtering */\n protected readonly prefixValues: Readonly<Record<string, string | number>>;\n /** The table name for execution tracking */\n protected readonly executionTableName: string;\n /** The table name for next available times */\n protected readonly nextAvailableTableName: string;\n\n constructor(\n protected readonly db: Pool,\n options?: RateLimiterStorageOptions\n ) {\n this.prefixes = options?.prefixes ?? [];\n this.prefixValues = options?.prefixValues ?? {};\n // Validate prefix column names before deriving table names from them.\n assertPrefixesSafe(this.prefixes);\n\n // Generate table names based on prefix configuration\n if (this.prefixes.length > 0) {\n const prefixNames = this.prefixes.map((p) => p.name).join(\"_\");\n this.executionTableName = `rate_limit_executions_${prefixNames}`;\n this.nextAvailableTableName = `rate_limit_next_available_${prefixNames}`;\n } else {\n this.executionTableName = \"rate_limit_executions\";\n this.nextAvailableTableName = \"rate_limit_next_available\";\n }\n }\n\n /** WHERE-clause helper specialized for the Postgres dialect. */\n private buildPrefixWhereClause(startParam: number) {\n return buildPrefixWhereClause(PostgresDialect, this.prefixes, this.prefixValues, startParam);\n }\n\n /** Returns prefix values in column order. */\n private getPrefixParamValues(): Array<string | number> {\n return getPrefixParamValues(this.prefixes, this.prefixValues);\n }\n\n /**\n * Returns the versioned migrations that this storage's tables depend on.\n * Callers can compose them with other storages' migrations under a shared\n * {@link PostgresMigrationRunner}; otherwise call {@link migrate}.\n */\n public getMigrations() {\n return postgresRateLimiterMigrations(\n this.executionTableName,\n this.nextAvailableTableName,\n this.prefixes\n );\n }\n\n /** Applies any pending migrations for this rate limiter's tables. */\n public async migrate(): Promise<void> {\n await new PostgresMigrationRunner(this.db).run(this.getMigrations());\n }\n\n public async tryReserveExecution(\n queueName: string,\n maxExecutions: number,\n windowMs: number\n ): Promise<unknown | null> {\n const prefixColumnNames = getPrefixColumnNames(this.prefixes);\n const prefixParamValues = this.getPrefixParamValues();\n const prefixCount = prefixColumnNames.length;\n\n // Parameter layout:\n // $1..$N prefix values (used in lock-key, count, next-available, and INSERT)\n // $(N+1) queueName\n // $(N+2) windowStart timestamp\n // $(N+3) maxExecutions\n const queueParam = `$${prefixCount + 1}`;\n const windowStartParam = `$${prefixCount + 2}`;\n\n // For the advisory lock we hash table-name + prefix values + queue-name into a bigint.\n // Use hashtextextended which returns int8 (advisory_xact_lock takes bigint).\n const lockKeyParts: string[] = [`'${this.executionTableName}'`];\n for (let i = 0; i < prefixCount; i++) {\n lockKeyParts.push(`$${i + 1}::text`);\n }\n lockKeyParts.push(`${queueParam}::text`);\n const lockKeyExpr = `hashtextextended(${lockKeyParts.join(\" || '|' || \")}, 0)`;\n\n const prefixWhere =\n prefixCount > 0\n ? \" AND \" + prefixColumnNames.map((p, i) => `${p} = $${i + 1}`).join(\" AND \")\n : \"\";\n\n const prefixInsertCols = prefixCount > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixInsertPlaceholders =\n prefixCount > 0 ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \" : \"\";\n\n const windowStart = new Date(Date.now() - windowMs).toISOString();\n\n // Use a dedicated client when the pool supports connect() (real pg.Pool)\n // — the advisory xact lock + transaction MUST run on the same connection\n // for atomicity. Without connect(), only known single-connection wrappers\n // (PGLitePool, raw PGlite) are safe, since they implicitly serialize all\n // queries through one underlying connection. Anything else (e.g. a custom\n // multi-connection adapter without connect()) would dispatch the lock and\n // the INSERT to different sessions, defeating the lock entirely.\n const supportsConnect =\n typeof (this.db as unknown as { connect?: unknown }).connect === \"function\";\n if (!supportsConnect) {\n // Without connect() we run BEGIN/advisory_lock/INSERT/COMMIT directly on\n // `db.query`. That's only safe if `db` is a single-connection wrapper\n // (every query goes through the same underlying session). Recognize:\n // - PGLitePool — our own wrapper class; constructor name preserved.\n // - PGlite — third-party, ships minified so `constructor.name`\n // can be obfuscated (observed: \"q\"). Detect via duck-typing on\n // methods PGlite uniquely exposes (`waitReady` Promise + `exec`).\n // Any other no-connect() pool would dispatch the lock and the INSERT\n // to potentially different sessions, breaking atomicity.\n const dbAny = this.db as unknown as {\n waitReady?: unknown;\n exec?: unknown;\n constructor?: { name?: string };\n };\n const ctorName = dbAny.constructor?.name;\n const looksLikePGlite = typeof dbAny.exec === \"function\" && dbAny.waitReady !== undefined;\n const looksLikePGLitePool = ctorName === \"PGLitePool\";\n if (!looksLikePGlite && !looksLikePGLitePool) {\n throw new Error(\n `PostgresRateLimiterStorage.tryReserveExecution requires a pg.Pool with connect() or a known single-connection wrapper (PGLitePool, PGlite); got ${ctorName ?? typeof this.db}. A multi-connection pool without connect() would dispatch the advisory lock and the INSERT to different sessions, breaking atomicity.`\n );\n }\n }\n const conn = supportsConnect\n ? await (\n this.db as unknown as {\n connect: () => Promise<{\n query: Pool[\"query\"];\n release: () => void;\n }>;\n }\n ).connect()\n : { query: this.db.query.bind(this.db), release: () => {} };\n\n try {\n await conn.query(\"BEGIN\");\n try {\n await conn.query(`SELECT pg_advisory_xact_lock(${lockKeyExpr})`, [\n ...prefixParamValues,\n queueName,\n ]);\n\n const countResult = await conn.query(\n `\n SELECT COUNT(*)::int AS n\n FROM ${this.executionTableName}\n WHERE queue_name = ${queueParam} AND executed_at > ${windowStartParam}${prefixWhere}\n `,\n [...prefixParamValues, queueName, windowStart]\n );\n const n: number = countResult.rows[0]?.n ?? 0;\n if (n >= maxExecutions) {\n await conn.query(\"COMMIT\");\n return null;\n }\n\n const naResult = await conn.query(\n `\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = ${queueParam}${prefixWhere}\n `,\n [...prefixParamValues, queueName]\n );\n const nextAvailableAt: Date | null = naResult.rows[0]?.next_available_at ?? null;\n if (nextAvailableAt && new Date(nextAvailableAt).getTime() > Date.now()) {\n await conn.query(\"COMMIT\");\n return null;\n }\n\n const insertResult = await conn.query(\n `\n INSERT INTO ${this.executionTableName} (${prefixInsertCols}queue_name)\n VALUES (${prefixInsertPlaceholders}${queueParam})\n RETURNING id\n `,\n [...prefixParamValues, queueName]\n );\n await conn.query(\"COMMIT\");\n return insertResult.rows[0]?.id ?? null;\n } catch (err) {\n try {\n await conn.query(\"ROLLBACK\");\n } catch {\n // best-effort\n }\n throw err;\n }\n } finally {\n conn.release();\n }\n }\n\n public async releaseExecution(queueName: string, token: unknown): Promise<void> {\n if (token === null || token === undefined) return;\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n // Delete by id — NEVER by recency. Two concurrent acquirers can hold\n // tokens for different rows; deleting \"the most recent\" would release the\n // other worker's slot.\n await this.db.query(\n `DELETE FROM ${this.executionTableName} WHERE id = $1 AND queue_name = $2${prefixConditions}`,\n [token as string | number, queueName, ...prefixParams]\n );\n }\n\n public async recordExecution(queueName: string): Promise<void> {\n const prefixColumnNames = getPrefixColumnNames(this.prefixes);\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \"\n : \"\";\n const queueParamNum = prefixColumnNames.length + 1;\n\n await this.db.query(\n `\n INSERT INTO ${this.executionTableName} (${prefixColumnsInsert}queue_name)\n VALUES (${prefixParamPlaceholders}$${queueParamNum})\n `,\n [...prefixParamValues, queueName]\n );\n }\n\n public async getExecutionCount(queueName: string, windowStartTime: string): Promise<number> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n\n const result = await this.db.query(\n `\n SELECT COUNT(*) AS count\n FROM ${this.executionTableName}\n WHERE queue_name = $1 AND executed_at > $2${prefixConditions}\n `,\n [queueName, windowStartTime, ...prefixParams]\n );\n\n return parseInt(result.rows[0]?.count ?? \"0\", 10);\n }\n\n public async getOldestExecutionAtOffset(\n queueName: string,\n offset: number\n ): Promise<string | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(3);\n\n const result = await this.db.query(\n `\n SELECT executed_at\n FROM ${this.executionTableName}\n WHERE queue_name = $1${prefixConditions}\n ORDER BY executed_at ASC\n LIMIT 1 OFFSET $2\n `,\n [queueName, offset, ...prefixParams]\n );\n\n const executedAt = result.rows[0]?.executed_at;\n if (!executedAt) return undefined;\n return new Date(executedAt).toISOString();\n }\n\n public async getNextAvailableTime(queueName: string): Promise<string | undefined> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n\n const result = await this.db.query(\n `\n SELECT next_available_at\n FROM ${this.nextAvailableTableName}\n WHERE queue_name = $1${prefixConditions}\n `,\n [queueName, ...prefixParams]\n );\n\n const nextAvailableAt = result.rows[0]?.next_available_at;\n if (!nextAvailableAt) return undefined;\n return new Date(nextAvailableAt).toISOString();\n }\n\n public async setNextAvailableTime(queueName: string, nextAvailableAt: string): Promise<void> {\n const prefixColumnNames = getPrefixColumnNames(this.prefixes);\n const prefixColumnsInsert =\n prefixColumnNames.length > 0 ? prefixColumnNames.join(\", \") + \", \" : \"\";\n const prefixParamValues = this.getPrefixParamValues();\n const prefixParamPlaceholders =\n prefixColumnNames.length > 0\n ? prefixColumnNames.map((_, i) => `$${i + 1}`).join(\", \") + \", \"\n : \"\";\n const baseParamStart = prefixColumnNames.length + 1;\n\n // Build the conflict columns for upsert\n const conflictColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n await this.db.query(\n `\n INSERT INTO ${this.nextAvailableTableName} (${prefixColumnsInsert}queue_name, next_available_at)\n VALUES (${prefixParamPlaceholders}$${baseParamStart}, $${baseParamStart + 1})\n ON CONFLICT (${conflictColumns})\n DO UPDATE SET next_available_at = EXCLUDED.next_available_at\n `,\n [...prefixParamValues, queueName, nextAvailableAt]\n );\n }\n\n public async clear(queueName: string): Promise<void> {\n const { conditions: prefixConditions, params: prefixParams } = this.buildPrefixWhereClause(2);\n\n await this.db.query(\n `DELETE FROM ${this.executionTableName} WHERE queue_name = $1${prefixConditions}`,\n [queueName, ...prefixParams]\n );\n await this.db.query(\n `DELETE FROM ${this.nextAvailableTableName} WHERE queue_name = $1${prefixConditions}`,\n [queueName, ...prefixParams]\n );\n }\n}\n",
9
9
  "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Pool } from \"../storage/_postgres/node-bun\";\nimport type { PrefixColumn } from \"@workglow/job-queue\";\nimport {\n buildPrefixColumnsSql,\n getPrefixColumnNames,\n getPrefixIndexPrefix,\n getPrefixIndexSuffix,\n type IMigration,\n PostgresDialect,\n} from \"@workglow/storage\";\n\n/** Initial migration set for the Postgres rate-limiter tables. */\nexport function postgresRateLimiterMigrations(\n executionTableName: string,\n nextAvailableTableName: string,\n prefixes: readonly PrefixColumn[]\n): IMigration<Pool>[] {\n const component = `rate-limiter:postgres:${executionTableName}`;\n const prefixColumnsSql = buildPrefixColumnsSql(PostgresDialect, prefixes);\n const prefixColumnNames = getPrefixColumnNames(prefixes);\n const prefixIndexPrefix = getPrefixIndexPrefix(prefixes);\n const indexSuffix = getPrefixIndexSuffix(prefixes);\n const primaryKeyColumns =\n prefixColumnNames.length > 0 ? `${prefixColumnNames.join(\", \")}, queue_name` : \"queue_name\";\n\n return [\n {\n component,\n version: 1,\n description: \"Create rate-limiter execution + next_available tables\",\n async up(db: Pool) {\n await db.query(`\n CREATE TABLE IF NOT EXISTS ${executionTableName} (\n id SERIAL PRIMARY KEY,\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n )\n `);\n await db.query(`\n CREATE INDEX IF NOT EXISTS rate_limit_exec_queue${indexSuffix}_idx\n ON ${executionTableName} (${prefixIndexPrefix}queue_name, executed_at)\n `);\n await db.query(`\n CREATE TABLE IF NOT EXISTS ${nextAvailableTableName} (\n ${prefixColumnsSql}queue_name TEXT NOT NULL,\n next_available_at TIMESTAMP WITH TIME ZONE,\n PRIMARY KEY (${primaryKeyColumns})\n )\n `);\n },\n },\n ];\n}\n"
10
10
  ],
11
- "mappings": ";AAMA;AAEA;AACA,sBAAS;AAST;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAME;AAAA;;;ACjBF;AAAA;AAAA;AAAA;AAAA;AA8CO,MAAM,wBAA0D;AAAA,EACxC;AAAA,EAA7B,WAAW,CAAkB,IAAU;AAAA,IAAV;AAAA;AAAA,OAEvB,uBAAsB,GAAkB;AAAA,IAC5C,MAAM,KAAK,GAAG,MAAM;AAAA,mCACW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAO9B;AAAA;AAAA,OAGG,gBAAe,CAAC,WAAyC;AAAA,IAC7D,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B,uBAAuB,yCACvB,CAAC,SAAS,CACZ;AAAA,IACA,OAAO,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA;AAAA,OAQ5C,cAAa,GAA0D;AAAA,IACnF,MAAM,OAAO,KAAK;AAAA,IAClB,IAAI,OAAO,KAAK,YAAY,YAAY;AAAA,MACtC,MAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAClC,OAAO,EAAE,QAAQ,SAAS,MAAM,OAAO,QAAQ,EAAE;AAAA,IACnD;AAAA,IACA,OAAO,EAAE,QAAQ,KAAK,IAA8B,SAAS,MAAG;AAAA,MAAG;AAAA,MAAU;AAAA;AAAA,OAGzE,IAAG,CACP,YACA,UAAgC,CAAC,GACS;AAAA,IAC1C,MAAM,KAAK,uBAAuB;AAAA,IAClC,MAAM,SAAS,eAAe,UAAU;AAAA,IACxC,MAAM,UAA8B,CAAC;AAAA,IACrC,MAAM,QAAQ,IAAI;AAAA,IAClB,MAAM,aAAa,QAAQ;AAAA,IAE3B,WAAW,KAAK,QAAQ;AAAA,MACtB,IAAI,OAAO,MAAM,IAAI,EAAE,SAAS;AAAA,MAChC,IAAI,CAAC,MAAM;AAAA,QACT,OAAO,MAAM,KAAK,gBAAgB,EAAE,SAAS;AAAA,QAC7C,MAAM,IAAI,EAAE,WAAW,IAAI;AAAA,MAC7B;AAAA,MACA,IAAI,KAAK,IAAI,EAAE,OAAO;AAAA,QAAG;AAAA,MAEzB,aAAa;AAAA,QACX,WAAW,EAAE;AAAA,QACb,SAAS,EAAE;AAAA,QACX,OAAO;AAAA,QACP,aAAa,EAAE;AAAA,MACjB,CAAC;AAAA,MAED,QAAQ,QAAQ,YAAY,MAAM,KAAK,cAAc;AAAA,MACrD,IAAI;AAAA,QACF,MAAM,OAAO,MAAM,OAAO;AAAA,QAI1B,MAAM,EAAE,GAAG,QAA2B,CAAC,aAAa;AAAA,UAClD,aAAa;AAAA,YACX,WAAW,EAAE;AAAA,YACb,SAAS,EAAE;AAAA,YACX,OAAO;AAAA,YACP,aAAa,EAAE;AAAA,YACf;AAAA,UACF,CAAC;AAAA,SACF;AAAA,QACD,MAAM,OAAO,MACX,eAAe,yEACf,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,IAAI,CAChD;AAAA,QACA,MAAM,OAAO,MAAM,QAAQ;AAAA,QAC3B,KAAK,IAAI,EAAE,OAAO;AAAA,QAClB,QAAQ,KAAK,CAAC;AAAA,QACd,aAAa;AAAA,UACX,WAAW,EAAE;AAAA,UACb,SAAS,EAAE;AAAA,UACX,OAAO;AAAA,UACP,aAAa,EAAE;AAAA,UACf,UAAU;AAAA,QACZ,CAAC;AAAA,QACD,OAAO,KAAc;AAAA,QACrB,MAAM,OAAO,MAAM,UAAU,EAAE,MAAM,MAAG;AAAA,UAAG;AAAA,SAAS;AAAA,QAEpD,IAAK,KAA2B,SAAS,SAAS;AAAA,UAChD,KAAK,IAAI,EAAE,OAAO;AAAA,UAClB,aAAa;AAAA,YACX,WAAW,EAAE;AAAA,YACb,SAAS,EAAE;AAAA,YACX,OAAO;AAAA,YACP,aAAa,EAAE;AAAA,YACf,UAAU;AAAA,UACZ,CAAC;AAAA,UACD;AAAA,QACF;AAAA,QACA,aAAa;AAAA,UACX,WAAW,EAAE;AAAA,UACb,SAAS,EAAE;AAAA,UACX,OAAO;AAAA,UACP,aAAa,EAAE;AAAA,UACf,OAAO;AAAA,QACT,CAAC;AAAA,QACD,MAAM;AAAA,gBACN;AAAA,QACA,QAAQ;AAAA;AAAA,IAEZ;AAAA,IAEA,OAAO;AAAA;AAEX;;;ACtKA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,IAAM,gBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAWA,SAAS,wBAAwB,GAAS;AAAA,EACxC,MAAM,UAAU,IAAI,IAAI,OAAO,OAAO,SAAS,CAAC;AAAA,EAChD,WAAW,KAAK,eAAe;AAAA,IAC7B,IAAI,CAAC,QAAQ,IAAI,CAAc,GAAG;AAAA,MAChC,MAAM,IAAI,MACR,6CAA6C,qCAC/C;AAAA,IACF;AAAA,EACF;AAAA,EACA,WAAW,KAAK,SAAS;AAAA,IACvB,IAAI,CAAC,cAAc,SAAS,CAAC,GAAG;AAAA,MAC9B,MAAM,IAAI,MACR,uBAAuB,uCACrB,iFAAiF,SACjF,0CACJ;AAAA,IACF;AAAA,EACF;AAAA;AAWK,SAAS,uBAAuB,CACrC,WACA,UACoB;AAAA,EACpB,yBAAyB;AAAA,EACzB,MAAM,YAAY,kBAAkB;AAAA,EACpC,MAAM,mBAAmB,sBAAsB,iBAAiB,QAAQ;AAAA,EACxE,MAAM,oBAAoB,qBAAqB,QAAQ;AAAA,EACvD,MAAM,cAAc,qBAAqB,QAAQ;AAAA,EAEjD,OAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,SAAS;AAAA,MACT,aAAa;AAAA,WACP,GAAE,CAAC,IAAU;AAAA,QAGjB,MAAM,cAAc,cAAc,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,KAAK,GAAG;AAAA,QAK/D,MAAM,GAAG,MAAM;AAAA;AAAA;AAAA;AAAA,gDAIyB;AAAA;AAAA;AAAA,SAGvC;AAAA,QAED,MAAM,GAAG,MAAM;AAAA,uCACgB;AAAA;AAAA,cAEzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAoBL;AAAA,QAED,MAAM,GAAG,MAAM;AAAA,kDAC2B;AAAA,iBACjC,cAAc;AAAA,SACtB;AAAA,QACD,MAAM,GAAG,MAAM;AAAA,wDACiC;AAAA,iBACvC,cAAc;AAAA,SACtB;AAAA,QACD,MAAM,GAAG,MAAM;AAAA,uDACgC;AAAA,iBACtC,cAAc;AAAA,SACtB;AAAA,QAeD,MAAM,SAAS,GAAG;AAAA,QAClB,MAAM,UAAU,GAAG;AAAA,QACnB,MAAM,GAAG,MAAM,kCAAkC;AAAA,QACjD,IAAI;AAAA,UACF,MAAM,GAAG,MAAM;AAAA,yCACgB;AAAA;AAAA,kDAES;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAavC;AAAA,UACD,MAAM,GAAG,MAAM,0BAA0B,cAAc,WAAW;AAAA,UAClE,MAAM,GAAG,MAAM;AAAA,6BACI;AAAA,0CACa;AAAA,8CACI;AAAA,WACnC;AAAA,UACD,MAAM,GAAG,MAAM,0CAA0C;AAAA,UACzD,MAAM;AAAA,UAIN,MAAM,GAAG,MAAM,8CAA8C,EAAE,MAAM,MAAG;AAAA,YAAG;AAAA,WAAS;AAAA,UACpF,MAAM,GAAG,MAAM,0CAA0C,EAAE,MAAM,MAAG;AAAA,YAAG;AAAA,WAAS;AAAA;AAAA;AAAA,IAGtF;AAAA,EACF;AAAA;;;AFlKK,IAAM,yBAAyB,mBACpC,2BACF;AAAA;AAiBO,MAAM,qBAA4E;AAAA,EAUlE;AAAA,EACA;AAAA,EAVL,QAAQ;AAAA,EAEL;AAAA,EAEA;AAAA,EAEA;AAAA,EAEnB,WAAW,CACU,IACA,WACnB,SACA;AAAA,IAHmB;AAAA,IACA;AAAA,IAGnB,KAAK,WAAW,SAAS,YAAY,CAAC;AAAA,IACtC,KAAK,eAAe,SAAS,gBAAgB,CAAC;AAAA,IAG9C,mBAAmB,KAAK,QAAQ;AAAA,IAGhC,IAAI,KAAK,SAAS,SAAS,GAAG;AAAA,MAC5B,MAAM,cAAc,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG;AAAA,MAC7D,KAAK,YAAY,aAAa;AAAA,IAChC,EAAO;AAAA,MACL,KAAK,YAAY;AAAA;AAAA;AAAA,EAKb,sBAAsB,CAAC,YAAoB;AAAA,IACjD,OAAO,uBAAuB,kBAAiB,KAAK,UAAU,KAAK,cAAc,UAAU;AAAA;AAAA,EAIrF,oBAAoB,GAA2B;AAAA,IACrD,OAAO,qBAAqB,KAAK,UAAU,KAAK,YAAY;AAAA;AAAA,EAQvD,aAAa,GAAG;AAAA,IACrB,OAAO,wBAAwB,KAAK,WAAW,KAAK,QAAQ;AAAA;AAAA,OAQjD,QAAO,GAAkB;AAAA,IACpC,MAAM,IAAI,wBAAwB,KAAK,EAAE,EAAE,IAAI,KAAK,cAAc,CAAC;AAAA;AAAA,EAO7D,iBAAiB,GAAW;AAAA,IAGlC,MAAM,gBAAgB,GAAG,KAAK,YAAY,KAAK;AAAA,IAC/C,MAAM,OAAO,WAAW,KAAK,EAAE,OAAO,aAAa,EAAE,OAAO,KAAK;AAAA,IACjE,OAAO,UAAU;AAAA;AAAA,OAQN,IAAG,CAAC,KAAwD;AAAA,IACvE,MAAM,MAAM,IAAI,KAAK,EAAE,YAAY;AAAA,IACnC,IAAI,QAAQ,KAAK;AAAA,IACjB,IAAI,aAAa,IAAI,cAAc,MAAM;AAAA,IACzC,IAAI,cAAc,MAAM,gBAAgB,IAAI,KAAK;AAAA,IACjD,IAAI,SAAS,WAAU;AAAA,IACvB,IAAI,WAAW;AAAA,IACf,IAAI,mBAAmB;AAAA,IACvB,IAAI,mBAAmB;AAAA,IACvB,IAAI,aAAa;AAAA,IACjB,IAAI,YAAY;AAAA,IAEhB,MAAM,oBAAoB,qBAAqB,KAAK,QAAQ;AAAA,IAC5D,QAAQ,SAAS,qBAAqB,cAAc,4BAClD,2BAA2B,kBAAiB,KAAK,UAAU,CAAC;AAAA,IAC9D,MAAM,oBAAoB,KAAK,qBAAqB;AAAA,IACpD,MAAM,iBAAiB,kBAAkB,SAAS;AAAA,IAElD,MAAM,MAAM;AAAA,oBACI,KAAK;AAAA,UACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAaC,2BAA2B,mBAAmB,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB,MAAM,iBAAiB;AAAA;AAAA,IAErR,MAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,KAAK,UAAU,IAAI,KAAK;AAAA,MACxB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI,mBAAmB,KAAK,UAAU,IAAI,gBAAgB,IAAI;AAAA,IAChE;AAAA,IACA,MAAM,SAAS,MAAM,KAAK,GAAG,MAAM,KAAK,MAAM;AAAA,IAE9C,IAAI,CAAC;AAAA,MAAQ,MAAM,IAAI,MAAM,wBAAwB;AAAA,IACrD,IAAI,KAAK,OAAO,KAAK,GAAG;AAAA,IACxB,OAAO,IAAI;AAAA;AAAA,OAQA,IAAG,CAAC,IAAmE;AAAA,IAClF,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA,eACS,KAAK;AAAA,sCACkB;AAAA;AAAA,kBAGhC,CAAC,IAAI,KAAK,WAAW,GAAG,YAAY,CACtC;AAAA,IAEA,IAAI,CAAC,UAAU,OAAO,KAAK,WAAW;AAAA,MAAG;AAAA,IACzC,OAAO,OAAO,KAAK;AAAA;AAAA,OAQR,KAAI,CACf,SAAoB,WAAU,SAC9B,MAAc,KACmC;AAAA,IACjD,MAAM,OAAO,GAAG,KAAK;AAAA,IACrB,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAI3B;AAAA;AAAA,eAES,KAAK;AAAA;AAAA,yBAEK;AAAA;AAAA;AAAA,iCAInB,CAAC,KAAK,WAAW,QAAQ,KAAK,GAAG,YAAY,CAC/C;AAAA,IACA,IAAI,CAAC;AAAA,MAAQ,OAAO,CAAC;AAAA,IACrB,OAAO,OAAO;AAAA;AAAA,OAQH,KAAI,CAAC,UAAwE;AAAA,IAExF,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAI3B;AAAA,eACS,KAAK;AAAA;AAAA;AAAA;AAAA,eAIL,KAAK;AAAA;AAAA;AAAA,UAGV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAOJ,CAAC,WAAU,YAAY,KAAK,WAAW,WAAU,SAAS,UAAU,GAAG,YAAY,CACrF;AAAA,IAEA,OAAO,QAAQ,OAAO,MAAM;AAAA;AAAA,OAQjB,KAAI,CAAC,SAAS,WAAU,SAA0B;AAAA,IAC7D,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA;AAAA,eAES,KAAK;AAAA;AAAA,yBAEK,oBACnB,CAAC,KAAK,WAAW,QAAQ,GAAG,YAAY,CAC1C;AAAA,IACA,IAAI,CAAC;AAAA,MAAQ,OAAO;AAAA,IACpB,OAAO,SAAS,OAAO,KAAK,GAAG,OAAO,EAAE;AAAA;AAAA,OAS7B,SAAQ,CAAC,YAA4D;AAAA,IAChF,MAAM,eAAe,KAAK,qBAAqB;AAAA,IAE/C,IAAI,WAAW,WAAW,WAAU,UAAU;AAAA,MAC5C,QAAQ,YAAY,qBAAqB,KAAK,uBAAuB,CAAC;AAAA,MACtE,MAAM,KAAK,GAAG,MACZ,UAAU,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wCAOiB,oBAChC,CAAC,WAAW,QAAQ,WAAW,IAAI,KAAK,WAAW,GAAG,YAAY,CACpE;AAAA,IACF,EAAO,SAAI,WAAW,WAAW,WAAU,SAAS;AAAA,MAClD,QAAQ,YAAY,qBAAqB,KAAK,uBAAuB,CAAC;AAAA,MACtE,MAAM,KAAK,GAAG,MACZ,UAAU,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wCAWiB,oBAChC;AAAA,QACE,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW;AAAA,QACX,KAAK;AAAA,QACL,GAAG;AAAA,MACL,CACF;AAAA,IACF,EAAO;AAAA,MACL,QAAQ,YAAY,qBAAqB,KAAK,uBAAuB,CAAC;AAAA,MACtE,MAAM,KAAK,GAAG,MACZ;AAAA,mBACW,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wCAYgB,oBAChC;AAAA,QACE,WAAW,SAAS,KAAK,UAAU,WAAW,MAAM,IAAI;AAAA,QACxD,WAAW,SAAS;AAAA,QACpB,WAAW,cAAc;AAAA,QACzB,WAAW;AAAA,QACX,WAAW;AAAA,QACX,KAAK;AAAA,QACL,GAAG;AAAA,MACL,CACF;AAAA;AAAA;AAAA,OAOS,UAAS,GAAkB;AAAA,IACtC,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,KAAK,GAAG,MACZ;AAAA,oBACc,KAAK;AAAA,0BACC,oBACpB,CAAC,KAAK,WAAW,GAAG,YAAY,CAClC;AAAA;AAAA,OAQW,eAAc,CAAC,OAAsC;AAAA,IAChE,MAAM,cAAc,MAAM,gBAAgB,KAAK;AAAA,IAC/C,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA;AAAA,eAES,KAAK;AAAA,wEACoD,oBAClE,CAAC,aAAa,KAAK,WAAW,GAAG,YAAY,CAC/C;AAAA,IACA,IAAI,CAAC,UAAU,OAAO,KAAK,WAAW;AAAA,MAAG,OAAO;AAAA,IAChD,OAAO,OAAO,KAAK,GAAG;AAAA;AAAA,OASX,MAAK,CAAC,OAA+B;AAAA,IAChD,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,KAAK,GAAG,MACZ;AAAA,eACS,KAAK;AAAA;AAAA,oCAEgB,oBAC9B,CAAC,OAAO,KAAK,WAAW,GAAG,YAAY,CACzC;AAAA;AAAA,OAOW,QAAO,CAAC,OAA+B;AAAA,IAClD,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,KAAK,GAAG,MACZ;AAAA,eACS,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAMkB,oBAChC,CAAC,OAAO,KAAK,WAAW,GAAG,YAAY,CACzC;AAAA;AAAA,OAQW,WAAU,CAAC,YAAqE;AAAA,IAC3F,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA,sBACgB,KAAK,iDAAiD,oBACtE,CAAC,YAAY,KAAK,WAAW,GAAG,YAAY,CAC9C;AAAA,IACA,IAAI,CAAC;AAAA,MAAQ,OAAO,CAAC;AAAA,IACrB,OAAO,OAAO;AAAA;AAAA,OAMH,aAAY,CACvB,OACA,UACA,SACA,SACe;AAAA,IACf,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,KAAK,GAAG,MACZ;AAAA,eACS,KAAK;AAAA;AAAA;AAAA;AAAA,oCAIgB,oBAC9B;AAAA,MACE;AAAA,MACA;AAAA,MACA,UAAU,KAAK,UAAU,OAAO,IAAI;AAAA,MACpC;AAAA,MACA,KAAK;AAAA,MACL,GAAG;AAAA,IACL,CACF;AAAA;AAAA,OAMW,OAAM,CAAC,OAA+B;AAAA,IACjD,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,KAAK,GAAG,MACZ,eAAe,KAAK,yCAAyC,oBAC7D,CAAC,OAAO,KAAK,WAAW,GAAG,YAAY,CACzC;AAAA;AAAA,OAQW,yBAAwB,CAAC,QAAmB,aAAoC;AAAA,IAC3F,MAAM,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,WAAW,EAAE,YAAY;AAAA,IAClE,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAC5F,MAAM,KAAK,GAAG,MACZ,eAAe,KAAK;AAAA;AAAA;AAAA;AAAA,+BAIK,oBACzB,CAAC,KAAK,WAAW,QAAQ,YAAY,GAAG,YAAY,CACtD;AAAA;AAAA,EAwBK,kBAAkB,CACvB,UACA,SACY;AAAA,IAEZ,MAAM,YAAY,KAAK;AAAA,IACvB,IAAI,OAAO,UAAU,YAAY,YAAY;AAAA,MAG3C,MAAM,IAAI,MACR,8FACF;AAAA,IACF;AAAA,IACA,MAAM,OAAO;AAAA,IAEb,MAAM,UAAU,KAAK,kBAAkB;AAAA,IAGvC,MAAM,wBACJ,SAAS,iBAAiB,YACtB,KAAK,SAAS,SAAS,IACrB,KAAK,eACL,OACF,OAAO,KAAK,QAAQ,YAAY,EAAE,WAAW,IAC3C,OACA,QAAQ;AAAA,IAEhB,IAAI,eAAe;AAAA,IACnB,IAAI,eAAoC;AAAA,IACxC,IAAI,iBAAuD;AAAA,IAC3D,IAAI,YAAY;AAAA,IAEhB,MAAM,WAAW,CAAC,WAAoD;AAAA,MACpE,IAAI;AAAA,QACF,SAAS,MAAM;AAAA,QACf,OAAO,KAAK;AAAA,QAEZ,UAAU,EAAE,MAAM,iDAAiD;AAAA,UACjE;AAAA,UACA,YAAY,OAAO;AAAA,UACnB,OAAO;AAAA,QACT,CAAC;AAAA;AAAA;AAAA,IAIL,MAAM,gBAAgB,CACpB,QACA,WACY;AAAA,MACZ,MAAM,MAAO,OAAO,OAAO,OAAO;AAAA,MAClC,IAAI,CAAC;AAAA,QAAK,OAAO;AAAA,MACjB,YAAY,GAAG,MAAM,OAAO,QAAQ,MAAM,GAAG;AAAA,QAC3C,IAAI,IAAI,OAAO;AAAA,UAAG,OAAO;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA;AAAA,IAQT,MAAM,UAAU,OAAO,OAAsE;AAAA,MAC3F,IAAI;AAAA,QACF,OAAO,MAAM,KAAK,IAAI,EAAE;AAAA,QACxB,MAAM;AAAA,QACN;AAAA;AAAA;AAAA,IAIJ,MAAM,qBAAqB,CAAC,QAAqD;AAAA,MAC/E,IAAI,IAAI,YAAY,WAAW,CAAC,IAAI;AAAA,QAAS;AAAA,MAC7C,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,QAC/B,MAAM;AAAA,QACN;AAAA;AAAA,OAEI,YAAY;AAAA,QAChB,MAAM,KAAK,OAAO;AAAA,QAClB,MAAM,WAAW;AAAA,UACf,IAAI,OAAO;AAAA,UACX,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO;AAAA,QACjB;AAAA,QACA,MAAM,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,OAAO,EAAE;AAAA,QACrE,MAAM,SAA4C;AAAA,UAChD,MAAM,OAAO,WAAW,WAAW,OAAO,WAAW,WAAW;AAAA,UAChE,KAAK,OAAO,WAAW,YAAa,WAAW;AAAA,UAC/C,KAAK,OAAO,WAAW,WAAW;AAAA,QACpC;AAAA,QACA,IAAI,yBAAyB,CAAC,cAAc,QAAQ,qBAAqB;AAAA,UAAG;AAAA,QAC5E,SAAS,MAAM;AAAA,SACd;AAAA;AAAA,IAGL,MAAM,UAAU,YAA2B;AAAA,MACzC,IAAI;AAAA,QAAc;AAAA,MAClB,IAAI;AAAA,QACF,MAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,QAClC,IAAI,cAAc;AAAA,UAChB,OAAO,QAAQ;AAAA,UACf;AAAA,QACF;AAAA,QACA,eAAe;AAAA,QACf,OAAO,GAAG,gBAAgB,kBAAkB;AAAA,QAC5C,OAAO,GAAG,SAAS,MAAM,kBAAkB,CAAC;AAAA,QAC5C,MAAM,OAAO,MAAM,UAAU,SAAS;AAAA,QACtC,YAAY;AAAA,QAIZ,SAAS,EAAE,MAAM,SAAS,CAAC;AAAA,QAC3B,MAAM;AAAA,QACN,kBAAkB;AAAA;AAAA;AAAA,IAItB,MAAM,oBAAoB,MAAY;AAAA,MACpC,IAAI,gBAAgB;AAAA,QAAgB;AAAA,MACpC,MAAM,IAAI;AAAA,MACV,eAAe;AAAA,MACf,IAAI;AAAA,QACF,GAAG,qBAAqB,cAAc;AAAA,QACtC,GAAG,qBAAqB,OAAO;AAAA,QAC/B,GAAG,QAAQ;AAAA,QACX,MAAM;AAAA,MAGR,MAAM,QAAQ,KAAK,IAAI,WAAW,KAAM;AAAA,MACxC,YAAY,KAAK,IAAI,YAAY,GAAG,KAAM;AAAA,MAC1C,iBAAiB,WAAW,MAAM;AAAA,QAChC,iBAAiB;AAAA,QACZ,QAAQ;AAAA,SACZ,KAAK;AAAA;AAAA,IAGL,QAAQ;AAAA,IAEb,OAAO,MAAM;AAAA,MACX,eAAe;AAAA,MACf,IAAI,gBAAgB;AAAA,QAClB,aAAa,cAAc;AAAA,QAC3B,iBAAiB;AAAA,MACnB;AAAA,MACA,MAAM,IAAI;AAAA,MACV,eAAe;AAAA,MACf,IAAI,GAAG;AAAA,QAEL,EAAE,MAAM,YAAY,SAAS,EAC1B,MAAM,MAAM,EAAE,EACd,QAAQ,MAAM;AAAA,UACb,IAAI;AAAA,YACF,EAAE,qBAAqB,cAAc;AAAA,YACrC,EAAE,qBAAqB,OAAO;AAAA,YAC9B,EAAE,QAAQ;AAAA,YACV,MAAM;AAAA,SAGT;AAAA,MACL;AAAA;AAAA;AAGN;;AGnqBA,+BAAS;AAQT;AAAA,wBACE;AAAA,4BACA;AAAA,0BACA;AAAA,0BACA;AAAA,qBACA;AAAA;;;ACXF;AAAA,2BACE;AAAA,0BACA;AAAA,0BACA;AAAA,0BACA;AAAA,qBAEA;AAAA;AAIK,SAAS,6BAA6B,CAC3C,oBACA,wBACA,UACoB;AAAA,EACpB,MAAM,YAAY,yBAAyB;AAAA,EAC3C,MAAM,mBAAmB,uBAAsB,kBAAiB,QAAQ;AAAA,EACxE,MAAM,oBAAoB,sBAAqB,QAAQ;AAAA,EACvD,MAAM,oBAAoB,sBAAqB,QAAQ;AAAA,EACvD,MAAM,cAAc,sBAAqB,QAAQ;AAAA,EACjD,MAAM,oBACJ,kBAAkB,SAAS,IAAI,GAAG,kBAAkB,KAAK,IAAI,kBAAkB;AAAA,EAEjF,OAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,SAAS;AAAA,MACT,aAAa;AAAA,WACP,GAAE,CAAC,IAAU;AAAA,QACjB,MAAM,GAAG,MAAM;AAAA,uCACgB;AAAA;AAAA,cAEzB;AAAA;AAAA;AAAA,SAGL;AAAA,QACD,MAAM,GAAG,MAAM;AAAA,4DACqC;AAAA,iBAC3C,uBAAuB;AAAA,SAC/B;AAAA,QACD,MAAM,GAAG,MAAM;AAAA,uCACgB;AAAA,cACzB;AAAA;AAAA,2BAEa;AAAA;AAAA,SAElB;AAAA;AAAA,IAEL;AAAA,EACF;AAAA;;;ADjCK,IAAM,gCAAgC,oBAC3C,8BACF;AAAA;AAMO,MAAM,2BAA0D;AAAA,EAYhD;AAAA,EAXL,QAAiC;AAAA,EAE9B;AAAA,EAEA;AAAA,EAEA;AAAA,EAEA;AAAA,EAEnB,WAAW,CACU,IACnB,SACA;AAAA,IAFmB;AAAA,IAGnB,KAAK,WAAW,SAAS,YAAY,CAAC;AAAA,IACtC,KAAK,eAAe,SAAS,gBAAgB,CAAC;AAAA,IAE9C,oBAAmB,KAAK,QAAQ;AAAA,IAGhC,IAAI,KAAK,SAAS,SAAS,GAAG;AAAA,MAC5B,MAAM,cAAc,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG;AAAA,MAC7D,KAAK,qBAAqB,yBAAyB;AAAA,MACnD,KAAK,yBAAyB,6BAA6B;AAAA,IAC7D,EAAO;AAAA,MACL,KAAK,qBAAqB;AAAA,MAC1B,KAAK,yBAAyB;AAAA;AAAA;AAAA,EAK1B,sBAAsB,CAAC,YAAoB;AAAA,IACjD,OAAO,wBAAuB,kBAAiB,KAAK,UAAU,KAAK,cAAc,UAAU;AAAA;AAAA,EAIrF,oBAAoB,GAA2B;AAAA,IACrD,OAAO,sBAAqB,KAAK,UAAU,KAAK,YAAY;AAAA;AAAA,EAQvD,aAAa,GAAG;AAAA,IACrB,OAAO,8BACL,KAAK,oBACL,KAAK,wBACL,KAAK,QACP;AAAA;AAAA,OAIW,QAAO,GAAkB;AAAA,IACpC,MAAM,IAAI,wBAAwB,KAAK,EAAE,EAAE,IAAI,KAAK,cAAc,CAAC;AAAA;AAAA,OAGxD,oBAAmB,CAC9B,WACA,eACA,UACyB;AAAA,IACzB,MAAM,oBAAoB,sBAAqB,KAAK,QAAQ;AAAA,IAC5D,MAAM,oBAAoB,KAAK,qBAAqB;AAAA,IACpD,MAAM,cAAc,kBAAkB;AAAA,IAOtC,MAAM,aAAa,IAAI,cAAc;AAAA,IACrC,MAAM,mBAAmB,IAAI,cAAc;AAAA,IAI3C,MAAM,eAAyB,CAAC,IAAI,KAAK,qBAAqB;AAAA,IAC9D,SAAS,IAAI,EAAG,IAAI,aAAa,KAAK;AAAA,MACpC,aAAa,KAAK,IAAI,IAAI,SAAS;AAAA,IACrC;AAAA,IACA,aAAa,KAAK,GAAG,kBAAkB;AAAA,IACvC,MAAM,cAAc,oBAAoB,aAAa,KAAK,aAAa;AAAA,IAEvE,MAAM,cACJ,cAAc,IACV,UAAU,kBAAkB,IAAI,CAAC,GAAG,MAAM,GAAG,QAAQ,IAAI,GAAG,EAAE,KAAK,OAAO,IAC1E;AAAA,IAEN,MAAM,mBAAmB,cAAc,IAAI,kBAAkB,KAAK,IAAI,IAAI,OAAO;AAAA,IACjF,MAAM,2BACJ,cAAc,IAAI,kBAAkB,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,EAAE,KAAK,IAAI,IAAI,OAAO;AAAA,IAErF,MAAM,cAAc,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,EAAE,YAAY;AAAA,IAShE,MAAM,kBACJ,OAAQ,KAAK,GAAwC,YAAY;AAAA,IACnE,IAAI,CAAC,iBAAiB;AAAA,MAUpB,MAAM,QAAQ,KAAK;AAAA,MAKnB,MAAM,WAAW,MAAM,aAAa;AAAA,MACpC,MAAM,kBAAkB,OAAO,MAAM,SAAS,cAAc,MAAM,cAAc;AAAA,MAChF,MAAM,sBAAsB,aAAa;AAAA,MACzC,IAAI,CAAC,mBAAmB,CAAC,qBAAqB;AAAA,QAC5C,MAAM,IAAI,MACR,mJAAmJ,YAAY,OAAO,KAAK,0IAC7K;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,OAAO,kBACT,MACE,KAAK,GAML,QAAQ,IACV,EAAE,OAAO,KAAK,GAAG,MAAM,KAAK,KAAK,EAAE,GAAG,SAAS,MAAM,GAAG;AAAA,IAE5D,IAAI;AAAA,MACF,MAAM,KAAK,MAAM,OAAO;AAAA,MACxB,IAAI;AAAA,QACF,MAAM,KAAK,MAAM,gCAAgC,gBAAgB;AAAA,UAC/D,GAAG;AAAA,UACH;AAAA,QACF,CAAC;AAAA,QAED,MAAM,cAAc,MAAM,KAAK,MAC7B;AAAA;AAAA,iBAEO,KAAK;AAAA,+BACS,gCAAgC,mBAAmB;AAAA,aAExE,CAAC,GAAG,mBAAmB,WAAW,WAAW,CAC/C;AAAA,QACA,MAAM,IAAY,YAAY,KAAK,IAAI,KAAK;AAAA,QAC5C,IAAI,KAAK,eAAe;AAAA,UACtB,MAAM,KAAK,MAAM,QAAQ;AAAA,UACzB,OAAO;AAAA,QACT;AAAA,QAEA,MAAM,WAAW,MAAM,KAAK,MAC1B;AAAA;AAAA,iBAEO,KAAK;AAAA,+BACS,aAAa;AAAA,aAElC,CAAC,GAAG,mBAAmB,SAAS,CAClC;AAAA,QACA,MAAM,kBAA+B,SAAS,KAAK,IAAI,qBAAqB;AAAA,QAC5E,IAAI,mBAAmB,IAAI,KAAK,eAAe,EAAE,QAAQ,IAAI,KAAK,IAAI,GAAG;AAAA,UACvE,MAAM,KAAK,MAAM,QAAQ;AAAA,UACzB,OAAO;AAAA,QACT;AAAA,QAEA,MAAM,eAAe,MAAM,KAAK,MAC9B;AAAA,wBACc,KAAK,uBAAuB;AAAA,oBAChC,2BAA2B;AAAA;AAAA,aAGrC,CAAC,GAAG,mBAAmB,SAAS,CAClC;AAAA,QACA,MAAM,KAAK,MAAM,QAAQ;AAAA,QACzB,OAAO,aAAa,KAAK,IAAI,MAAM;AAAA,QACnC,OAAO,KAAK;AAAA,QACZ,IAAI;AAAA,UACF,MAAM,KAAK,MAAM,UAAU;AAAA,UAC3B,MAAM;AAAA,QAGR,MAAM;AAAA;AAAA,cAER;AAAA,MACA,KAAK,QAAQ;AAAA;AAAA;AAAA,OAIJ,iBAAgB,CAAC,WAAmB,OAA+B;AAAA,IAC9E,IAAI,UAAU,QAAQ,UAAU;AAAA,MAAW;AAAA,IAC3C,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAI5F,MAAM,KAAK,GAAG,MACZ,eAAe,KAAK,uDAAuD,oBAC3E,CAAC,OAA0B,WAAW,GAAG,YAAY,CACvD;AAAA;AAAA,OAGW,gBAAe,CAAC,WAAkC;AAAA,IAC7D,MAAM,oBAAoB,sBAAqB,KAAK,QAAQ;AAAA,IAC5D,MAAM,sBACJ,kBAAkB,SAAS,IAAI,kBAAkB,KAAK,IAAI,IAAI,OAAO;AAAA,IACvE,MAAM,oBAAoB,KAAK,qBAAqB;AAAA,IACpD,MAAM,0BACJ,kBAAkB,SAAS,IACvB,kBAAkB,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,EAAE,KAAK,IAAI,IAAI,OAC1D;AAAA,IACN,MAAM,gBAAgB,kBAAkB,SAAS;AAAA,IAEjD,MAAM,KAAK,GAAG,MACZ;AAAA,oBACc,KAAK,uBAAuB;AAAA,gBAChC,2BAA2B;AAAA,OAErC,CAAC,GAAG,mBAAmB,SAAS,CAClC;AAAA;AAAA,OAGW,kBAAiB,CAAC,WAAmB,iBAA0C;AAAA,IAC1F,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAE5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA;AAAA,aAEO,KAAK;AAAA,kDACgC;AAAA,OAE5C,CAAC,WAAW,iBAAiB,GAAG,YAAY,CAC9C;AAAA,IAEA,OAAO,SAAS,OAAO,KAAK,IAAI,SAAS,KAAK,EAAE;AAAA;AAAA,OAGrC,2BAA0B,CACrC,WACA,QAC6B;AAAA,IAC7B,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAE5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA;AAAA,aAEO,KAAK;AAAA,6BACW;AAAA;AAAA;AAAA,OAIvB,CAAC,WAAW,QAAQ,GAAG,YAAY,CACrC;AAAA,IAEA,MAAM,aAAa,OAAO,KAAK,IAAI;AAAA,IACnC,IAAI,CAAC;AAAA,MAAY;AAAA,IACjB,OAAO,IAAI,KAAK,UAAU,EAAE,YAAY;AAAA;AAAA,OAG7B,qBAAoB,CAAC,WAAgD;AAAA,IAChF,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAE5F,MAAM,SAAS,MAAM,KAAK,GAAG,MAC3B;AAAA;AAAA,aAEO,KAAK;AAAA,6BACW;AAAA,OAEvB,CAAC,WAAW,GAAG,YAAY,CAC7B;AAAA,IAEA,MAAM,kBAAkB,OAAO,KAAK,IAAI;AAAA,IACxC,IAAI,CAAC;AAAA,MAAiB;AAAA,IACtB,OAAO,IAAI,KAAK,eAAe,EAAE,YAAY;AAAA;AAAA,OAGlC,qBAAoB,CAAC,WAAmB,iBAAwC;AAAA,IAC3F,MAAM,oBAAoB,sBAAqB,KAAK,QAAQ;AAAA,IAC5D,MAAM,sBACJ,kBAAkB,SAAS,IAAI,kBAAkB,KAAK,IAAI,IAAI,OAAO;AAAA,IACvE,MAAM,oBAAoB,KAAK,qBAAqB;AAAA,IACpD,MAAM,0BACJ,kBAAkB,SAAS,IACvB,kBAAkB,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,GAAG,EAAE,KAAK,IAAI,IAAI,OAC1D;AAAA,IACN,MAAM,iBAAiB,kBAAkB,SAAS;AAAA,IAGlD,MAAM,kBACJ,kBAAkB,SAAS,IAAI,GAAG,kBAAkB,KAAK,IAAI,kBAAkB;AAAA,IAEjF,MAAM,KAAK,GAAG,MACZ;AAAA,oBACc,KAAK,2BAA2B;AAAA,gBACpC,2BAA2B,oBAAoB,iBAAiB;AAAA,qBAC3D;AAAA;AAAA,OAGf,CAAC,GAAG,mBAAmB,WAAW,eAAe,CACnD;AAAA;AAAA,OAGW,MAAK,CAAC,WAAkC;AAAA,IACnD,QAAQ,YAAY,kBAAkB,QAAQ,iBAAiB,KAAK,uBAAuB,CAAC;AAAA,IAE5F,MAAM,KAAK,GAAG,MACZ,eAAe,KAAK,2CAA2C,oBAC/D,CAAC,WAAW,GAAG,YAAY,CAC7B;AAAA,IACA,MAAM,KAAK,GAAG,MACZ,eAAe,KAAK,+CAA+C,oBACnE,CAAC,WAAW,GAAG,YAAY,CAC7B;AAAA;AAEJ;",
12
- "debugId": "2ED5372BB2A9B7BA64756E2164756E21",
11
+ "mappings": "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",
12
+ "debugId": "4374150EC82279E664756E2164756E21",
13
13
  "names": []
14
14
  }
@@ -16,9 +16,12 @@ import { type IMigration, type IMigrationRunner, type RunMigrationsOptions } fro
16
16
  * `connect()` (it is single-client by construction), so we fall back to
17
17
  * the raw pool — BEGIN/COMMIT on it still hit the same backing connection.
18
18
  *
19
- * A unique constraint on `(component, version)` makes concurrent runners
20
- * safe: the loser of a race raises a duplicate-key error (`23505`) and we
21
- * treat that as "already applied".
19
+ * Concurrent `run()` calls against the same pool are serialized through a
20
+ * JS-layer mutex so racing runners see each others' bookkeeping rows before
21
+ * deciding to invoke `up()`. The unique constraint on `(component, version)`
22
+ * remains a defense-in-depth check — a 23505 from a separate process (or a
23
+ * different pool instance backed by the same database) is still treated as
24
+ * "already applied".
22
25
  */
23
26
  export declare class PostgresMigrationRunner implements IMigrationRunner<Pool> {
24
27
  private readonly db;
@@ -27,5 +30,6 @@ export declare class PostgresMigrationRunner implements IMigrationRunner<Pool> {
27
30
  appliedVersions(component: string): Promise<Set<number>>;
28
31
  private acquireClient;
29
32
  run(migrations: ReadonlyArray<IMigration<Pool>>, options?: RunMigrationsOptions): Promise<ReadonlyArray<IMigration<Pool>>>;
33
+ private runInternal;
30
34
  }
31
35
  //# sourceMappingURL=PostgresMigrationRunner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PostgresMigrationRunner.d.ts","sourceRoot":"","sources":["../../src/migrations/PostgresMigrationRunner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAyB3B;;;;;;;;;;;;;;GAcG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB,CAAC,IAAI,CAAC;IACxD,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,IAAI,EAAI;IAEnC,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAU5C;IAEK,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAM7D;YAOa,aAAa;IASrB,GAAG,CACP,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAC3C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CA+E1C;CACF"}
1
+ {"version":3,"file":"PostgresMigrationRunner.d.ts","sourceRoot":"","sources":["../../src/migrations/PostgresMigrationRunner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EACL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAsC3B;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB,CAAC,IAAI,CAAC;IACxD,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,IAAI,EAAI;IAEnC,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAU5C;IAEK,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAM7D;YAOa,aAAa;IASrB,GAAG,CACP,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAC3C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAS1C;YAEa,WAAW;CAmF1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/migrations/common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/migrations/common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC"}
@@ -242,6 +242,18 @@ export declare class PostgresTabularStorage<Schema extends DataPortSchemaObject,
242
242
  */
243
243
  get(key: PrimaryKey): Promise<Entity | undefined>;
244
244
  private _getInternal;
245
+ /**
246
+ * Fetch multiple rows by primary key in a single statement. Single-column
247
+ * keys emit `WHERE pk IN ($1,$2,...)`. Compound keys emit
248
+ * `WHERE (pk1,pk2,...) IN (($1,$2,...),($3,$4,...),...)`. Values bind
249
+ * through `jsToSqlValue` for parity with `query()` and `get()`.
250
+ *
251
+ * Postgres caps a single statement at 65535 bind parameters; inputs that
252
+ * would exceed the cap are chunked so each round-trip stays well under
253
+ * it. The same chunking shape is shared with the SQLite backend.
254
+ */
255
+ getBulk(keys: readonly PrimaryKey[]): Promise<Entity[]>;
256
+ private _getBulkInternal;
245
257
  /**
246
258
  * Deletes a row from the database.
247
259
  *
@@ -281,8 +293,8 @@ export declare class PostgresTabularStorage<Schema extends DataPortSchemaObject,
281
293
  * @param limit - Maximum number of records to return
282
294
  * @returns Array of entities or undefined if no records found
283
295
  */
284
- getBulk(offset: number, limit: number): Promise<Entity[] | undefined>;
285
- private _getBulkInternal;
296
+ getOffsetPage(offset: number, limit: number): Promise<Entity[] | undefined>;
297
+ private _getOffsetPageInternal;
286
298
  /**
287
299
  * Builds WHERE clause conditions from delete search criteria.
288
300
  * @param criteria - The search criteria object
@@ -1 +1 @@
1
- {"version":3,"file":"PostgresTabularStorage.d.ts","sourceRoot":"","sources":["../../src/storage/PostgresTabularStorage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostgresTabularStorage.d.ts","sourceRoot":"","sources":["../../src/storage/PostgresTabularStorage.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@
6
6
  import type { Pool } from "@workglow/postgres/storage";
7
7
  import type { DataPortSchemaObject, FromSchema, TypedArray, TypedArrayConstructor, TypedArraySchemaOptions } from "@workglow/util/schema";
8
8
  import { PostgresTabularStorage } from "./PostgresTabularStorage";
9
- import type { HybridSearchOptions, IVectorStorage, VectorIndexOptions, VectorSearchOptions } from "@workglow/storage";
9
+ import type { IVectorStorage, VectorIndexOptions, VectorSearchOptions } from "@workglow/storage";
10
10
  export declare class PostgresVectorStorage<Schema extends DataPortSchemaObject, PrimaryKeyNames extends ReadonlyArray<keyof Schema["properties"]>, Metadata extends Record<string, unknown> = Record<string, unknown>, Entity = FromSchema<Schema, TypedArraySchemaOptions>> extends PostgresTabularStorage<Schema, PrimaryKeyNames, Entity> implements IVectorStorage<Metadata, Schema, Entity, PrimaryKeyNames> {
11
11
  private vectorDimensions;
12
12
  private readonly vectorCtor;
@@ -69,9 +69,6 @@ export declare class PostgresVectorStorage<Schema extends DataPortSchemaObject,
69
69
  similaritySearch(query: TypedArray, options?: VectorSearchOptions<Metadata>): Promise<Array<Entity & {
70
70
  score: number;
71
71
  }>>;
72
- hybridSearch(query: TypedArray, options: HybridSearchOptions<Metadata>): Promise<(Entity & {
73
- score: number;
74
- })[]>;
75
72
  /**
76
73
  * Throws if the configured distance metric isn't cosine. The in-memory
77
74
  * fallback paths below only know how to compute cosine similarity; if
@@ -81,7 +78,6 @@ export declare class PostgresVectorStorage<Schema extends DataPortSchemaObject,
81
78
  */
82
79
  private assertFallbackSupportsDistance;
83
80
  private searchFallback;
84
- private hybridSearchFallback;
85
81
  private getPrimaryKeyWhereClause;
86
82
  private getPrimaryKeyValues;
87
83
  private matchesFilter;
@@ -1 +1 @@
1
- {"version":3,"file":"PostgresVectorStorage.d.ts","sourceRoot":"","sources":["../../src/storage/PostgresVectorStorage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EAEd,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAoB3B,qBAAa,qBAAqB,CAChC,MAAM,SAAS,oBAAoB,EACnC,eAAe,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,EACjE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAEpD,SAAQ,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,CAC9D,YAAW,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC;IAEpE,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwB;IACnD,OAAO,CAAC,kBAAkB,CAAe;IACzC,OAAO,CAAC,oBAAoB,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAElD;;;;;;;;;;;;;;OAcG;IACH,YACE,EAAE,EAAE,IAAI,EACR,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,YAAK,EACrF,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,qBAAoC,EAChD,YAAY,GAAE,kBAAuB,EAetC;IAEe,mBAAmB,IAAI,MAAM,CAE5C;IAED,4EAA4E;IAC5E,UAAmB,qBAAqB,IAAI,kBAAkB,CAE7D;IAED,sEAAsE;IACtE,OAAO,KAAK,QAAQ,GAEnB;IAED;;;;;;OAMG;IACH,OAAO,KAAK,gBAAgB,GAS3B;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;;;;;;;OAUG;IACI,cAAc,IAAI;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAK9D;IAEY,gBAAgB,CAC3B,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,mBAAmB,CAAC,QAAQ,CAAM,GAC1C,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CA4F5C;IAEK,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC;eA9FzC,MAAM;UAyLxC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,8BAA8B;YAcxB,cAAc;YAiCd,oBAAoB;IA+ClC,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,aAAa;CAQtB"}
1
+ {"version":3,"file":"PostgresVectorStorage.d.ts","sourceRoot":"","sources":["../../src/storage/PostgresVectorStorage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,KAAK,EACV,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,OAAO,KAAK,EACV,cAAc,EAEd,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAoB3B,qBAAa,qBAAqB,CAChC,MAAM,SAAS,oBAAoB,EACnC,eAAe,SAAS,aAAa,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,EACjE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAEpD,SAAQ,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,CAC9D,YAAW,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC;IAEpE,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwB;IACnD,OAAO,CAAC,kBAAkB,CAAe;IACzC,OAAO,CAAC,oBAAoB,CAA2B;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAElD;;;;;;;;;;;;;;OAcG;IACH,YACE,EAAE,EAAE,IAAI,EACR,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,YAAK,EACrF,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,qBAAoC,EAChD,YAAY,GAAE,kBAAuB,EAetC;IAEe,mBAAmB,IAAI,MAAM,CAE5C;IAED,4EAA4E;IAC5E,UAAmB,qBAAqB,IAAI,kBAAkB,CAE7D;IAED,sEAAsE;IACtE,OAAO,KAAK,QAAQ,GAEnB;IAED;;;;;;OAMG;IACH,OAAO,KAAK,gBAAgB,GAS3B;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;IAYtB;;;;;;;;;;OAUG;IACI,cAAc,IAAI;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAK9D;IAEY,gBAAgB,CAC3B,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,mBAAmB,CAAC,QAAQ,CAAM,GAC1C,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CA4F5C;IAED;;;;;;OAMG;IACH,OAAO,CAAC,8BAA8B;YAcxB,cAAc;IA6B5B,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,aAAa;CAQtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/storage/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/storage/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
@@ -748,6 +748,52 @@ class PostgresTabularStorage extends BaseSqlTabularStorage {
748
748
  this.events.emit("get", key, val);
749
749
  return val;
750
750
  }
751
+ async getBulk(keys) {
752
+ if (keys.length === 0)
753
+ return [];
754
+ const pkColCount = this.primaryKeyColumns().length;
755
+ const chunkSize = Math.max(1, Math.floor(30000 / pkColCount));
756
+ let rows;
757
+ if (keys.length <= chunkSize) {
758
+ rows = await this.mutex(() => this._getBulkInternal(keys));
759
+ } else {
760
+ rows = [];
761
+ for (let i = 0;i < keys.length; i += chunkSize) {
762
+ const chunk = keys.slice(i, i + chunkSize);
763
+ const chunkRows = await this.mutex(() => this._getBulkInternal(chunk));
764
+ rows.push(...chunkRows);
765
+ }
766
+ }
767
+ this.events.emit("getBulk", keys, rows);
768
+ return rows;
769
+ }
770
+ async _getBulkInternal(keys) {
771
+ const db = this.db;
772
+ const pkCols = this.primaryKeyColumns();
773
+ const params = [];
774
+ const tuples = [];
775
+ let p = 1;
776
+ for (const key of keys) {
777
+ const ordered = this.getPrimaryKeyAsOrderedArray(key);
778
+ params.push(...ordered);
779
+ const slots = [];
780
+ for (let i = 0;i < pkCols.length; i++) {
781
+ slots.push(`$${p++}`);
782
+ }
783
+ tuples.push(`(${slots.join(", ")})`);
784
+ }
785
+ const lhs = pkCols.length === 1 ? `"${pkCols[0]}"` : `(${pkCols.map((c) => `"${c}"`).join(", ")})`;
786
+ const rhs = pkCols.length === 1 ? params.map((_, i) => `$${i + 1}`).join(", ") : tuples.join(", ");
787
+ const sql = `SELECT * FROM "${this.table}" WHERE ${lhs} IN (${rhs})`;
788
+ const result = await db.query(sql, params);
789
+ for (const row of result.rows) {
790
+ const record = row;
791
+ for (const key in this.schema.properties) {
792
+ record[key] = this.sqlToJsValue(key, record[key]);
793
+ }
794
+ }
795
+ return result.rows;
796
+ }
751
797
  async delete(value) {
752
798
  return this.mutex(() => this._deleteInternal(value));
753
799
  }
@@ -820,10 +866,10 @@ class PostgresTabularStorage extends BaseSqlTabularStorage {
820
866
  const result = await db.query(`SELECT COUNT(*) FROM "${this.table}" WHERE ${whereClause}`, params);
821
867
  return parseInt(result.rows[0].count, 10);
822
868
  }
823
- async getBulk(offset, limit) {
824
- return this.mutex(() => this._getBulkInternal(offset, limit));
869
+ async getOffsetPage(offset, limit) {
870
+ return this.mutex(() => this._getOffsetPageInternal(offset, limit));
825
871
  }
826
- async _getBulkInternal(offset, limit) {
872
+ async _getOffsetPageInternal(offset, limit) {
827
873
  const db = this.db;
828
874
  const orderByClause = this.primaryKeyColumns().map((col) => `"${String(col)}"`).join(", ");
829
875
  const result = await db.query(`SELECT * FROM "${this.table}" ORDER BY ${orderByClause} LIMIT $1 OFFSET $2`, [limit, offset]);
@@ -1172,74 +1218,6 @@ class PostgresVectorStorage extends PostgresTabularStorage {
1172
1218
  return this.searchFallback(query, options);
1173
1219
  }
1174
1220
  }
1175
- async hybridSearch(query, options) {
1176
- const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;
1177
- if (!textQuery || textQuery.trim().length === 0) {
1178
- return this.similaritySearch(query, { topK, filter, scoreThreshold });
1179
- }
1180
- try {
1181
- const queryVector = `[${Array.from(query).join(",")}]`;
1182
- const tsQueryText = textQuery;
1183
- const vectorColRaw = String(this.vectorPropertyName);
1184
- const vectorCol = PostgresDialect2.quoteId(vectorColRaw);
1185
- const metadataColRaw = this.metadataPropertyName ? String(this.metadataPropertyName) : null;
1186
- const metadataCol = metadataColRaw ? PostgresDialect2.quoteId(metadataColRaw) : null;
1187
- const vectorScoreExpr = this.buildScoreExpr(vectorCol, "$1");
1188
- const combinedScoreExpr = `(
1189
- $2 * ${vectorScoreExpr} +
1190
- $3 * ts_rank(to_tsvector('english', ${metadataCol || "''"}::text), plainto_tsquery('english', $4))
1191
- )`;
1192
- let sql = `
1193
- SELECT
1194
- *,
1195
- ${combinedScoreExpr} as score
1196
- FROM "${this.table}"
1197
- `;
1198
- const params = [queryVector, vectorWeight, 1 - vectorWeight, tsQueryText];
1199
- let paramIndex = 5;
1200
- let hasWhere = false;
1201
- if (filter && Object.keys(filter).length > 0 && metadataCol) {
1202
- const conditions = [];
1203
- for (const [key, value] of Object.entries(filter)) {
1204
- if (!SAFE_IDENTIFIER_RE.test(key)) {
1205
- throw new StorageValidationError(`Invalid metadata filter key: "${key}". Keys must match /^[a-zA-Z_][a-zA-Z0-9_]*$/.`);
1206
- }
1207
- conditions.push(`${metadataCol}->>'${key}' = $${paramIndex}`);
1208
- params.push(String(value));
1209
- paramIndex++;
1210
- }
1211
- if (conditions.length > 0) {
1212
- sql += ` WHERE ${conditions.join(" AND ")}`;
1213
- hasWhere = true;
1214
- }
1215
- }
1216
- sql += hasWhere ? " AND" : " WHERE";
1217
- sql += ` ${combinedScoreExpr} >= $${paramIndex}`;
1218
- params.push(scoreThreshold);
1219
- paramIndex++;
1220
- sql += ` ORDER BY score DESC LIMIT $${paramIndex}`;
1221
- params.push(topK);
1222
- const result = await this.db.query(sql, params);
1223
- const results = [];
1224
- for (const row of result.rows) {
1225
- const vectorResult = await this.db.query(`SELECT ${vectorCol}::text FROM "${this.table}" WHERE ${this.getPrimaryKeyWhereClause()}`, this.getPrimaryKeyValues(row));
1226
- const vectorStr = vectorResult.rows[0]?.[vectorColRaw] || "[]";
1227
- const vectorArray = JSON.parse(vectorStr);
1228
- results.push({
1229
- ...row,
1230
- [this.vectorPropertyName]: new this.vectorCtor(vectorArray),
1231
- score: parseFloat(row.score)
1232
- });
1233
- }
1234
- return results;
1235
- } catch (error) {
1236
- if (error instanceof StorageValidationError) {
1237
- throw error;
1238
- }
1239
- console.error("pgvector hybrid query failed, falling back to in-memory search:", error);
1240
- return this.hybridSearchFallback(query, options);
1241
- }
1242
- }
1243
1221
  assertFallbackSupportsDistance() {
1244
1222
  if (this.distance !== "cosine") {
1245
1223
  throw new Error(`PostgresVectorStorage: pgvector is unavailable and the in-memory ` + `fallback only supports cosine distance (configured: "${this.distance}"). ` + `Install pgvector or switch the storage to cosine distance.`);
@@ -1265,40 +1243,6 @@ class PostgresVectorStorage extends PostgresTabularStorage {
1265
1243
  const topResults = results.slice(0, topK);
1266
1244
  return topResults;
1267
1245
  }
1268
- async hybridSearchFallback(query, options) {
1269
- this.assertFallbackSupportsDistance();
1270
- const { topK = 10, filter, scoreThreshold = 0, textQuery, vectorWeight = 0.7 } = options;
1271
- const allRows = await this.getAll() || [];
1272
- const results = [];
1273
- const queryLower = textQuery.toLowerCase();
1274
- const queryWords = queryLower.split(/\s+/).filter((w) => w.length > 0);
1275
- for (const row of allRows) {
1276
- const vector = row[this.vectorPropertyName];
1277
- const metadata = this.metadataPropertyName ? row[this.metadataPropertyName] : {};
1278
- if (filter && !this.matchesFilter(metadata, filter)) {
1279
- continue;
1280
- }
1281
- const vectorScore = cosineSimilarity(query, vector);
1282
- const metadataText = Object.values(metadata ?? {}).join(" ").toLowerCase();
1283
- let textScore = 0;
1284
- if (queryWords.length > 0) {
1285
- let matches = 0;
1286
- for (const word of queryWords) {
1287
- if (metadataText.includes(word)) {
1288
- matches++;
1289
- }
1290
- }
1291
- textScore = matches / queryWords.length;
1292
- }
1293
- const combinedScore = vectorWeight * vectorScore + (1 - vectorWeight) * textScore;
1294
- if (combinedScore >= scoreThreshold) {
1295
- results.push({ ...row, score: combinedScore });
1296
- }
1297
- }
1298
- results.sort((a, b) => b.score - a.score);
1299
- const topResults = results.slice(0, topK);
1300
- return topResults;
1301
- }
1302
1246
  getPrimaryKeyWhereClause() {
1303
1247
  const conditions = this.primaryKeyNames.map((key, idx) => `${String(key)} = $${idx + 1}`);
1304
1248
  return conditions.join(" AND ");
@@ -1327,4 +1271,4 @@ export {
1327
1271
  POSTGRES_KV_REPOSITORY
1328
1272
  };
1329
1273
 
1330
- //# debugId=9A981229758C242364756E2164756E21
1274
+ //# debugId=6727C8BA6F088ED064756E2164756E21