@happyvertical/sql 0.74.11 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{duckdb-CIywTPV3.js → duckdb-B6m78QdL.js} +2 -2
- package/dist/chunks/{duckdb-CIywTPV3.js.map → duckdb-B6m78QdL.js.map} +1 -1
- package/dist/chunks/{index-DrPgGVZz.js → index-CzdYvRFp.js} +4 -4
- package/dist/chunks/{index-DrPgGVZz.js.map → index-CzdYvRFp.js.map} +1 -1
- package/dist/chunks/{sqlite-Cxjsirpn.js → sqlite-CPCNeJIH.js} +3 -3
- package/dist/chunks/{sqlite-Cxjsirpn.js.map → sqlite-CPCNeJIH.js.map} +1 -1
- package/dist/chunks/{sqlite-native-BdArMasZ.js → sqlite-native-DqVPKNUu.js} +2 -2
- package/dist/chunks/{sqlite-native-BdArMasZ.js.map → sqlite-native-DqVPKNUu.js.map} +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-DrPgGVZz.js","sources":["../../src/shared/utils.ts","../../src/aggregate.ts","../../src/shared/duckdb-schema-utils.ts","../../src/doctor.ts","../../src/schema-manager.ts","../../src/shared/types.ts","../../src/json.ts","../../src/shared/alter-utils.ts","../../src/postgres.ts","../../src/index.ts"],"sourcesContent":["/**\n * Shared SQL utilities that work in both browser and Node.js environments\n */\n\nimport type { WhereClause } from './types.js';\n\n/**\n * Formats a database error to include all relevant details\n *\n * Database drivers often include additional properties beyond just `message`:\n * - PostgreSQL: code, detail, hint, severity\n * - DuckDB: may include additional context\n * - SQLite/LibSQL: may include errno, code\n *\n * This function extracts all available error properties to provide\n * better debugging information.\n *\n * @param error - The caught error object\n * @returns Formatted error string with all available error details\n */\nexport function formatDbError(error: unknown): string {\n const dbError = error as {\n message?: string;\n code?: string;\n detail?: string;\n hint?: string;\n severity?: string;\n errno?: number;\n cause?: unknown;\n };\n\n const parts: string[] = [];\n\n if (dbError.message) parts.push(dbError.message);\n if (dbError.code) parts.push(`code=${dbError.code}`);\n if (dbError.detail) parts.push(`detail=${dbError.detail}`);\n if (dbError.hint) parts.push(`hint=${dbError.hint}`);\n if (dbError.severity) parts.push(`severity=${dbError.severity}`);\n if (dbError.errno !== undefined) parts.push(`errno=${dbError.errno}`);\n\n return parts.length > 0 ? parts.join(', ') : String(error);\n}\n\n/**\n * Map of valid SQL operators for use in WHERE clauses\n */\nconst VALID_OPERATORS = {\n '=': '=',\n '>': '>',\n '>=': '>=',\n '<': '<',\n '<=': '<=',\n '!=': '!=',\n like: 'LIKE',\n in: 'IN',\n 'not in': 'NOT IN',\n} as const;\n\nfunction isSimpleSqlIdentifier(field: string): boolean {\n return /^[a-zA-Z0-9_.]+$/.test(field);\n}\n\nexport function parseConditionKey(fullKey: string): {\n field: string;\n operator: string;\n explicitOperator: boolean;\n} {\n const trimmed = fullKey.trim();\n const lower = trimmed.toLowerCase();\n const operators = ['not in', 'like', 'in', '!=', '>=', '<=', '>', '<', '='];\n\n for (const operator of operators) {\n if (lower.endsWith(` ${operator}`)) {\n return {\n field: trimmed.slice(0, -(operator.length + 1)).trim(),\n operator,\n explicitOperator: true,\n };\n }\n }\n\n return { field: trimmed, operator: '=', explicitOperator: false };\n}\n\n/**\n * SQL adapter type for adapter-specific query generation\n */\nexport type SqlAdapterType = 'sqlite' | 'postgres' | 'duckdb' | 'json';\n\n/**\n * Builds a single condition for a WHERE clause\n * @internal\n */\nconst buildCondition = (\n fullKey: string,\n value: any,\n currIndex: { value: number },\n adapterType?: SqlAdapterType,\n): { sql: string; values: any[] } => {\n const { field, operator, explicitOperator } = parseConditionKey(fullKey);\n if (!explicitOperator && !isSimpleSqlIdentifier(field)) {\n throw new Error(`Invalid SQL identifier: ${field}`);\n }\n const sqlOperator =\n VALID_OPERATORS[operator as keyof typeof VALID_OPERATORS] || '=';\n const values: any[] = [];\n\n let sql: string;\n\n if (value === null) {\n sql = `${field} IS ${sqlOperator === '=' ? 'NULL' : 'NOT NULL'}`;\n } else if (\n (sqlOperator === 'IN' || sqlOperator === 'NOT IN') &&\n Array.isArray(value)\n ) {\n if (value.length === 0) {\n throw new Error(`${sqlOperator} requires at least one value`);\n }\n const placeholders = value.map(() => `$${currIndex.value++}`).join(', ');\n sql = `${field} ${sqlOperator} (${placeholders})`;\n values.push(...value);\n } else if (value instanceof Date) {\n // DuckDB/JSON need CAST to TIMESTAMP to prevent ANY type inference (issue #540)\n // SQLite/PostgreSQL handle ISO strings natively without CAST\n const needsCast = adapterType === 'duckdb' || adapterType === 'json';\n if (needsCast) {\n sql = `${field} ${sqlOperator} CAST($${currIndex.value++} AS TIMESTAMP)`;\n } else {\n sql = `${field} ${sqlOperator} $${currIndex.value++}`;\n }\n values.push(value.toISOString());\n } else {\n sql = `${field} ${sqlOperator} $${currIndex.value++}`;\n values.push(value);\n }\n\n return { sql, values };\n};\n\n/**\n * Builds a SQL WHERE clause with parameterized values and flexible operators\n *\n * @param where - Conditions as object (AND-only) or 2D array (OR/AND compound)\n * @param startIndex - Starting index for parameter numbering (default: 1)\n * @param adapterType - Database adapter type. Controls Date handling:\n * - `'duckdb'` / `'json'`: Wraps Date values in `CAST($N AS TIMESTAMP)` to\n * prevent DuckDB ANY-type inference issues.\n * - `'sqlite'` / `'postgres'` / `undefined`: Passes ISO strings directly\n * (these adapters handle ISO timestamp strings natively).\n *\n * Keys with explicit operator suffixes are treated as SQL field/expression\n * text. Keep those keys developer-controlled; do not pass end-user input as a\n * condition key.\n *\n * @returns Object containing the SQL clause and array of values\n *\n * @example Basic Usage (Object format - AND-only):\n * ```typescript\n * buildWhere({\n * 'status': 'active', // equals operator is default\n * 'price >': 100, // greater than\n * 'stock <=': 5, // less than or equal\n * 'category in': ['A', 'B'], // IN clause for arrays\n * 'name like': '%shirt%' // LIKE for pattern matching\n * });\n * ```\n *\n * @example 2D Array Format (OR/AND compound logic):\n * ```typescript\n * // WHERE (status = 'active' AND price > 100) OR (status = 'pending' AND priority = 'high')\n * buildWhere([\n * [{ status: 'active' }, { 'price >': 100 }],\n * [{ status: 'pending' }, { priority: 'high' }]\n * ]);\n * ```\n *\n * @example NULL Handling:\n * ```typescript\n * buildWhere({\n * 'deleted_at': null, // becomes \"deleted_at IS NULL\"\n * 'updated_at !=': null, // becomes \"updated_at IS NOT NULL\"\n * 'status': 'active' // regular comparison\n * });\n * ```\n *\n * @example Common Patterns:\n * ```typescript\n * // Price range\n * buildWhere({\n * 'price >=': 10,\n * 'price <': 100\n * });\n *\n * // Date filtering\n * buildWhere({\n * 'created_at >': startDate,\n * 'created_at <=': endDate,\n * 'deleted_at': null\n * });\n *\n * // Search with LIKE\n * buildWhere({\n * 'title like': '%search%',\n * 'description like': '%search%',\n * 'status': 'published'\n * });\n *\n * // Multiple values with IN\n * buildWhere({\n * 'role in': ['admin', 'editor'],\n * 'active': true,\n * 'last_login !=': null\n * });\n * ```\n *\n * The function handles:\n * - Standard comparisons (=, >, >=, <, <=, !=)\n * - NULL checks (IS NULL, IS NOT NULL)\n * - IN clauses for arrays\n * - LIKE for pattern matching\n * - Object format: Multiple conditions combined with AND\n * - 2D array format: Inner arrays ANDed, outer array ORed\n */\nexport const buildWhere = (\n where: WhereClause,\n startIndex = 1,\n adapterType?: SqlAdapterType,\n) => {\n let sql = '';\n const values: any[] = [];\n const currIndex = { value: startIndex };\n\n // Handle 2D array format for OR/AND compound logic\n if (Array.isArray(where)) {\n if (where.length === 0) {\n return { sql: '', values: [] };\n }\n\n const orGroups: string[] = [];\n\n for (const andGroup of where) {\n if (!Array.isArray(andGroup) || andGroup.length === 0) {\n continue;\n }\n\n const andConditions: string[] = [];\n\n for (const conditionObj of andGroup) {\n for (const [fullKey, value] of Object.entries(conditionObj)) {\n const result = buildCondition(fullKey, value, currIndex, adapterType);\n andConditions.push(result.sql);\n values.push(...result.values);\n }\n }\n\n if (andConditions.length > 0) {\n // Wrap AND group in parentheses\n orGroups.push(`(${andConditions.join(' AND ')})`);\n }\n }\n\n if (orGroups.length > 0) {\n sql = `WHERE ${orGroups.join(' OR ')}`;\n }\n\n return { sql, values };\n }\n\n // Handle object format (original behavior - AND-only)\n if (where && Object.keys(where).length > 0) {\n sql = 'WHERE ';\n for (const [fullKey, value] of Object.entries(where)) {\n const result = buildCondition(fullKey, value, currIndex, adapterType);\n\n if (sql !== 'WHERE ') {\n sql += ' AND ';\n }\n\n sql += result.sql;\n values.push(...result.values);\n }\n }\n\n return { sql, values };\n};\n","import type { WhereClause } from './shared/types.js';\nimport {\n buildWhere,\n parseConditionKey,\n type SqlAdapterType,\n} from './shared/utils.js';\n\nexport type AggregateTimeBucketUnit =\n | 'minute'\n | 'hour'\n | 'day'\n | 'week'\n | 'month'\n | 'quarter'\n | 'year';\n\nexport type AggregateFunction =\n | 'count'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | (string & {});\n\nexport type AggregateSelectExpr =\n | { column: string; as?: string }\n | {\n fn: AggregateFunction;\n column?: string;\n as: string;\n distinct?: boolean;\n }\n | {\n bucket: AggregateTimeBucketUnit;\n column: string;\n as: string;\n };\n\nexport interface AggregateSpec {\n from: string;\n select: AggregateSelectExpr[];\n where?: WhereClause;\n groupBy?: string[];\n having?: WhereClause;\n orderBy?: string | string[];\n limit?: number;\n offset?: number;\n}\n\nexport interface AggregateBuildResult {\n sql: string;\n values: any[];\n}\n\nconst VALID_DIRECTIONS = new Set(['ASC', 'DESC']);\nconst VALID_BUCKET_UNITS = new Set<AggregateTimeBucketUnit>([\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n 'quarter',\n 'year',\n]);\n\nfunction validateSqlIdentifier(identifier: string): string {\n if (!/^[a-zA-Z0-9_.]+$/.test(identifier)) {\n throw new Error(`Invalid SQL identifier: ${identifier}`);\n }\n return identifier;\n}\n\nfunction normalizeAdapter(adapterType?: SqlAdapterType): SqlAdapterType {\n return adapterType ?? 'sqlite';\n}\n\nfunction placeholder(index: number): string {\n return `$${index}`;\n}\n\nexport function bucketExpr(\n adapterType: SqlAdapterType | undefined,\n unit: AggregateTimeBucketUnit,\n column: string,\n): string {\n if (!VALID_BUCKET_UNITS.has(unit)) {\n throw new Error(`Invalid aggregate bucket unit: ${unit}`);\n }\n\n const col = validateSqlIdentifier(column);\n const adapter = normalizeAdapter(adapterType);\n\n if (adapter === 'postgres' || adapter === 'duckdb' || adapter === 'json') {\n return `date_trunc('${unit}', ${col})`;\n }\n\n switch (unit) {\n case 'minute':\n return `strftime('%Y-%m-%d %H:%M:00', ${col})`;\n case 'hour':\n return `strftime('%Y-%m-%d %H:00:00', ${col})`;\n case 'day':\n return `strftime('%Y-%m-%d 00:00:00', ${col})`;\n case 'week':\n return `strftime('%Y-%m-%d 00:00:00', date(${col}, printf('-%d days', (CAST(strftime('%w', ${col}) AS INTEGER) + 6) % 7)))`;\n case 'month':\n return `strftime('%Y-%m-01 00:00:00', ${col})`;\n case 'quarter':\n return `strftime('%Y-%m-%d 00:00:00', date(strftime('%Y-', ${col}) || printf('%02d', ((CAST(strftime('%m', ${col}) AS INTEGER) - 1) / 3) * 3 + 1) || '-01'))`;\n case 'year':\n return `strftime('%Y-01-01 00:00:00', ${col})`;\n }\n}\n\nfunction aggregateExpression(\n expr: Extract<AggregateSelectExpr, { fn: AggregateFunction }>,\n): string {\n const normalizedFn = String(expr.fn).toLowerCase();\n const fn = validateSqlIdentifier(String(expr.fn)).toUpperCase();\n if (normalizedFn === 'count' && !expr.column) {\n if (expr.distinct) {\n throw new Error(`Aggregate ${expr.fn} with distinct requires a column`);\n }\n return 'COUNT(*)';\n }\n if (!expr.column) {\n throw new Error(`Aggregate ${expr.fn} requires a column`);\n }\n const col = validateSqlIdentifier(expr.column);\n const distinct = expr.distinct ? 'DISTINCT ' : '';\n return `${fn}(${distinct}${col})`;\n}\n\nfunction selectExpression(\n expr: AggregateSelectExpr,\n adapterType: SqlAdapterType | undefined,\n): { expression: string; alias: string; groupingCandidate: boolean } {\n if ('column' in expr && !('fn' in expr) && !('bucket' in expr)) {\n const column = validateSqlIdentifier(expr.column);\n const alias = validateSqlIdentifier(expr.as ?? expr.column);\n return { expression: column, alias, groupingCandidate: true };\n }\n if ('bucket' in expr) {\n const expression = bucketExpr(adapterType, expr.bucket, expr.column);\n const alias = validateSqlIdentifier(expr.as);\n return { expression, alias, groupingCandidate: true };\n }\n\n const expression = aggregateExpression(expr);\n const alias = validateSqlIdentifier(expr.as);\n return { expression, alias, groupingCandidate: false };\n}\n\nfunction validateWhereShape(where: AggregateSpec['where']): void {\n if (!where) return;\n const validateKey = (key: string) => {\n const { field } = parseConditionKey(key);\n if (field) validateSqlIdentifier(field);\n };\n if (Array.isArray(where)) {\n for (const andGroup of where) {\n for (const condition of andGroup) {\n for (const key of Object.keys(condition)) validateKey(key);\n }\n }\n return;\n }\n for (const key of Object.keys(where)) validateKey(key);\n}\n\nfunction expandHavingKey(\n key: string,\n expressionByAlias: Map<string, string>,\n): string {\n const parsed = parseConditionKey(key);\n const expression =\n expressionByAlias.get(parsed.field) ?? validateSqlIdentifier(parsed.field);\n\n return `${expression} ${parsed.operator}`;\n}\n\nfunction expandHaving(\n having: WhereClause,\n expressionByAlias: Map<string, string>,\n): WhereClause {\n const expandCondition = (condition: Record<string, any>) =>\n Object.fromEntries(\n Object.entries(condition).map(([key, value]) => [\n expandHavingKey(key, expressionByAlias),\n value,\n ]),\n );\n if (Array.isArray(having)) {\n return having.map((andGroup: Record<string, any>[]) =>\n andGroup.map((condition: Record<string, any>) =>\n expandCondition(condition),\n ),\n );\n }\n\n return expandCondition(having);\n}\n\nfunction buildHaving(\n having: AggregateSpec['having'],\n expressionByAlias: Map<string, string>,\n startIndex: number,\n adapterType: SqlAdapterType | undefined,\n): AggregateBuildResult {\n if (!having) return { sql: '', values: [] };\n const expanded = expandHaving(having, expressionByAlias);\n const built = buildWhere(expanded, startIndex, adapterType);\n\n return {\n sql: built.sql ? built.sql.replace(/^WHERE/, 'HAVING') : '',\n values: built.values,\n };\n}\n\nfunction buildOrderBy(orderBy: string | string[] | undefined): string {\n if (!orderBy) return '';\n const items = Array.isArray(orderBy) ? orderBy : [orderBy];\n const parts = items.map((item) => {\n const [field, direction = 'ASC'] = item.trim().split(/\\s+/);\n const normalizedDirection = direction.toUpperCase();\n if (!VALID_DIRECTIONS.has(normalizedDirection)) {\n throw new Error(`Invalid aggregate order direction: ${direction}`);\n }\n const orderExpr = validateSqlIdentifier(field);\n return `${orderExpr} ${normalizedDirection}`;\n });\n return `ORDER BY ${parts.join(', ')}`;\n}\n\nexport function buildAggregate(\n spec: AggregateSpec,\n startIndex = 1,\n adapterType?: SqlAdapterType,\n): AggregateBuildResult {\n const from = validateSqlIdentifier(spec.from);\n if (spec.select.length === 0) {\n throw new Error(\n 'AggregateSpec.select must contain at least one expression',\n );\n }\n\n validateWhereShape(spec.where);\n\n const expressionByAlias = new Map<string, string>();\n const groupingAliases: string[] = [];\n const selectSql = spec.select.map((expr) => {\n const selected = selectExpression(expr, adapterType);\n expressionByAlias.set(selected.alias, selected.expression);\n if (selected.groupingCandidate) {\n groupingAliases.push(selected.alias);\n }\n return `${selected.expression} AS ${selected.alias}`;\n });\n\n const where = spec.where\n ? buildWhere(spec.where, startIndex, adapterType)\n : { sql: '', values: [] };\n let nextParamIndex = startIndex + where.values.length;\n\n const groupByItems = spec.groupBy ?? groupingAliases;\n const groupBySql =\n groupByItems.length > 0\n ? `GROUP BY ${groupByItems\n .map((item) =>\n expressionByAlias.has(item)\n ? expressionByAlias.get(item)\n : validateSqlIdentifier(item),\n )\n .join(', ')}`\n : '';\n\n const having = buildHaving(\n spec.having,\n expressionByAlias,\n nextParamIndex,\n adapterType,\n );\n nextParamIndex += having.values.length;\n\n const orderBySql = buildOrderBy(spec.orderBy);\n\n const pagingValues: any[] = [];\n const pagingSql: string[] = [];\n if (spec.limit !== undefined) {\n pagingSql.push(`LIMIT ${placeholder(nextParamIndex++)}`);\n pagingValues.push(spec.limit);\n } else if (\n spec.offset !== undefined &&\n normalizeAdapter(adapterType) === 'sqlite'\n ) {\n pagingSql.push('LIMIT -1');\n }\n if (spec.offset !== undefined) {\n pagingSql.push(`OFFSET ${placeholder(nextParamIndex++)}`);\n pagingValues.push(spec.offset);\n }\n\n const sql = [\n `SELECT ${selectSql.join(', ')}`,\n `FROM ${from}`,\n where.sql,\n groupBySql,\n having.sql,\n orderBySql,\n pagingSql.join(' '),\n ]\n .filter(Boolean)\n .join(' ');\n\n return {\n sql,\n values: [...where.values, ...having.values, ...pagingValues],\n };\n}\n","/**\n * DuckDB-specific schema transformation utilities\n *\n * DuckDB has a known limitation (issue #12684) where ON CONFLICT clauses\n * fail with UNIQUE INDEX but work with inline UNIQUE constraints.\n *\n * This module provides utilities to transform SMRT-generated schemas\n * (which use separate CREATE UNIQUE INDEX statements) into DuckDB-compatible\n * schemas (which use inline UNIQUE constraints).\n */\n\n/**\n * Index definition extracted from CREATE INDEX statement\n */\ninterface ParsedIndex {\n name: string;\n columns: string[];\n unique: boolean;\n sql: string;\n}\n\n/**\n * Parses a CREATE INDEX statement to extract index details\n *\n * @param indexSQL - CREATE INDEX statement\n * @returns Parsed index definition or null if parsing fails\n *\n * @example\n * ```typescript\n * const index = parseIndexStatement(\n * 'CREATE UNIQUE INDEX ds_slug_context_idx ON ds (slug, context)'\n * );\n * // Returns: {\n * // name: 'ds_slug_context_idx',\n * // columns: ['slug', 'context'],\n * // unique: true,\n * // sql: '...'\n * // }\n * ```\n */\nexport function parseIndexStatement(indexSQL: string): ParsedIndex | null {\n const trimmed = indexSQL.trim();\n\n // Match: CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON table (columns)\n // Support both quoted and unquoted identifiers: table, \"table\", columns, \"columns\"\n const match = trimmed.match(\n /CREATE\\s+(UNIQUE\\s+)?INDEX\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(\\w+)\\s+ON\\s+(?:\"?\\w+\"?)\\s*\\(([^)]+)\\)/i,\n );\n\n if (!match) {\n return null;\n }\n\n const [, uniqueKeyword, name, columnsStr] = match;\n\n // Remove quotes from column names\n const columns = columnsStr\n .split(',')\n .map((col) => col.trim().replace(/^\"|\"$/g, ''));\n\n return {\n name,\n columns,\n unique: Boolean(uniqueKeyword),\n sql: trimmed,\n };\n}\n\n/**\n * Converts UNIQUE INDEX statements to inline UNIQUE constraints for DuckDB compatibility\n *\n * DuckDB's ON CONFLICT clause requires inline UNIQUE constraints, not separate indexes.\n * This function transforms SMRT-generated schemas to work with DuckDB's limitations.\n *\n * @param ddl - CREATE TABLE DDL statement\n * @param indexes - Array of CREATE INDEX statements (optional)\n * @returns Transformed DDL with inline UNIQUE constraints and filtered index list\n *\n * @example\n * ```typescript\n * const ddl = `\n * CREATE TABLE ds (\n * id TEXT PRIMARY KEY,\n * slug TEXT NOT NULL,\n * context TEXT NOT NULL\n * )\n * `;\n * const indexes = [\n * 'CREATE UNIQUE INDEX ds_slug_context_idx ON ds (slug, context)'\n * ];\n *\n * const result = convertUniqueIndexesToInlineConstraints(ddl, indexes);\n * // result.ddl:\n * // CREATE TABLE ds (\n * // id TEXT PRIMARY KEY,\n * // slug TEXT NOT NULL,\n * // context TEXT NOT NULL,\n * // UNIQUE(slug, context)\n * // )\n * // result.indexes: [] (UNIQUE index removed, non-UNIQUE indexes preserved)\n * ```\n */\nexport function convertUniqueIndexesToInlineConstraints(\n ddl: string,\n indexes?: string[],\n): {\n ddl: string;\n indexes: string[];\n} {\n if (!indexes || indexes.length === 0) {\n return { ddl, indexes: [] };\n }\n\n // Parse all indexes\n const parsedIndexes = indexes\n .map(parseIndexStatement)\n .filter((idx): idx is ParsedIndex => idx !== null);\n\n // Separate UNIQUE indexes from regular indexes\n const uniqueIndexes = parsedIndexes.filter((idx) => idx.unique);\n const regularIndexes = parsedIndexes.filter((idx) => !idx.unique);\n\n // If no UNIQUE indexes, return unchanged\n if (uniqueIndexes.length === 0) {\n return { ddl, indexes };\n }\n\n // Find the closing parenthesis of the CREATE TABLE statement\n const lines = ddl.split('\\n');\n let closingParenIndex = -1;\n\n for (let i = lines.length - 1; i >= 0; i--) {\n const trimmed = lines[i].trim();\n if (trimmed === ')' || trimmed.startsWith(');')) {\n closingParenIndex = i;\n break;\n }\n }\n\n if (closingParenIndex === -1) {\n // Can't find closing paren - return unchanged\n console.warn(\n '[duckdb-schema-utils] Could not find closing parenthesis in CREATE TABLE statement',\n );\n return { ddl, indexes };\n }\n\n // Build inline UNIQUE constraints with quoted column names\n const uniqueConstraints = uniqueIndexes.map((idx) => {\n const columns = idx.columns.map((col) => `\"${col}\"`).join(', ');\n return ` UNIQUE(${columns})`;\n });\n\n // Insert UNIQUE constraints before closing parenthesis\n const modifiedLines = [...lines];\n const closingLine = modifiedLines[closingParenIndex].trim();\n\n // Add comma to previous line if it doesn't have one\n if (closingParenIndex > 0) {\n const prevLine = modifiedLines[closingParenIndex - 1].trim();\n if (!prevLine.endsWith(',')) {\n modifiedLines[closingParenIndex - 1] = modifiedLines[\n closingParenIndex - 1\n ].replace(/\\s*$/, ',');\n }\n }\n\n // Insert UNIQUE constraints\n const constraintLines = uniqueConstraints.map((constraint, idx) => {\n // Add comma after all but the last constraint\n return idx < uniqueConstraints.length - 1 ? `${constraint},` : constraint;\n });\n\n modifiedLines.splice(closingParenIndex, 0, ...constraintLines);\n\n const transformedDDL = modifiedLines.join('\\n');\n\n // Return regular (non-UNIQUE) indexes only\n const remainingIndexes = regularIndexes.map((idx) => idx.sql);\n\n return {\n ddl: transformedDDL,\n indexes: remainingIndexes,\n };\n}\n\n/**\n * Checks if a schema definition contains UNIQUE indexes that need conversion\n *\n * @param indexes - Array of CREATE INDEX statements\n * @returns True if any UNIQUE indexes are present\n */\nexport function hasUniqueIndexes(indexes?: string[]): boolean {\n if (!indexes || indexes.length === 0) {\n return false;\n }\n\n return indexes.some((indexSQL) => {\n const parsed = parseIndexStatement(indexSQL);\n return parsed?.unique === true;\n });\n}\n","/**\n * Database integrity-check framework.\n *\n * The runner is a thin loop over user-supplied checks; the value here is\n * the reusable check builders (expected tables, unique columns, FK-like\n * relationships) that codify the common shapes of integrity bugs that\n * sneak past schema migrations.\n *\n * No SMRT awareness — checks operate on the `DatabaseInterface` from this\n * package and on plain table/column names.\n *\n * **Postgres-only today.** The bundled check builders and\n * `listPublicTables` use Postgres syntax (`pg_tables`, `::int`/`::text`\n * casts). The shape is portable in principle — `DoctorContext` carries a\n * generic `DatabaseInterface` so apps can add engine-aware checks — but\n * the out-of-the-box runner expects a Postgres connection. `runDoctor`\n * throws early if pointed at a non-Postgres URL rather than failing\n * mid-execution with a confusing `pg_tables`-doesn't-exist error.\n */\nimport { redactDatabaseUrl } from './postgres-cli';\nimport type { DatabaseInterface } from './shared/types';\n\nexport type DoctorLevel = 'fail' | 'warn';\n\nexport interface DoctorIssue {\n level: DoctorLevel;\n message: string;\n}\n\nexport interface DoctorContext {\n db: DatabaseInterface;\n tables: Set<string>;\n}\n\nexport type DoctorCheck = (ctx: DoctorContext) => Promise<DoctorIssue[]>;\n\nexport interface RunDoctorOptions {\n db: DatabaseInterface;\n checks: DoctorCheck[];\n}\n\nexport interface DoctorResult {\n failures: DoctorIssue[];\n warnings: DoctorIssue[];\n issues: DoctorIssue[];\n}\n\n/**\n * Execute every check against the public-schema tables of `db` and\n * partition the results by severity. Returns the aggregate; callers\n * format/exit as they see fit.\n *\n * The current table set is enumerated once and shared across checks so\n * each check can cheaply decide whether its target tables exist.\n */\nexport async function runDoctor(\n options: RunDoctorOptions,\n): Promise<DoctorResult> {\n assertPostgresAdapter(options.db);\n const tables = await listPublicTables(options.db);\n const issues: DoctorIssue[] = [];\n\n for (const check of options.checks) {\n const checkIssues = await check({ db: options.db, tables });\n issues.push(...checkIssues);\n }\n\n return {\n failures: issues.filter((issue) => issue.level === 'fail'),\n warnings: issues.filter((issue) => issue.level === 'warn'),\n issues,\n };\n}\n\n/**\n * Throw early if the supplied database isn't Postgres. The check builders\n * and `listPublicTables` use Postgres syntax; pointing them at SQLite or\n * DuckDB would fail mid-execution with a confusing \"table pg_tables does\n * not exist\" error from the adapter. Fail fast with a useful message\n * instead.\n */\nfunction assertPostgresAdapter(db: DatabaseInterface): void {\n const url = String(db.url ?? '');\n if (!url.startsWith('postgres://') && !url.startsWith('postgresql://')) {\n throw new Error(\n `runDoctor requires a Postgres database connection. Got URL: ${url ? redactDatabaseUrl(url) : '(empty)'}. ` +\n 'The bundled check builders use Postgres-specific syntax (pg_tables, ::int/::text casts).',\n );\n }\n}\n\n/**\n * Emit a 'warn' for each table in `expected` that's missing.\n *\n * Marked as `warn` rather than `fail` because a missing table often\n * indicates a migration that hasn't been run yet, not active data\n * corruption — callers can promote to fail by mapping the issues.\n */\nexport function checkExpectedTables(expected: readonly string[]): DoctorCheck {\n return async ({ tables }) => {\n const issues: DoctorIssue[] = [];\n for (const table of expected) {\n if (!tables.has(table)) {\n issues.push({\n level: 'warn',\n message: `Missing expected table: ${table}`,\n });\n }\n }\n return issues;\n };\n}\n\nexport interface UniqueColumnSpec {\n table: string;\n column: string;\n /** Human-readable label used in the issue message. */\n label: string;\n}\n\n/**\n * Emit a 'fail' for each value that appears more than once in\n * `(table, column)` (ignoring NULL and empty-string values).\n *\n * Useful for catching slug/key collisions that the schema didn't\n * declare a UNIQUE constraint for (or where the constraint was added\n * after data already existed).\n */\nexport function checkUniqueColumn(spec: UniqueColumnSpec): DoctorCheck {\n return async ({ db, tables }) => {\n if (!tables.has(spec.table)) return [];\n const result = await db.query(`\n SELECT ${quoteIdentifier(spec.column)} AS value, count(*)::text AS count\n FROM ${quoteIdentifier(spec.table)}\n WHERE NULLIF(trim(${quoteIdentifier(spec.column)}::text), '') IS NOT NULL\n GROUP BY ${quoteIdentifier(spec.column)}\n HAVING count(*) > 1\n ORDER BY count DESC, ${quoteIdentifier(spec.column)}\n `);\n return result.rows.map((row) => ({\n level: 'fail' as const,\n message: `Duplicate ${spec.label} \"${String(row.value)}\" in ${spec.table} (${countValueFromRow(\n row.count,\n )} rows).`,\n }));\n };\n}\n\nexport interface RelationshipSpec {\n childTable: string;\n childColumn: string;\n parentTable: string;\n /** Defaults to 'id'. */\n parentColumn?: string;\n /** Human-readable label used in the issue message. */\n label: string;\n}\n\n/**\n * Emit a 'fail' counting orphan rows where the child column points at a\n * parent row that doesn't exist (FK-shaped check, but doesn't require an\n * actual FK constraint to be declared — useful for soft references like\n * tag-id-or-slug lookup columns).\n */\nexport function checkRelationship(spec: RelationshipSpec): DoctorCheck {\n return async ({ db, tables }) => {\n if (!tables.has(spec.childTable) || !tables.has(spec.parentTable))\n return [];\n const parentColumn = spec.parentColumn ?? 'id';\n const result = await db.query(`\n SELECT count(*)::text AS count\n FROM ${quoteIdentifier(spec.childTable)} child\n LEFT JOIN ${quoteIdentifier(spec.parentTable)} parent\n ON parent.${quoteIdentifier(parentColumn)} = child.${quoteIdentifier(spec.childColumn)}\n WHERE NULLIF(trim(child.${quoteIdentifier(spec.childColumn)}::text), '') IS NOT NULL\n AND parent.${quoteIdentifier(parentColumn)} IS NULL\n `);\n const orphanCount = countValueFromRow(result.rows[0]?.count);\n if (orphanCount === '0') return [];\n return [\n {\n level: 'fail',\n message: `${spec.label}: ${orphanCount} orphaned row${orphanCount === '1' ? '' : 's'}.`,\n },\n ];\n };\n}\n\nasync function listPublicTables(db: DatabaseInterface): Promise<Set<string>> {\n const result = await db.query(\n \"SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename\",\n );\n return new Set(result.rows.map((row) => String(row.tablename ?? '')));\n}\n\nfunction quoteIdentifier(value: string): string {\n return `\"${value.replace(/\"/gu, '\"\"')}\"`;\n}\n\nfunction countValueFromRow(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'bigint') {\n return String(value);\n }\n return '0';\n}\n","/**\n * Schema management and dependency resolution for JSON manifests\n * Moved from SMRT package to SQL package for proper separation of concerns\n */\n\nimport type {\n DatabaseInterface,\n IndexDefinition,\n SchemaDefinition,\n SchemaInitializationOptions,\n TriggerDefinition,\n} from './shared/types.js';\n\n/**\n * Result returned by DatabaseSchemaManager.initializeSchemas()\n *\n * Contains the list of schemas that were successfully initialized,\n * any that were skipped (already up to date), errors encountered,\n * and the total execution time in milliseconds.\n */\nexport interface SchemaInitializationResult {\n initialized: string[];\n skipped: string[];\n errors: Array<{ schema: string; error: string }>;\n executionTime: number;\n}\n\n/**\n * Manages schema initialization from JSON manifests with dependency resolution\n *\n * Handles topological sorting of schema dependencies, table creation,\n * index and trigger setup, and version tracking to avoid redundant re-initialization.\n */\nexport class DatabaseSchemaManager {\n private static initializationLock = new Map<string, Promise<void>>();\n private initializedSchemas = new Set<string>();\n private schemaVersions = new Map<string, string>();\n\n /**\n * Initializes database schemas from a JSON manifest with dependency resolution\n *\n * Schemas are topologically sorted by their declared dependencies and\n * initialized in order. Supports legacy raw-SQL schemas via the `schema` option,\n * JSON manifests via the `manifest` option, and schema overrides for extending\n * base schemas.\n *\n * @param db - Database interface to execute DDL against\n * @param options - Schema initialization options (manifest, overrides, force, debug)\n * @returns Result with lists of initialized/skipped schemas, errors, and execution time\n */\n async initializeSchemas(\n db: DatabaseInterface,\n options: SchemaInitializationOptions,\n ): Promise<SchemaInitializationResult> {\n const startTime = Date.now();\n const result: SchemaInitializationResult = {\n initialized: [],\n skipped: [],\n errors: [],\n executionTime: 0,\n };\n\n try {\n let schemas: Record<string, SchemaDefinition> = {};\n\n // Handle legacy SQL schema format\n if (options.schema) {\n console.log(\n '[schema] Legacy SQL schema provided, converting to manifest format',\n );\n // For legacy support, we'll still use the original syncSchema method\n if (db.syncSchema) {\n await db.syncSchema(options.schema);\n result.initialized.push('legacy-sql');\n }\n result.executionTime = Date.now() - startTime;\n return result;\n }\n\n // Handle JSON manifest format\n if (options.manifest) {\n schemas = { ...options.manifest.schemas };\n }\n\n // Apply schema overrides\n if (options.overrides) {\n schemas = { ...schemas, ...options.overrides };\n }\n\n if (Object.keys(schemas).length === 0) {\n console.warn('[schema] No schemas provided for initialization');\n result.executionTime = Date.now() - startTime;\n return result;\n }\n\n // Build dependency graph\n const dependencyGraph = this.buildDependencyGraph(schemas);\n\n // Get initialization order\n const initializationOrder = this.resolveDependencies(dependencyGraph);\n\n if (options.debug) {\n console.log('[schema] Initialization order:', initializationOrder);\n }\n\n // Initialize schemas in dependency order\n for (const schemaName of initializationOrder) {\n const schema = schemas[schemaName];\n if (!schema) continue;\n\n try {\n await this.initializeSchema(db, schemaName, schema, {\n force: options.force,\n debug: options.debug,\n });\n result.initialized.push(schemaName);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n result.errors.push({ schema: schemaName, error: errorMessage });\n\n if (options.debug) {\n console.error(\n `[schema] Failed to initialize ${schemaName}:`,\n error,\n );\n }\n }\n }\n\n result.executionTime = Date.now() - startTime;\n\n if (options.debug) {\n console.log('[schema] Initialization complete:', result);\n }\n\n return result;\n } catch (error) {\n result.executionTime = Date.now() - startTime;\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n result.errors.push({\n schema: 'dependency-resolution',\n error: errorMessage,\n });\n return result;\n }\n }\n\n /**\n * Initialize a single schema\n */\n private async initializeSchema(\n db: DatabaseInterface,\n schemaName: string,\n schema: SchemaDefinition,\n options: { force?: boolean; debug?: boolean },\n ): Promise<void> {\n const { tableName, version } = schema;\n const lockKey = `${schemaName}:${tableName}`;\n\n // Check if already being initialized\n if (DatabaseSchemaManager.initializationLock.has(lockKey)) {\n await DatabaseSchemaManager.initializationLock.get(lockKey);\n return;\n }\n\n // Check if already initialized and up to date\n if (!options.force && this.isSchemaUpToDate(schemaName, version)) {\n if (options.debug) {\n console.log(`[schema] Skipping ${schemaName} - already up to date`);\n }\n return;\n }\n\n // Create initialization promise\n const initPromise = this.performSchemaInitialization(\n db,\n schemaName,\n schema,\n options,\n );\n DatabaseSchemaManager.initializationLock.set(lockKey, initPromise);\n\n try {\n await initPromise;\n this.markSchemaInitialized(schemaName, version);\n } finally {\n DatabaseSchemaManager.initializationLock.delete(lockKey);\n }\n }\n\n /**\n * Perform the actual schema initialization\n */\n private async performSchemaInitialization(\n db: DatabaseInterface,\n schemaName: string,\n schema: SchemaDefinition,\n options: { force?: boolean; debug?: boolean },\n ): Promise<void> {\n const { tableName, columns, indexes, triggers } = schema;\n\n if (options.debug) {\n console.log(`[schema] Initializing ${schemaName} (${tableName})`);\n }\n\n // Check if table exists\n const tableExists = await db.tableExists(tableName);\n\n if (!tableExists) {\n // Create table\n await this.createTable(db, schema);\n\n // Create indexes\n for (const index of indexes) {\n await this.createIndex(db, tableName, index);\n }\n\n // Create triggers\n for (const trigger of triggers) {\n await this.createTrigger(db, trigger);\n }\n } else if (options.force) {\n // Recreate table if forced\n await db.query(`DROP TABLE IF EXISTS ${tableName}`);\n await this.createTable(db, schema);\n\n for (const index of indexes) {\n await this.createIndex(db, tableName, index);\n }\n\n for (const trigger of triggers) {\n await this.createTrigger(db, trigger);\n }\n } else {\n // Table exists, check for schema changes\n await this.updateSchemaIfNeeded(db, schema);\n }\n }\n\n /**\n * Create table from schema definition\n */\n private async createTable(\n db: DatabaseInterface,\n schema: SchemaDefinition,\n ): Promise<void> {\n const { tableName, columns, foreignKeys } = schema;\n\n const columnDefinitions: string[] = [];\n\n // Add column definitions\n for (const [columnName, columnDef] of Object.entries(columns)) {\n let def = `${columnName} ${columnDef.type}`;\n\n if (columnDef.primaryKey) def += ' PRIMARY KEY';\n if (columnDef.unique && !columnDef.primaryKey) def += ' UNIQUE';\n if (columnDef.notNull) def += ' NOT NULL';\n if (columnDef.defaultValue !== undefined) {\n def += ` DEFAULT ${columnDef.defaultValue}`;\n }\n if (columnDef.check) def += ` CHECK (${columnDef.check})`;\n\n columnDefinitions.push(def);\n }\n\n // Add foreign key constraints\n for (const fk of foreignKeys) {\n let fkDef = `FOREIGN KEY (${fk.column}) REFERENCES ${fk.referencesTable}(${fk.referencesColumn})`;\n if (fk.onDelete) fkDef += ` ON DELETE ${fk.onDelete}`;\n if (fk.onUpdate) fkDef += ` ON UPDATE ${fk.onUpdate}`;\n columnDefinitions.push(fkDef);\n }\n\n const createTableSQL = `CREATE TABLE ${tableName} (\\n ${columnDefinitions.join(',\\n ')}\\n)`;\n await db.query(createTableSQL);\n }\n\n /**\n * Create index from definition\n */\n private async createIndex(\n db: DatabaseInterface,\n tableName: string,\n index: IndexDefinition,\n ): Promise<void> {\n const uniqueClause = index.unique ? 'UNIQUE ' : '';\n const whereClause = index.where ? ` WHERE ${index.where}` : '';\n const createIndexSQL = `CREATE ${uniqueClause}INDEX ${index.name} ON ${tableName} (${index.columns.join(', ')})${whereClause}`;\n\n await db.query(createIndexSQL);\n }\n\n /**\n * Create trigger from definition\n */\n private async createTrigger(\n db: DatabaseInterface,\n trigger: TriggerDefinition,\n ): Promise<void> {\n const conditionClause = trigger.condition\n ? ` WHEN ${trigger.condition}`\n : '';\n const createTriggerSQL = `CREATE TRIGGER ${trigger.name} ${trigger.when} ${trigger.event} ON ${trigger.table}${conditionClause} BEGIN ${trigger.body} END`;\n\n await db.query(createTriggerSQL);\n }\n\n /**\n * Update schema if changes are detected\n */\n private async updateSchemaIfNeeded(\n _db: DatabaseInterface,\n schema: SchemaDefinition,\n ): Promise<void> {\n // For now, just log that update is needed\n // In future, implement ALTER TABLE logic\n console.log(\n `[schema] Schema update logic not yet implemented for ${schema.tableName}`,\n );\n }\n\n /**\n * Build dependency graph from schemas\n */\n private buildDependencyGraph(\n schemas: Record<string, SchemaDefinition>,\n ): Map<string, string[]> {\n const graph = new Map<string, string[]>();\n\n for (const [schemaName, schema] of Object.entries(schemas)) {\n const dependencies = schema.dependencies.filter((dep) =>\n Object.values(schemas).some((s) => s.tableName === dep),\n );\n graph.set(\n schemaName,\n dependencies.map(\n (dep) =>\n Object.entries(schemas).find(\n ([_, s]) => s.tableName === dep,\n )?.[0] || dep,\n ),\n );\n }\n\n return graph;\n }\n\n /**\n * Resolve dependencies using topological sort\n */\n private resolveDependencies(graph: Map<string, string[]>): string[] {\n const resolved: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (node: string) => {\n if (visiting.has(node)) {\n throw new Error(`Circular dependency detected involving ${node}`);\n }\n if (visited.has(node)) return;\n\n visiting.add(node);\n const dependencies = graph.get(node) || [];\n\n for (const dep of dependencies) {\n if (graph.has(dep)) {\n visit(dep);\n }\n }\n\n visiting.delete(node);\n visited.add(node);\n resolved.push(node);\n };\n\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n visit(node);\n }\n }\n\n return resolved;\n }\n\n /**\n * Check if schema is up to date\n */\n private isSchemaUpToDate(schemaName: string, version: string): boolean {\n return (\n this.initializedSchemas.has(schemaName) &&\n this.schemaVersions.get(schemaName) === version\n );\n }\n\n /**\n * Mark schema as initialized\n */\n private markSchemaInitialized(schemaName: string, version: string): void {\n this.initializedSchemas.add(schemaName);\n this.schemaVersions.set(schemaName, version);\n }\n\n /**\n * Reset initialization state (for testing)\n */\n reset(): void {\n this.initializedSchemas.clear();\n this.schemaVersions.clear();\n DatabaseSchemaManager.initializationLock.clear();\n }\n}\n","/**\n * WHERE clause input for database queries\n *\n * Supports two formats:\n * 1. Object format (AND-only): `{ status: 'active', 'price >': 100 }`\n * - All conditions are AND-joined\n *\n * 2. 2D array format (OR/AND compound logic): `[[cond1, cond2], [cond3, cond4]]`\n * - Inner arrays are AND-joined: `(cond1 AND cond2)`\n * - Outer array is OR-joined: `(cond1 AND cond2) OR (cond3 AND cond4)`\n *\n * @example Object format (backward compatible)\n * ```typescript\n * // WHERE status = 'active' AND price > 100\n * const where = { status: 'active', 'price >': 100 };\n * ```\n *\n * @example 2D array format for OR/AND compound logic\n * ```typescript\n * // WHERE (status = 'active' AND price > 100) OR (status = 'pending' AND priority = 'high')\n * const where = [\n * [{ status: 'active' }, { 'price >': 100 }],\n * [{ status: 'pending' }, { priority: 'high' }]\n * ];\n * ```\n */\nexport type WhereClause = Record<string, any> | Record<string, any>[][];\n\n/**\n * Common database connection options\n */\nexport interface DatabaseOptions {\n /**\n * Database connection URL\n */\n url?: string;\n\n /**\n * Authentication token for the database connection\n */\n authToken?: string;\n}\n\n/**\n * DuckDB-specific connection options\n */\nexport interface DuckDBOptions extends DatabaseOptions {\n /**\n * Database type identifier\n */\n type?: 'duckdb';\n\n /**\n * Path to directory containing JSON files to auto-register as tables\n * @default './data'\n */\n dataDir?: string;\n\n /**\n * Automatically register JSON files in dataDir as queryable tables\n * @default true\n */\n autoRegisterJSON?: boolean;\n\n /**\n * Strategy for writing data back to JSON files\n * - 'immediate': Write changes to JSON files immediately\n * - 'manual': Require explicit export calls\n * - 'none': Read-only mode, no writes to JSON files\n * @default 'none'\n */\n writeStrategy?: 'immediate' | 'manual' | 'none';\n\n /**\n * Whether to use a persistent DuckDB file for caching/indexes\n * If true, uses url or defaults to ':memory:'\n * @default false\n */\n persistent?: boolean;\n\n /**\n * Explicit schema definitions for tables\n * When provided, these schemas will be used for table creation\n */\n schemas?: SchemasOption;\n}\n\n/**\n * JSON database adapter options (DuckDB-backed)\n *\n * Uses DuckDB's in-memory engine to query JSON files directly.\n * No WAL files or persistent database files are created.\n */\nexport interface JSONOptions {\n /**\n * Database type identifier\n */\n type: 'json';\n\n /**\n * Path to directory containing JSON files (required)\n * JSON files in this directory will be loaded as queryable tables\n */\n url: string;\n\n /**\n * Automatically load all JSON files in dataDir as tables\n * @default true\n */\n autoRegister?: boolean;\n\n /**\n * Strategy for writing changes back to JSON files\n * - 'immediate': Auto-save after every insert/update (default)\n * - 'manual': Require explicit exportTable() calls\n * - 'none': Read-only mode, throws error on writes\n * @default 'immediate'\n */\n writeStrategy?: 'immediate' | 'manual' | 'none';\n\n /**\n * Explicit schema definitions for tables\n *\n * When provided, these schemas will be used instead of auto-detection.\n * This allows frameworks to provide explicit schemas via dependency injection.\n *\n * @example\n * ```typescript\n * const db = await getDatabase({\n * type: 'json',\n * url: './data',\n * schemas: {\n * users: {\n * tableName: 'users',\n * ddl: 'CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT)',\n * indexes: ['CREATE INDEX idx_users_name ON users(name)']\n * }\n * }\n * });\n * ```\n */\n schemas?: SchemasOption;\n\n /**\n * Unique identifier for in-memory DuckDB instances to enable connection sharing\n * When multiple getDatabase() calls use the same dbid, they receive\n * the same database connection instance.\n *\n * Auto-generated if not provided, enabling connection sharing by default.\n * This solves the issue where multiple collections create separate in-memory\n * databases that can't see each other's tables.\n */\n dbid?: string;\n\n /**\n * Eagerly load all JSON files as tables at connection time\n *\n * When true (default), creates tables with inferred schemas for all JSON files\n * in the data directory, even those without explicit schemas or .schema.sql files.\n * This enables cross-table queries (JOINs, NOT EXISTS subqueries) before\n * syncSchema() is called.\n *\n * Note: Inferred schemas don't include UNIQUE constraints. UPSERT operations\n * require syncSchema() to be called first to establish proper constraints.\n * When syncSchema() is called, tables with inferred schemas are dropped and\n * recreated with the proper schema.\n *\n * @default true\n */\n eagerLoadTables?: boolean;\n\n /**\n * Force a fresh database connection, bypassing the connection cache\n *\n * When true, clears any cached connection for this URL before creating a new one.\n * Useful when you need to reload the database from disk after external changes.\n *\n * @default false\n *\n * @example\n * // Initial connection - cached\n * const db1 = await getDatabase({ type: 'json', url: './data' });\n *\n * // External process adds JSON files...\n *\n * // Force reload from disk\n * const db2 = await getDatabase({\n * type: 'json',\n * url: './data',\n * clearCache: true\n * });\n */\n clearCache?: boolean;\n}\n\n/**\n * Result of a database operation that modifies data\n */\nexport interface QueryResult {\n /**\n * Type of operation performed (e.g., \"insert\", \"update\", \"delete\")\n */\n operation: string;\n\n /**\n * Number of rows affected by the operation\n */\n affected: number;\n}\n\n/**\n * Options for upsert operations.\n */\nexport interface UpsertOptions {\n /**\n * Preserve database-native NULL-distinct conflict behavior.\n *\n * By default, upsert treats NULL values in conflict columns as matching\n * existing NULL values. Set this to true to opt out and use the underlying\n * database's native ON CONFLICT behavior where NULLs are distinct.\n */\n nullsDistinct?: boolean;\n}\n\n/**\n * Schema definition that can be provided to database adapters\n *\n * Allows frameworks like SMRT to provide explicit schemas instead of\n * relying on auto-detection or circular dependencies.\n *\n * This is a simpler, DDL-based alternative to SchemaDefinition which is\n * used for structured JSON manifests.\n */\nexport interface SchemaProvider {\n /**\n * Table name in snake_case plural form\n */\n tableName: string;\n\n /**\n * DDL statement(s) to create the table\n * Can be a single CREATE TABLE statement or multiple statements\n */\n ddl: string;\n\n /**\n * Index creation statements (optional)\n * Each string should be a complete CREATE INDEX statement\n */\n indexes?: string[];\n\n /**\n * Trigger creation statements (optional, adapter-specific support)\n * Each string should be a complete CREATE TRIGGER statement\n */\n triggers?: string[];\n\n /**\n * Schema version for migration tracking (optional)\n */\n version?: string;\n\n /**\n * Field metadata (optional, for advanced use cases)\n * Can be used by frameworks for runtime type information and validation\n */\n fields?: Map<string, any>;\n}\n\n/**\n * Schema definitions for getDatabase(), either eagerly built or lazy.\n *\n * Callers can pass schemas as a lazy function so that building the schema\n * map (potentially 200+ objects from ObjectRegistry) is deferred until an\n * adapter actually needs it. Adapters that manage tables via migrations\n * (Postgres, SQLite) never call the function, making the cost zero.\n *\n * @example Lazy — only resolved by JSON/DuckDB adapters\n * ```typescript\n * await getDatabase({\n * type: 'postgres',\n * url: '...',\n * schemas: () => ObjectRegistry.getAllSchemas(), // never called\n * });\n * ```\n *\n * @example Eager — built upfront (fine for JSON/DuckDB)\n * ```typescript\n * await getDatabase({\n * type: 'json',\n * url: './data',\n * schemas: { users: { tableName: 'users', ddl: '...' } },\n * });\n * ```\n */\nexport type SchemasOption =\n | Record<string, SchemaProvider>\n | (() => Record<string, SchemaProvider>);\n\n/**\n * Resolves a SchemasOption to its concrete value.\n *\n * Adapters that need schemas (JSON, DuckDB) call this to unwrap the\n * lazy function. Adapters that don't (Postgres, SQLite) simply ignore\n * the `schemas` option without calling this.\n */\nexport function resolveSchemas(\n schemas: SchemasOption | undefined,\n): Record<string, SchemaProvider> | undefined {\n if (!schemas) return undefined;\n if (typeof schemas === 'function') return schemas();\n return schemas;\n}\n\n/**\n * Schema manifest structure for JSON-based schema management\n */\nexport interface SchemaManifest {\n version: string;\n timestamp: number;\n packageName: string;\n schemas: Record<string, SchemaDefinition>;\n dependencies: string[];\n}\n\n/**\n * Schema definition for individual tables\n */\nexport interface SchemaDefinition {\n tableName: string;\n columns: Record<string, ColumnDefinition>;\n indexes: IndexDefinition[];\n triggers: TriggerDefinition[];\n foreignKeys: ForeignKeyDefinition[];\n dependencies: string[];\n version: string;\n packageName: string;\n baseClass?: string;\n}\n\n/**\n * Column definition structure\n */\nexport interface ColumnDefinition {\n type: string;\n primaryKey?: boolean;\n unique?: boolean;\n notNull?: boolean;\n defaultValue?: any;\n check?: string;\n foreignKey?: {\n table: string;\n column: string;\n onDelete?: string;\n onUpdate?: string;\n };\n description?: string;\n}\n\n/**\n * Column definition with name for ALTER TABLE operations\n */\nexport interface ColumnDefinitionWithName extends ColumnDefinition {\n name: string;\n}\n\n/**\n * Index definition structure\n */\nexport interface IndexDefinition {\n name: string;\n columns: string[];\n unique?: boolean;\n where?: string;\n description?: string;\n}\n\n/**\n * Trigger definition structure\n */\nexport interface TriggerDefinition {\n name: string;\n when: string;\n event: string;\n table: string;\n condition?: string;\n body: string;\n description?: string;\n}\n\n/**\n * Foreign key constraint definition\n */\nexport interface ForeignKeyDefinition {\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete?: string;\n onUpdate?: string;\n}\n\n/**\n * Options for schema initialization and management\n */\nexport interface SchemaInitializationOptions {\n /** Schema manifest containing table definitions */\n manifest?: SchemaManifest;\n /** Raw SQL DDL schema string (legacy support) */\n schema?: string;\n /** Schema overrides for extending base schemas */\n overrides?: Record<string, SchemaDefinition>;\n /** Force recreation of tables */\n force?: boolean;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Table schema information returned by getTableSchema()\n */\nexport interface TableSchemaInfo {\n /** Table name */\n tableName: string;\n /** Columns in the table */\n columns: Record<string, ColumnDefinition>;\n /** Indexes on the table */\n indexes: IndexDefinition[];\n /** Foreign key constraints */\n foreignKeys: ForeignKeyDefinition[];\n}\n\n/**\n * Options for vector similarity search\n */\nexport interface VectorSearchOptions {\n /** Maximum number of results to return */\n limit?: number;\n /** Distance metric for similarity comparison @default 'cosine' */\n metric?: 'cosine' | 'l2' | 'ip';\n /**\n * Additional SQL WHERE clause.\n * Use $2, $3, etc. for parameter placeholders ($1 is reserved for the query vector).\n * @example `category = $2`\n */\n where?: string;\n /** Parameters for the WHERE clause, bound to $2, $3, etc. */\n params?: any[];\n}\n\n/**\n * Result of a vector similarity search\n */\nexport interface VectorSearchResult {\n /** Row primary key */\n id: string;\n /**\n * Distance from query vector (lower = more similar).\n * Range varies by metric: cosine [0, 2], L2 [0, Infinity), ip (-Infinity, Infinity).\n */\n distance: number;\n /** Additional columns from the row */\n [key: string]: any;\n}\n\n/**\n * Options for creating a vector index\n */\nexport interface VectorIndexOptions {\n /** Number of dimensions (informational only, dimensions are set via ensureColumn) */\n dimensions?: number;\n /** Distance metric @default 'cosine' */\n metric?: 'cosine' | 'l2' | 'ip';\n /** Index type @default 'hnsw' */\n type?: 'hnsw' | 'ivfflat';\n}\n\n/**\n * Vector operations capability for database adapters\n *\n * Provides native vector similarity search, storage, and indexing.\n * Implemented by PostgreSQL via pgvector and optionally by SQLite via\n * sqlite-vector.\n */\nexport interface VectorCapabilities {\n /**\n * Search for similar vectors\n *\n * @param table - Table containing vector column\n * @param column - Name of the vector column\n * @param embedding - Query vector\n * @param options - Search options\n * @returns Ranked results by similarity\n */\n search(\n table: string,\n column: string,\n embedding: number[],\n options?: VectorSearchOptions,\n ): Promise<VectorSearchResult[]>;\n\n /**\n * Ensure a vector column exists on a table\n *\n * @param table - Table name\n * @param column - Column name\n * @param dimensions - Number of vector dimensions\n */\n ensureColumn(\n table: string,\n column: string,\n dimensions: number,\n ): Promise<void>;\n\n /**\n * Ensure a vector index exists on a column\n *\n * @param table - Table name\n * @param column - Column name\n * @param options - Index options\n */\n ensureIndex(\n table: string,\n column: string,\n options?: VectorIndexOptions,\n ): Promise<void>;\n\n /**\n * Store or update a vector in a specific row\n *\n * @param table - Table name\n * @param where - Conditions to identify the row\n * @param column - Vector column name\n * @param embedding - Vector data\n */\n upsertVector(\n table: string,\n where: Record<string, any>,\n column: string,\n embedding: number[],\n ): Promise<void>;\n}\n\n/**\n * SQLite notification delivered by optional notification capabilities.\n */\nexport interface DatabaseNotification {\n id: number;\n channel: string;\n payload: any;\n createdAt?: number | string | Date | null;\n}\n\n/**\n * Options for notification listeners.\n */\nexport interface NotificationListenOptions {\n /**\n * Fallback poll interval in milliseconds when the native watcher does not\n * receive an update signal.\n */\n fallbackPollMs?: number | null;\n}\n\n/**\n * Options for waiting on the next database update.\n */\nexport interface NotificationWaitOptions {\n /**\n * Maximum time to wait in milliseconds. When omitted, waits indefinitely.\n */\n timeoutMs?: number;\n\n /**\n * Optional abort signal to cancel the wait.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for pruning persisted notification rows.\n */\nexport interface NotificationPruneOptions {\n /** Delete notifications older than this many seconds. */\n olderThanS?: number | null;\n /** Keep at most this many most-recent notifications. */\n maxKeep?: number | null;\n}\n\n/**\n * Optional notification/pub-sub capabilities for database adapters.\n */\nexport interface NotificationCapabilities {\n notify(channel: string, payload: any): Promise<number>;\n listen(\n channel: string,\n options?: NotificationListenOptions,\n ): AsyncIterable<DatabaseNotification>;\n waitForUpdate(options?: NotificationWaitOptions): Promise<boolean>;\n prune(options?: NotificationPruneOptions): Promise<number>;\n}\n\n/**\n * Options for SQLite native notification support.\n */\nexport interface SqliteNotificationCapabilityOptions {\n watcherBackend?: 'polling' | 'kernel' | 'shm';\n maxReaders?: number;\n}\n\n/**\n * Options for SQLite native vector support.\n */\nexport interface SqliteVectorCapabilityOptions {\n preload?: boolean;\n quantization?: 'turbo4' | 'turbo3' | 'turbo2' | 'uint8' | 'int8' | '1bit';\n maxMemory?: string;\n}\n\n/**\n * Optional SQLite-only native capabilities.\n */\nexport interface SqliteCapabilitiesOptions {\n notifications?: boolean | SqliteNotificationCapabilityOptions;\n vector?: boolean | SqliteVectorCapabilityOptions;\n}\n\n/**\n * Common interface for database adapters\n * Provides a unified API for different database backends\n */\nexport interface DatabaseInterface {\n /**\n * Database location identifier\n * For file-based databases: file path\n * For directory-based databases (JSON/DuckDB with JSON): directory path\n * For in-memory databases: ':memory:'\n * For remote databases: connection URL\n */\n url: string;\n\n /**\n * Underlying database client instance\n */\n client: any;\n\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n */\n insert: (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ) => Promise<QueryResult>;\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to matching record or null if not found\n */\n get: (\n table: string,\n where: WhereClause,\n ) => Promise<Record<string, any> | null>;\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to array of matching records\n */\n list: (table: string, where: WhereClause) => Promise<Record<string, any>[]>;\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update (object for AND-only, 2D array for OR/AND)\n * @param data - New data to set\n * @returns Promise resolving to operation result\n */\n update: (\n table: string,\n where: WhereClause,\n data: Record<string, any>,\n ) => Promise<QueryResult>;\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n * Uses database-specific ON CONFLICT / ON DUPLICATE KEY syntax\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n *\n * @example\n * ```typescript\n * // Upsert a user by email\n * await db.upsert('users', ['email'], {\n * email: 'user@example.com',\n * name: 'John Doe',\n * updated_at: new Date().toISOString()\n * });\n *\n * // Upsert with composite key\n * await db.upsert('settings', ['user_id', 'key'], {\n * user_id: '123',\n * key: 'theme',\n * value: 'dark'\n * });\n * ```\n */\n upsert: (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ) => Promise<QueryResult>;\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record (object for AND-only, 2D array for OR/AND)\n * @param data - Data to insert if no record found\n * @returns Promise resolving to the record (either retrieved or newly inserted)\n */\n getOrInsert: (\n table: string,\n where: WhereClause,\n data: Record<string, any>,\n ) => Promise<Record<string, any>>;\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to operation result with count of deleted rows\n *\n * @example\n * ```typescript\n * // Delete by ID\n * await db.delete('products', { id: 'prod-123' });\n *\n * // Delete by criteria\n * await db.delete('orders', { status: 'cancelled' });\n *\n * // Delete with multiple conditions\n * await db.delete('sessions', {\n * user_id: 'user-123',\n * expired: true\n * });\n * ```\n */\n delete: (table: string, where: WhereClause) => Promise<QueryResult>;\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted; object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to count of matching records\n *\n * @example\n * ```typescript\n * // Count all records\n * const total = await db.count('products');\n *\n * // Count with single condition\n * const activeCount = await db.count('products', { active: true });\n *\n * // Count with multiple conditions\n * const filteredCount = await db.count('orders', {\n * status: 'pending',\n * priority: 'high'\n * });\n * ```\n */\n count: (table: string, where?: WhereClause) => Promise<number>;\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param table - Table name\n * @returns TableInterface for the specified table\n */\n table: (table: string) => TableInterface;\n\n /**\n * Checks if a table exists in the database\n *\n * @param table - Table name\n * @returns Promise resolving to boolean indicating existence\n */\n tableExists: (table: string) => Promise<boolean>;\n\n /**\n * Whether this adapter requires schema existence checks at runtime.\n *\n * Set to `true` on adapters where tables may not exist yet and need\n * to be verified before use (e.g. JSON/DuckDB with auto-created tables).\n *\n * When absent or `false`, frameworks skip `tableExists()` calls during\n * collection initialization — tables are assumed to exist because\n * schema is managed by migrations (e.g. `smrt db:migrate`).\n *\n * - Postgres adapter: not set (migration-managed)\n * - SQLite adapter: not set (migration-managed)\n * - JSON/DuckDB adapter: `true` (tables may be auto-created)\n */\n requiresSchemaCheck?: boolean;\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n */\n many: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any>[]>;\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n */\n single: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any> | null>;\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n */\n pluck: (strings: TemplateStringsArray, ...vars: any[]) => Promise<any>;\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n */\n execute: (strings: TemplateStringsArray, ...vars: any[]) => Promise<void>;\n\n /**\n * Alias for many() - Executes a SQL query and returns multiple rows\n */\n oo: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any>[]>;\n\n /**\n * Alias for single() - Executes a SQL query and returns a single row\n */\n oO: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any> | null>;\n\n /**\n * Alias for pluck() - Executes a SQL query and returns a single value\n */\n ox: (strings: TemplateStringsArray, ...vars: any[]) => Promise<any>;\n\n /**\n * Alias for execute() - Executes a SQL query without returning results\n */\n xx: (strings: TemplateStringsArray, ...vars: any[]) => Promise<void>;\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * Raw queries use the adapter's native placeholder syntax.\n * Parameters may be passed as rest arguments or as one values array.\n * For adapter-specific array parameter caveats, see the package docs.\n *\n * @param str - SQL query string\n * @param vars - Variables to use as parameters\n * @returns Promise resolving to query result with rows and count\n */\n query: (\n str: string,\n ...vars: any[]\n ) => Promise<{ rows: Record<string, any>[]; rowCount: number }>;\n\n /**\n * Synchronizes database schema with provided SQL DDL\n * Creates tables if they don't exist and adds missing columns\n *\n * @param schema - SQL schema definition with CREATE TABLE statements\n * @returns Promise that resolves when schema is synchronized\n */\n syncSchema?: (schema: string) => Promise<void>;\n\n /**\n * Initialize database schemas from JSON manifest\n * Supports dependency resolution and schema overrides\n *\n * @param options - Schema initialization options\n * @returns Promise that resolves when schemas are initialized\n */\n initializeSchemas?: (options: SchemaInitializationOptions) => Promise<void>;\n\n /**\n * Executes a callback within a database transaction\n * Automatically commits on success or rolls back on error\n *\n * @param callback - Function to execute within transaction\n * @returns Promise resolving to callback result\n */\n transaction?: <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ) => Promise<T>;\n\n /**\n * Begins a new transaction and returns a handle for manual control\n *\n * Unlike transaction(), this gives you explicit control over commit/rollback.\n * Ideal for test isolation where you want to rollback after each test.\n *\n * @returns Promise resolving to a TransactionHandle\n *\n * @example Test isolation pattern\n * ```typescript\n * let tx: TransactionHandle;\n *\n * beforeEach(async () => {\n * tx = await db.beginTransaction();\n * });\n *\n * afterEach(async () => {\n * await tx.rollback(); // Discard all test changes\n * });\n *\n * it('creates user', async () => {\n * await tx.insert('users', { id: '1', name: 'Test' });\n * const user = await tx.get('users', { id: '1' });\n * expect(user).toBeDefined();\n * // Changes rolled back in afterEach\n * });\n * ```\n */\n beginTransaction?: () => Promise<TransactionHandle>;\n\n /**\n * Acquire a pinned single-connection session.\n *\n * Returns a {@link SessionHandle} whose queries all run on one underlying\n * connection, enabling session-scoped state (e.g. PostgreSQL session advisory\n * locks) that the pooled top-level {@link query} cannot hold reliably. The\n * caller must {@link SessionHandle.release} it.\n *\n * Only meaningful for engines with session-scoped state, so it is currently\n * implemented for PostgreSQL only; check for the method before calling\n * (`if (db.acquireSession)`). Single-connection engines (SQLite, DuckDB) have\n * no session-scoped locks to hold, so they leave it undefined.\n *\n * @returns Promise resolving to a SessionHandle\n *\n * @example Hold a Postgres session advisory lock\n * ```typescript\n * const session = await db.acquireSession();\n * try {\n * await session.query('SELECT pg_advisory_lock($1)', 42);\n * // ... lock is held for the life of this session ...\n * } finally {\n * await session.release(); // frees the lock and drops the connection\n * }\n * ```\n */\n acquireSession?: () => Promise<SessionHandle>;\n\n /**\n * Retrieves the schema information for a table\n *\n * @param table - Table name\n * @returns Promise resolving to table schema info or null if table doesn't exist\n */\n getTableSchema?: (table: string) => Promise<TableSchemaInfo | null>;\n\n /**\n * Vector operations for native similarity search\n *\n * When available, enables database-level vector operations (e.g., pgvector).\n * Consumers should check for this capability rather than checking the database type.\n */\n vector?: VectorCapabilities;\n\n /**\n * Optional notification/pub-sub operations.\n */\n notifications?: NotificationCapabilities;\n\n /**\n * Close the database adapter and release native resources when supported.\n */\n close?: () => Promise<void>;\n\n /**\n * ALTER TABLE operations for schema evolution\n */\n alterTable?: {\n /**\n * Adds a new column to an existing table\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @returns Promise that resolves when column is added\n */\n addColumn: (\n table: string,\n column: ColumnDefinitionWithName,\n ) => Promise<void>;\n\n /**\n * Adds a new index to an existing table\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns Promise that resolves when index is created\n */\n addIndex: (table: string, index: IndexDefinition) => Promise<void>;\n };\n}\n\n/**\n * Transaction handle for manual transaction control\n *\n * Extends DatabaseInterface with commit() and rollback() methods.\n * Use beginTransaction() to obtain a handle, then explicitly\n * commit or rollback when done.\n *\n * @example Test isolation with rollback\n * ```typescript\n * const tx = await db.beginTransaction();\n * try {\n * // All operations happen in the transaction\n * await tx.insert('users', { id: '1', name: 'Test' });\n * const user = await tx.get('users', { id: '1' });\n *\n * // Rollback discards all changes (useful for test isolation)\n * await tx.rollback();\n * } catch (error) {\n * await tx.rollback();\n * throw error;\n * }\n * ```\n *\n * @example Manual commit\n * ```typescript\n * const tx = await db.beginTransaction();\n * try {\n * await tx.insert('orders', { id: '1', total: 100 });\n * await tx.insert('order_items', { order_id: '1', product: 'Widget' });\n * await tx.commit(); // Persist changes\n * } catch (error) {\n * await tx.rollback();\n * throw error;\n * }\n * ```\n */\nexport interface TransactionHandle extends DatabaseInterface {\n /**\n * Commits the transaction, persisting all changes\n *\n * After commit, the transaction handle should not be used.\n */\n commit: () => Promise<void>;\n\n /**\n * Rolls back the transaction, discarding all changes\n *\n * After rollback, the transaction handle should not be used.\n * This is the key method for test isolation - rollback after each test.\n */\n rollback: () => Promise<void>;\n\n /**\n * Whether the transaction is still active (not committed or rolled back)\n */\n isActive: () => boolean;\n}\n\n/**\n * Pinned single-connection session handle.\n *\n * Obtained via {@link DatabaseInterface.acquireSession}. Unlike the pooled\n * top-level `query` (which may run each statement on a different connection),\n * every call on a session handle runs on the *same* underlying connection for\n * the handle's lifetime. This is required for session-scoped state such as\n * PostgreSQL session advisory locks (`pg_advisory_lock`), which must be\n * acquired, observed, and released on one connection — and which release\n * automatically if the connection drops (e.g. the process dies).\n *\n * A session holds one connection out of the pool (default max 20) for its\n * entire lifetime, so it is meant to be held one-per-process, not per-operation.\n * Always {@link SessionHandle.release} the handle when done, and release it\n * *before* calling `db.client.end()` — a pinned connection keeps `pool.end()`\n * from resolving.\n */\nexport interface SessionHandle {\n /**\n * Execute a raw query on this session's pinned connection.\n * Same placeholder/return contract as {@link DatabaseInterface.query}.\n * Throws if the session has been released or its connection was lost.\n */\n query: (\n sql: string,\n ...vars: any[]\n ) => Promise<{ rows: Record<string, any>[]; rowCount: number }>;\n\n /**\n * Whether the session is still usable — not released and its connection has\n * not errored/dropped. A long-lived lock holder can poll this without\n * issuing a query.\n */\n isActive: () => boolean;\n\n /**\n * Release the session. Idempotent. After release the handle must not be used.\n * Best-effort frees session-scoped locks, then drops the underlying\n * connection (it is NOT returned to the pool) so the database releases any\n * remaining session state — returning it to the pool would leak that state\n * onto a later, unrelated checkout.\n */\n release: () => Promise<void>;\n}\n\n/**\n * Simplified interface for table-specific operations\n */\nexport interface TableInterface {\n /**\n * Inserts one or more records into the table\n *\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n */\n insert: (\n data: Record<string, any> | Record<string, any>[],\n ) => Promise<QueryResult>;\n\n /**\n * Retrieves a single record from the table matching the where criteria\n *\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to matching record or null if not found\n */\n get: (where: WhereClause) => Promise<Record<string, any> | null>;\n\n /**\n * Retrieves multiple records from the table matching the where criteria\n *\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to array of matching records\n */\n list: (where: WhereClause) => Promise<Record<string, any>[]>;\n}\n","import { mkdir, readdir } from 'node:fs/promises';\nimport { basename, extname, join } from 'node:path';\nimport { DatabaseError } from '@happyvertical/utils';\nimport { DatabaseSchemaManager } from './schema-manager';\nimport { convertUniqueIndexesToInlineConstraints } from './shared/duckdb-schema-utils';\nimport type {\n DatabaseInterface,\n JSONOptions,\n QueryResult,\n SchemaInitializationOptions,\n TableInterface,\n TransactionHandle,\n UpsertOptions,\n} from './shared/types';\nimport { resolveSchemas } from './shared/types';\nimport { buildWhere, formatDbError } from './shared/utils';\n\n/**\n * Extend globalThis to include our connection cache properties.\n * Using globalThis ensures all module instances share the same cache,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/sdk/issues/678\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __haveSqlMemoryConnectionCache:\n | Map<string, DatabaseInterface>\n | undefined;\n // eslint-disable-next-line no-var\n var __haveSqlPendingConnections:\n | Map<string, Promise<DatabaseInterface>>\n | undefined;\n}\n\n/**\n * Connection cache for in-memory DuckDB instances keyed by data directory URL\n * Enables sharing of in-memory databases across multiple getDatabase() calls\n * with the same data directory.\n *\n * Uses globalThis to ensure cache is shared across all module instances,\n * fixing the lost update bug in monorepos with workspace symlinks.\n *\n * @see https://github.com/happyvertical/sdk/issues/678\n */\nglobalThis.__haveSqlMemoryConnectionCache ??= new Map<\n string,\n DatabaseInterface\n>();\nconst memoryConnectionCache = globalThis.__haveSqlMemoryConnectionCache;\n\n/**\n * Pending connection promises to handle concurrent getDatabase() calls\n * Prevents creating duplicate connections when parallel calls happen.\n *\n * Uses globalThis to ensure cache is shared across all module instances.\n *\n * @see https://github.com/happyvertical/sdk/issues/678\n */\nglobalThis.__haveSqlPendingConnections ??= new Map<\n string,\n Promise<DatabaseInterface>\n>();\nconst pendingConnections = globalThis.__haveSqlPendingConnections;\n\n/**\n * Clears all cached connections\n * Useful for testing to ensure test isolation\n */\nexport function clearConnectionCache(): void {\n memoryConnectionCache.clear();\n pendingConnections.clear();\n}\n\n/**\n * Creates a JSON database connection using DuckDB in-memory engine\n *\n * This adapter uses DuckDB as a query engine for JSON files, storing everything\n * in-memory and writing changes back to JSON files. No WAL files or persistent\n * database files are created.\n *\n * @param options - JSON database options\n * @returns Promise resolving to a DuckDB connection\n */\nasync function createJSONConnection(options: JSONOptions) {\n const { url, autoRegister = true, eagerLoadTables = true } = options;\n const schemas = resolveSchemas(options.schemas) ?? {};\n\n if (!url) {\n throw new DatabaseError('url is required for JSON adapter', {\n options,\n });\n }\n\n // Track JSON files pending deferred loading (tableName → filePath)\n const pendingJSONFiles = new Map<string, string>();\n\n // Track tables created with inferred schemas (need DROP before syncSchema())\n const inferredSchemaTables = new Set<string>();\n\n try {\n // Dynamic import to avoid bundling\n const duckdbModule = '@duckdb/node-api';\n const { DuckDBInstance } = await import(/* @vite-ignore */ duckdbModule);\n\n // Always use in-memory database - no persistent files\n const instance = await DuckDBInstance.create(':memory:');\n const connection = await instance.connect();\n\n // Ensure data directory exists\n try {\n await mkdir(url, { recursive: true });\n } catch (_error) {\n // Directory might already exist, that's okay\n }\n\n // Scan JSON files - tables with schemas are created now, others are deferred\n if (autoRegister) {\n await loadJSONTables(\n connection,\n url,\n schemas,\n pendingJSONFiles,\n eagerLoadTables,\n inferredSchemaTables,\n );\n }\n\n return { connection, pendingJSONFiles, inferredSchemaTables };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new DatabaseError(\n `Failed to create JSON database connection: ${errorMessage}`,\n {\n url,\n originalError: errorMessage,\n },\n );\n }\n}\n\n/**\n * Loads JSON data into an existing table\n *\n * This function only loads data - it assumes the table already exists with proper schema.\n * Used after DDL creates the table to load persisted JSON data.\n *\n * @param connection - DuckDB connection\n * @param tableName - Name of the table to load data into\n * @param filePath - Path to the JSON file\n */\nasync function loadJSONData(\n connection: any,\n tableName: string,\n filePath: string,\n): Promise<void> {\n try {\n const { readFile } = await import('node:fs/promises');\n const jsonContent = await readFile(filePath, 'utf-8');\n const records = JSON.parse(jsonContent);\n\n if (Array.isArray(records) && records.length > 0) {\n await insertRecordsWithCast(connection, tableName, records);\n console.log(\n `[json-adapter] Loaded ${records.length} records into ${tableName} from JSON`,\n );\n }\n } catch (error) {\n // If load fails (e.g., empty file, parse error), that's okay - table structure is what matters\n console.warn(\n `[json-adapter] Could not load data for ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\n/**\n * Scans the data directory and registers JSON files for deferred loading\n *\n * Unlike the DuckDB adapter which creates views, this creates actual tables\n * so that indexes can be added.\n *\n * Schema resolution priority:\n * 1. Explicit schemas provided via options.schemas - table created immediately\n * 2. Schema file (.schema.sql) in data directory - table created with schema\n * 3. All other tables - DEFERRED until syncSchema() provides DDL\n *\n * IMPORTANT: Tables without explicit schemas are NOT auto-created from JSON.\n * This ensures UNIQUE constraints from syncSchema() are in place before data\n * is loaded, which is required for UPSERT operations to work correctly.\n *\n * For users who want auto-inference, use the inferSchemaFromJSON() method\n * after database creation.\n *\n * @param connection - DuckDB connection\n * @param dataDir - Directory containing JSON files\n * @param providedSchemas - Explicit schema definitions provided by caller (optional)\n * @param pendingJSONFiles - Map to store JSON files pending deferred loading\n * @param eagerLoadTables - Whether to eagerly create tables with inferred schemas\n * @param inferredSchemaTables - Set to track tables created with inferred schemas\n */\nasync function loadJSONTables(\n connection: any,\n dataDir: string,\n providedSchemas: Record<string, import('./shared/types').SchemaProvider> = {},\n pendingJSONFiles: Map<string, string> = new Map(),\n eagerLoadTables: boolean = true,\n inferredSchemaTables: Set<string> = new Set(),\n) {\n try {\n const files = await readdir(dataDir);\n const jsonFiles = files.filter(\n (file) => extname(file).toLowerCase() === '.json',\n );\n\n for (const file of jsonFiles) {\n const filePath = join(dataDir, file);\n const tableName = basename(file, '.json');\n\n // Check for explicitly provided schema\n const schema = providedSchemas[tableName];\n\n if (schema) {\n // Create table with provided schema (proper typing)\n console.log(\n `[json-adapter] Creating ${tableName} with provided schema definition`,\n );\n await createTableFromSchema(connection, tableName, schema);\n\n // Load JSON data into properly-typed table\n await loadJSONData(connection, tableName, filePath);\n } else {\n // Check for schema file first (preserves constraints like PRIMARY KEY, UNIQUE, etc.)\n const schemaPath = join(dataDir, `${tableName}.schema.sql`);\n const { readFile, access } = await import('node:fs/promises');\n const { constants } = await import('node:fs');\n\n let schemaExists = false;\n try {\n await access(schemaPath, constants.F_OK);\n schemaExists = true;\n } catch {\n schemaExists = false;\n }\n\n if (schemaExists) {\n // Schema file exists - create table and load data now\n try {\n const schemaDDL = await readFile(schemaPath, 'utf-8');\n await connection.run(schemaDDL);\n await loadJSONData(connection, tableName, filePath);\n } catch (error) {\n console.warn(\n `[json-adapter] Could not load ${tableName} with schema file: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n } else {\n // No schema file - either eager load with inferred schema or defer\n if (eagerLoadTables) {\n // Eager load: create table with inferred schema from JSON\n // This enables cross-table queries before syncSchema() is called\n // Note: Inferred schemas don't have UNIQUE constraints, so UPSERT won't work\n // until syncSchema() is called to upgrade the schema\n try {\n await connection.run(\n `CREATE TABLE IF NOT EXISTS \"${tableName}\" AS SELECT * FROM read_json_auto('${filePath}')`,\n );\n inferredSchemaTables.add(tableName);\n console.log(\n `[json-adapter] Eagerly created ${tableName} with inferred schema (no UNIQUE constraints)`,\n );\n } catch (error) {\n console.warn(\n `[json-adapter] Could not eagerly load ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n } else {\n console.log(\n `[json-adapter] Deferring ${tableName} - will load after syncSchema() creates table`,\n );\n }\n // Always track for later schema upgrade and data reload\n pendingJSONFiles.set(tableName, filePath);\n }\n }\n }\n } catch (error) {\n // If directory doesn't exist or is empty, that's okay\n if ((error as any).code !== 'ENOENT') {\n // Log the error for debugging\n console.error('[json-adapter] Error loading JSON tables:', error);\n throw new DatabaseError(`Failed to load JSON tables from ${dataDir}`, {\n dataDir,\n originalError: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n}\n\n/**\n * Converts DuckDB-specific type representations to JavaScript types\n *\n * Handles three cases:\n * 1. JavaScript BigInt values → converted to numbers\n * 2. DuckDB hugeint objects ({ hugeint: number }) → converted to strings\n * 3. DuckDB timestamp objects ({ micros: number }) → converted to Date objects\n *\n * DuckDB represents HUGEINT (128-bit integers) as objects with a single\n * property called 'hugeint'. When UUID strings (stored as TEXT) are\n * exported to JSON via COPY TO, DuckDB sometimes converts them to hugeint\n * representation. This function converts them back to strings.\n *\n * DuckDB represents TIMESTAMP values as objects with a single property\n * called 'micros' containing microseconds since Unix epoch. This function\n * converts them to JavaScript Date objects for proper round-trip serialization.\n *\n * @param obj - Object that may contain BigInt, hugeint, or timestamp values\n * @returns Object with DuckDB types converted to JavaScript types\n */\nfunction convertBigInts(obj: any): any {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'bigint') return Number(obj);\n\n // Handle DuckDB hugeint objects: { hugeint: number }\n // Convert to string to preserve UUID/TEXT values\n if (\n typeof obj === 'object' &&\n !Array.isArray(obj) &&\n 'hugeint' in obj &&\n Object.keys(obj).length === 1\n ) {\n // Convert hugeint to string representation\n // For UUIDs and other TEXT values that DuckDB converted\n return String(obj.hugeint);\n }\n\n // Handle DuckDB timestamp objects: { micros: number | bigint }\n // Convert to JavaScript Date for proper round-trip serialization\n // Fixes issue #319: JSON adapter fails to serialize Date fields during UPSERT\n if (\n typeof obj === 'object' &&\n !Array.isArray(obj) &&\n 'micros' in obj &&\n Object.keys(obj).length === 1 &&\n (typeof obj.micros === 'number' || typeof obj.micros === 'bigint')\n ) {\n // Convert microseconds to milliseconds for Date constructor\n // DuckDB stores timestamps as microseconds since Unix epoch\n // Handle both number and bigint types (DuckDB can return either)\n const micros =\n typeof obj.micros === 'bigint' ? Number(obj.micros) : obj.micros;\n const milliseconds = micros / 1000;\n return new Date(milliseconds);\n }\n\n if (Array.isArray(obj)) return obj.map(convertBigInts);\n if (typeof obj === 'object') {\n const result: any = {};\n for (const key in obj) {\n result[key] = convertBigInts(obj[key]);\n }\n return result;\n }\n return obj;\n}\n\n/**\n * Creates a table from a schema definition with proper typing\n *\n * DuckDB has issues with type inference when DEFAULT values are empty strings.\n * This function explicitly casts all DEFAULT values to their column types to\n * prevent DuckDB from inferring ANY type.\n *\n * Additionally, DuckDB has a known limitation (issue #12684) where ON CONFLICT\n * clauses fail with UNIQUE INDEX but work with inline UNIQUE constraints.\n * This function converts UNIQUE indexes to inline constraints for compatibility.\n *\n * @param connection - DuckDB connection\n * @param tableName - Name of the table to create\n * @param schema - Schema definition with DDL and indexes\n */\nasync function createTableFromSchema(\n connection: any,\n tableName: string,\n schema: import('./shared/types').SchemaProvider,\n): Promise<void> {\n // Extract CREATE TABLE statement (without triggers which aren't supported)\n const ddlLines = schema.ddl.split('\\n');\n const createTableEnd = ddlLines.findIndex((line) => {\n const trimmed = line.trim();\n return trimmed === ')' || trimmed.startsWith(');');\n });\n\n if (createTableEnd === -1) {\n throw new DatabaseError('Invalid schema DDL - no closing parenthesis', {\n tableName,\n ddl: schema.ddl,\n });\n }\n\n // Get CREATE TABLE statement\n let createTableSQL = ddlLines.slice(0, createTableEnd + 1).join('\\n');\n\n // Fix DEFAULT values for DuckDB type inference\n // DuckDB infers ANY type when DEFAULT is an empty string without explicit cast\n // Replace patterns like: DEFAULT '' with DEFAULT CAST('' AS TEXT)\n createTableSQL = createTableSQL.replace(\n /\\b(\\w+)\\s+(TEXT|VARCHAR)\\s+DEFAULT\\s+''/g,\n \"$1 $2 DEFAULT CAST('' AS $2)\",\n );\n\n // Also handle DEFAULT NULL cases to ensure proper typing\n createTableSQL = createTableSQL.replace(\n /\\b(\\w+)\\s+(TEXT|VARCHAR)\\s+DEFAULT\\s+NULL/g,\n '$1 $2 DEFAULT CAST(NULL AS $2)',\n );\n\n // Convert UNIQUE indexes to inline UNIQUE constraints for DuckDB compatibility\n // DuckDB's ON CONFLICT requires inline constraints, not separate indexes\n const transformed = convertUniqueIndexesToInlineConstraints(\n createTableSQL,\n schema.indexes,\n );\n createTableSQL = transformed.ddl;\n const indexesToCreate = transformed.indexes;\n\n try {\n await connection.run(createTableSQL);\n\n // Get actual columns after table creation\n let existingColumns: Set<string> = new Set();\n try {\n const schemaInfo = await connection.runAndReadAll(\n `DESCRIBE ${tableName}`,\n );\n const columns = schemaInfo.getRowObjects();\n existingColumns = new Set(\n columns.map((col: any) => col.column_name.toLowerCase()),\n );\n\n console.log(`[json-adapter] Created ${tableName} with schema:`, {\n columns: columns.map((col: any) => ({\n name: col.column_name,\n type: col.column_type,\n null: col.null,\n })),\n });\n } catch (error) {\n // Schema verification failed, but table was created - log warning and continue\n console.warn(\n `[json-adapter] Could not verify schema for ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n // Add columns from fields that aren't in the DDL (important for STI subclass fields)\n if (schema.fields && existingColumns.size > 0) {\n // Handle both Map and Record formats\n const fieldEntries =\n schema.fields instanceof Map\n ? Array.from(schema.fields.entries())\n : Object.entries(schema.fields);\n\n for (const [fieldName, fieldDef] of fieldEntries) {\n const columnName = fieldName.toLowerCase();\n if (!existingColumns.has(columnName)) {\n // Determine SQL type from field definition\n const sqlType = fieldDef?.type || 'TEXT';\n try {\n await connection.run(\n `ALTER TABLE ${tableName} ADD COLUMN \"${fieldName}\" ${sqlType}`,\n );\n console.log(\n `[json-adapter] Added missing column '${fieldName}' (${sqlType}) to ${tableName}`,\n );\n } catch (alterError) {\n console.warn(\n `[json-adapter] Could not add column '${fieldName}' to ${tableName}: ${alterError instanceof Error ? alterError.message : String(alterError)}`,\n );\n }\n }\n }\n }\n\n // Create remaining indexes (non-UNIQUE indexes only)\n // UNIQUE indexes have been converted to inline constraints\n if (indexesToCreate && indexesToCreate.length > 0) {\n for (const indexSQL of indexesToCreate) {\n try {\n await connection.run(indexSQL);\n } catch (error) {\n // Index creation might fail if column doesn't exist or syntax incompatibility\n console.warn(\n `[json-adapter] Failed to create index: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n } catch (error) {\n throw new DatabaseError('Failed to create table from schema', {\n tableName,\n sql: createTableSQL,\n originalError: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\n/**\n * Inserts records with proper CAST handling for empty strings\n *\n * This helper avoids using read_json() with auto_detect, which causes DuckDB\n * to re-infer column types from data (causing ANY type for empty strings).\n * Instead, it uses parameterized INSERT with CAST to maintain table schema.\n *\n * @param connection - DuckDB connection\n * @param tableName - Name of the table to insert into\n * @param records - Array of records to insert\n */\nasync function insertRecordsWithCast(\n connection: any,\n tableName: string,\n records: Record<string, any>[],\n): Promise<void> {\n if (records.length === 0) return;\n\n const keys = Object.keys(records[0]);\n\n // Build placeholders - schema has NOT NULL DEFAULT '' to prevent ANY type\n const values: any[] = [];\n let paramIdx = 1;\n\n const placeholders = records\n .map((record) => {\n const rowPlaceholders = keys.map((key) => {\n const value = record[key];\n\n if (value === null) {\n return 'NULL';\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference on parameters\n values.push(value);\n return `CAST($${paramIdx++} AS TEXT)`;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n values.push(value.toISOString());\n return `CAST($${paramIdx++} AS TIMESTAMP)`;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else {\n // Direct parameter binding for other values\n values.push(value);\n return `$${paramIdx++}`;\n }\n });\n return `(${rowPlaceholders.join(', ')})`;\n })\n .join(', ');\n\n const sql = `INSERT INTO ${tableName} (${keys.join(', ')}) VALUES ${placeholders}`;\n\n await connection.run(sql, values);\n}\n\n/**\n * Validates that a table name is valid (alphanumeric + underscores only)\n *\n * @param table - Table name to validate\n * @throws DatabaseError if table name is invalid\n */\nfunction validateTableName(table: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(table)) {\n throw new DatabaseError(`Invalid table name: ${table}`, { table });\n }\n}\n\n/**\n * Creates a JSON database adapter using DuckDB in-memory engine\n *\n * This adapter provides SQL query capabilities over JSON files without creating\n * persistent database files or WAL files. All data is stored in-memory during\n * runtime and written back to JSON files based on the write strategy.\n *\n * @param options - JSON database options\n * @returns Database interface for JSON files\n */\nexport async function getDatabase(\n options: JSONOptions,\n): Promise<DatabaseInterface> {\n // Generate cache key from URL and options that affect database behavior\n // FIX for issues #533/#534: Auto-generate dbid from URL when schemas provided\n // This ensures connection caching ALWAYS happens for the same URL, preventing\n // the lost update bug where multiple connections overwrite each other's data.\n //\n // Priority:\n // 1. Explicit dbid from caller\n // 2. Auto-generated from URL + writeStrategy (ensures caching)\n const cacheKey =\n options.dbid ||\n `json:${options.url}:${options.writeStrategy || 'immediate'}:${options.autoRegister !== false}`;\n\n // If clearCache option is true, clear any cached connection for this key\n if (options.clearCache) {\n memoryConnectionCache.delete(cacheKey);\n pendingConnections.delete(cacheKey);\n }\n\n // Check if we have a cached connection for this cache key\n const cached = memoryConnectionCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // Check if there's a pending connection for this cache key\n const pending = pendingConnections.get(cacheKey);\n if (pending) {\n return pending;\n }\n\n // Create a new connection promise\n const connectionPromise = (async () => {\n const { connection, pendingJSONFiles, inferredSchemaTables } =\n await createJSONConnection(options);\n const writeStrategy = options.writeStrategy || 'immediate';\n const { url } = options;\n\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n * @throws Error if the insert operation fails\n */\n const insert = async (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot insert: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n const records = Array.isArray(data) ? data : [data];\n\n if (records.length === 0) {\n return { operation: 'insert', affected: 0 };\n }\n\n const keys = Object.keys(records[0]);\n\n // Build placeholders with CAST for empty strings\n const values: any[] = [];\n let paramIdx = 1;\n\n const placeholders = records\n .map((record) => {\n const rowPlaceholders = keys.map((key) => {\n const value = record[key];\n\n if (value === null) {\n return 'NULL';\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference\n values.push(value);\n return `CAST($${paramIdx++} AS TEXT)`;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB (issue #319)\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n values.push(value.toISOString());\n return `CAST($${paramIdx++} AS TIMESTAMP)`;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n // DuckDB cannot infer array element types from empty arrays or mixed types\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n // Only applies to plain objects (not class instances)\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else {\n // Direct parameter binding for other values\n values.push(value);\n return `$${paramIdx++}`;\n }\n });\n return `(${rowPlaceholders.join(', ')})`;\n })\n .join(', ');\n\n const sql = `INSERT INTO \"${table}\" (${keys.join(', ')}) VALUES ${placeholders}`;\n\n try {\n await connection.run(sql, values);\n const affected = records.length;\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'insert', affected };\n } catch (e) {\n throw new DatabaseError('Failed to insert records into table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to matching record or null if not found\n * @throws Error if the query fails\n */\n const get = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any> | null> => {\n validateTableName(table);\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `SELECT * FROM \"${table}\" ${whereClause} LIMIT 1`;\n\n try {\n const reader = await connection.runAndReadAll(sql, values);\n const rows = reader.getRowObjects();\n return rows.length > 0 ? convertBigInts(rows[0]) : null;\n } catch (e) {\n throw new DatabaseError('Failed to retrieve record from table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to array of matching records\n * @throws Error if the query fails\n */\n const list = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any>[]> => {\n validateTableName(table);\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `SELECT * FROM \"${table}\" ${whereClause}`;\n\n try {\n const reader = await connection.runAndReadAll(sql, values);\n return convertBigInts(reader.getRowObjects());\n } catch (e) {\n throw new DatabaseError('Failed to list records from table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update\n * @param data - New data to set\n * @returns Promise resolving to operation result\n * @throws Error if the update operation fails\n */\n const update = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot update: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n const keys = Object.keys(data);\n const setClause = keys\n .map((key, idx) => `${key} = $${idx + 1}`)\n .join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n keys.length + 1,\n 'json',\n );\n\n // Convert Date objects to ISO strings for DuckDB (issue #319)\n const dataValues = Object.values(data).map((value) =>\n value instanceof Date ? value.toISOString() : value,\n );\n\n const sql = `UPDATE \"${table}\" SET ${setClause} ${whereClause}`;\n const values = [...dataValues, ...whereValues];\n\n try {\n await connection.run(sql, values);\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n // DuckDB doesn't return rowsAffected in the same way, estimate from where clause\n return { operation: 'update', affected: 1 };\n } catch (e) {\n throw new DatabaseError('Failed to update records in table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n const buildJSONValueExpression = (\n value: any,\n values: any[],\n paramIdx: { value: number },\n ): string => {\n if (value === null) {\n return 'NULL';\n }\n if (value === '' && typeof value === 'string') {\n values.push(value);\n return `CAST($${paramIdx.value++} AS TEXT)`;\n }\n if (value instanceof Date) {\n values.push(value.toISOString());\n return `CAST($${paramIdx.value++} AS TIMESTAMP)`;\n }\n if (Array.isArray(value)) {\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx.value++} AS JSON)`;\n }\n if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx.value++} AS JSON)`;\n }\n\n values.push(value);\n return `$${paramIdx.value++}`;\n };\n\n const executeNullAwareJSONUpsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n ): Promise<QueryResult> => {\n const conflictWhere = Object.fromEntries(\n conflictColumns.map((col) => [col, data[col]]),\n );\n const existing = await get(table, conflictWhere);\n\n if (!existing) {\n return insert(table, data);\n }\n\n const keys = Object.keys(data);\n const values: any[] = [];\n const paramIdx = { value: 1 };\n const assignments = keys.map((key) => {\n const valueExpr = buildJSONValueExpression(data[key], values, paramIdx);\n return `\"${key}\" = ${valueExpr}`;\n });\n const { sql: whereClause, values: whereValues } = buildWhere(\n conflictWhere,\n paramIdx.value,\n 'json',\n );\n const sql = `UPDATE \"${table}\" SET ${assignments.join(', ')} ${whereClause}`;\n\n try {\n await connection.run(sql, [...values, ...whereValues]);\n\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'upsert', affected: 1 };\n } catch (e) {\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n sql,\n values: [...values, ...whereValues],\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n * @throws Error if the upsert operation fails\n */\n const upsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot upsert: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n // Validate that all conflict columns are present in the data\n const missingColumns = conflictColumns.filter((col) => !(col in data));\n\n if (missingColumns.length > 0) {\n throw new DatabaseError('Conflict columns missing from data', {\n table,\n conflictColumns,\n missingColumns,\n availableColumns: Object.keys(data),\n hint: 'All columns specified in ON CONFLICT must be present in the data being inserted. Undefined values should be replaced with null or an appropriate default.',\n });\n }\n\n if (\n !options?.nullsDistinct &&\n conflictColumns.some((col) => data[col] === null)\n ) {\n return executeNullAwareJSONUpsert(table, conflictColumns, data);\n }\n\n const keys = Object.keys(data);\n const dataValues = Object.values(data);\n\n // Build placeholders - schema has NOT NULL DEFAULT '' to prevent ANY type\n const placeholders: string[] = [];\n const values: any[] = [];\n let paramIdx = 1;\n\n for (const value of dataValues) {\n if (value === null) {\n placeholders.push('NULL');\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference on parameters\n placeholders.push(`CAST($${paramIdx} AS TEXT)`);\n values.push(value);\n paramIdx++;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n placeholders.push(`CAST($${paramIdx} AS TIMESTAMP)`);\n values.push(value.toISOString());\n paramIdx++;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n // DuckDB cannot infer array element types from empty arrays or mixed types\n placeholders.push(`CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n // Only applies to plain objects (not class instances)\n placeholders.push(`CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else {\n // Direct parameter binding for other values\n placeholders.push(`$${paramIdx}`);\n values.push(value);\n paramIdx++;\n }\n }\n\n // Build UPDATE SET clause with same approach\n // DO NOT reset paramIdx - parameters must be unique across entire query\n const updateSetParts: string[] = [];\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const value = dataValues[i];\n\n if (value === null) {\n updateSetParts.push(`${key} = NULL`);\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference on parameters\n updateSetParts.push(`${key} = CAST($${paramIdx} AS TEXT)`);\n values.push(value);\n paramIdx++;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n updateSetParts.push(`${key} = CAST($${paramIdx} AS TIMESTAMP)`);\n values.push(value.toISOString());\n paramIdx++;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n updateSetParts.push(`${key} = CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n updateSetParts.push(`${key} = CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else {\n // Direct parameter binding for other values\n updateSetParts.push(`${key} = $${paramIdx}`);\n values.push(value);\n paramIdx++;\n }\n }\n\n // Quote ALL column names to match DuckDB's schema generation\n // SchemaGenerator always quotes column names, so UPSERT must match\n const conflict = conflictColumns.map((col) => `\"${col}\"`).join(', ');\n const quotedKeys = keys.map((key) => `\"${key}\"`).join(', ');\n\n // Quote column names in UPDATE SET clause to match schema and ON CONFLICT\n // Extract the value expression from each updateSetPart (everything after '=')\n const quotedUpdateSetParts = keys.map((key, i) => {\n const part = updateSetParts[i];\n const valueExpr = part.substring(part.indexOf('=') + 1).trim();\n return `\"${key}\" = ${valueExpr}`;\n });\n\n const sql = `INSERT INTO \"${table}\" (${quotedKeys}) VALUES (${placeholders.join(', ')}) ON CONFLICT(${conflict}) DO UPDATE SET ${quotedUpdateSetParts.join(', ')}`;\n\n try {\n await connection.run(sql, values);\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'upsert', affected: 1 };\n } catch (e) {\n // Log detailed error information for debugging\n console.error('UPSERT failed:', {\n table,\n sql,\n values,\n valueTypes: values.map((v) => `${typeof v} (${v})`),\n conflictColumns,\n error: formatDbError(e),\n });\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n sql,\n values,\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record\n * @param data - Data to insert if no record found\n * @returns Promise resolving to the record (either retrieved or newly inserted)\n * @throws Error if the operation fails\n */\n const getOrInsert = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<Record<string, any>> => {\n const result = await get(table, where);\n if (result) return result;\n\n await insert(table, data);\n const inserted = await get(table, where);\n\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n\n return inserted;\n };\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion\n * @returns Promise resolving to operation result with count of deleted rows\n * @throws Error if the delete operation fails\n */\n const deleteRecords = async (\n table: string,\n where: Record<string, any>,\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot delete: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `DELETE FROM \"${table}\" ${whereClause}`;\n\n try {\n await connection.run(sql, values);\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'delete', affected: 1 };\n } catch (e) {\n throw new DatabaseError('Failed to delete records from table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted)\n * @returns Promise resolving to count of matching records\n * @throws Error if the count operation fails\n */\n const count = async (\n table: string,\n where?: Record<string, any>,\n ): Promise<number> => {\n validateTableName(table);\n\n try {\n if (!where || Object.keys(where).length === 0) {\n // Count all records\n const result = await connection.runAndReadAll(\n `SELECT COUNT(*) as count FROM \"${table}\"`,\n );\n const rows = result.getRowObjects();\n return Number(rows[0]?.count) || 0;\n }\n\n // Count with conditions\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `SELECT COUNT(*) as count FROM \"${table}\" ${whereClause}`;\n\n const result = await connection.runAndReadAll(sql, values);\n const rows = result.getRowObjects();\n\n return Number(rows[0]?.count) || 0;\n } catch (e) {\n throw new DatabaseError('Failed to count records in table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Checks if a table exists in the database\n *\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\n const tableExists = async (tableName: string): Promise<boolean> => {\n try {\n // Try to query the table\n await connection.runAndReadAll(`SELECT * FROM ${tableName} LIMIT 1`);\n return true;\n } catch {\n return false;\n }\n };\n\n /**\n * Exports a table to JSON and schema files\n *\n * Exports two files:\n * 1. {table}.json - Table data with columns cast appropriately\n * 2. {table}.schema.sql - CREATE TABLE statement to preserve constraints\n *\n * Note: JSON columns are NOT cast to TEXT to preserve object structure.\n * Other columns are cast to TEXT to prevent DuckDB from converting UUIDs\n * and other TEXT values to hugeint representation in JSON output.\n *\n * @param connection - DuckDB connection\n * @param table - Table name\n * @param dataDir - Directory to write files\n */\n const exportTableToJSON = async (\n connection: any,\n table: string,\n dataDir: string,\n ): Promise<void> => {\n const filePath = join(dataDir, `${table}.json`);\n const schemaPath = join(dataDir, `${table}.schema.sql`);\n\n // Export schema first using SHOW CREATE TABLE\n try {\n const schemaResult = await connection.runAndReadAll(\n `SELECT sql FROM sqlite_master WHERE type='table' AND name='${table}'`,\n );\n const rows = schemaResult.getRowObjects();\n if (rows.length > 0 && rows[0].sql) {\n const { writeFile } = await import('node:fs/promises');\n await writeFile(schemaPath, rows[0].sql, 'utf-8');\n }\n } catch (error) {\n console.warn(\n `[json-adapter] Could not export schema for ${table}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n // Get column names and types to handle JSON columns specially\n // JSON columns should NOT be cast to TEXT to preserve object structure (fixes #542)\n const columnsResult = await connection.runAndReadAll(\n `SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '${table}' ORDER BY ordinal_position`,\n );\n const columnInfo = columnsResult.getRowObjects() as {\n column_name: string;\n data_type: string;\n }[];\n\n if (columnInfo.length === 0) {\n // Fallback to SELECT * if we can't get column names\n await connection.run(\n `COPY (SELECT * FROM \"${table}\") TO '${filePath}' (FORMAT JSON, ARRAY true)`,\n );\n return;\n }\n\n // Preserve type-appropriate columns, only cast text-based columns to TEXT\n // - JSON/STRUCT: preserve as-is for object structure (fixes #542)\n // - Numeric types: preserve as-is so numbers export as numbers (fixes #694)\n // - Boolean: preserve as-is\n // - Text-based: cast to TEXT to prevent DuckDB hugeint conversion for UUIDs\n const selectList = columnInfo\n .map(({ column_name, data_type }) => {\n const upperType = data_type.toUpperCase();\n // Preserve JSON/STRUCT as-is for object structure\n if (upperType === 'JSON' || upperType.startsWith('STRUCT')) {\n return `\"${column_name}\"`;\n }\n // Preserve numeric types as-is so they export as numbers, not strings\n if (\n [\n 'DOUBLE',\n 'REAL',\n 'FLOAT',\n 'INTEGER',\n 'BIGINT',\n 'SMALLINT',\n 'TINYINT',\n 'DECIMAL',\n 'NUMERIC',\n 'HUGEINT',\n 'UBIGINT',\n 'UINTEGER',\n 'USMALLINT',\n 'UTINYINT',\n ].some((t) => upperType.includes(t))\n ) {\n return `\"${column_name}\"`;\n }\n // Preserve boolean types as-is\n if (upperType === 'BOOLEAN' || upperType === 'BOOL') {\n return `\"${column_name}\"`;\n }\n // Cast text-based columns to TEXT to prevent hugeint conversion for UUIDs\n return `CAST(\"${column_name}\" AS TEXT) AS \"${column_name}\"`;\n })\n .join(', ');\n const sql = `COPY (SELECT ${selectList} FROM \"${table}\") TO '${filePath}' (FORMAT JSON, ARRAY true)`;\n\n await connection.run(sql);\n };\n\n /**\n * Manual export method for 'manual' write strategy\n *\n * Allows explicit control over when tables are written back to JSON files.\n *\n * @param table - Table name to export\n * @returns Promise that resolves when export completes\n */\n const exportTable = async (table: string): Promise<void> => {\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot export table: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n await exportTableToJSON(connection, table, url);\n };\n\n /**\n * Creates a table by inferring schema from a JSON file\n *\n * This utility is for users who want automatic schema inference from JSON.\n * Note: Inferred schemas do NOT include UNIQUE constraints, so UPSERT\n * operations will fail. Use syncSchema() with explicit DDL for UPSERT support.\n *\n * @param tableName - Name of the table to create\n * @param jsonPath - Optional path to JSON file (defaults to {dataDir}/{tableName}.json)\n * @returns Promise that resolves when table is created\n * @throws Error if JSON file doesn't exist or table creation fails\n */\n const inferSchemaFromJSON = async (\n tableName: string,\n jsonPath?: string,\n ): Promise<void> => {\n validateTableName(tableName);\n\n const filePath = jsonPath || join(url, `${tableName}.json`);\n\n try {\n // Check if file exists\n const { access } = await import('node:fs/promises');\n const { constants } = await import('node:fs');\n await access(filePath, constants.F_OK);\n\n // Use DuckDB's read_json_auto to infer types and create table\n console.log(\n `[json-adapter] Inferring schema for ${tableName} from JSON file`,\n );\n await connection.run(\n `CREATE TABLE \"${tableName}\" AS SELECT * FROM read_json_auto('${filePath}')`,\n );\n\n // Remove from pending files if it was deferred\n pendingJSONFiles.delete(tableName);\n\n console.log(\n `[json-adapter] Created ${tableName} with inferred schema (no UNIQUE constraints)`,\n );\n } catch (error) {\n throw new DatabaseError(\n `Failed to infer schema from JSON for table ${tableName}`,\n {\n tableName,\n jsonPath: filePath,\n originalError:\n error instanceof Error ? error.message : String(error),\n },\n );\n }\n };\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param tableName - Table name\n * @returns TableInterface for the specified table\n */\n const table = (tableName: string): TableInterface => ({\n insert: (data) => insert(tableName, data),\n get: (where) => get(tableName, where),\n list: (where) => list(tableName, where),\n });\n\n /**\n * Parses a tagged template literal into a SQL query and values\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Object with SQL query and values array\n */\n const parseTemplate = (strings: TemplateStringsArray, ...vars: any[]) => {\n let sql = strings[0];\n const values = [];\n for (let i = 0; i < vars.length; i++) {\n values.push(vars[i]);\n sql += `$${i + 1}${strings[i + 1]}`;\n }\n return { sql, values };\n };\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n * @throws Error if the query fails\n */\n const many = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any>[]> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const reader = await connection.runAndReadAll(sql, values);\n return convertBigInts(reader.getRowObjects());\n } catch (e) {\n throw new DatabaseError('Failed to execute many query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n * @throws Error if the query fails\n */\n const single = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any> | null> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const reader = await connection.runAndReadAll(sql, values);\n const rows = reader.getRowObjects();\n return rows[0] ? convertBigInts(rows[0]) : null;\n } catch (e) {\n throw new DatabaseError('Failed to execute single query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n * @throws Error if the query fails\n */\n const pluck = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<any> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const reader = await connection.runAndReadAll(sql, values);\n const rows = reader.getRowObjects();\n if (rows.length === 0) return null;\n const firstRow = rows[0];\n const firstKey = Object.keys(firstRow)[0];\n return convertBigInts(firstRow[firstKey]);\n } catch (e) {\n throw new DatabaseError('Failed to execute pluck query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n * @throws Error if the query fails\n */\n const execute = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<void> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n await connection.run(sql, values);\n\n // Detect CREATE TABLE statements\n const createTableMatch = sql.match(\n /CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?[\"']?(\\w+)[\"']?/i,\n );\n if (createTableMatch) {\n const tableName = createTableMatch[1];\n\n // Check if there's pending JSON data for this table (deferred loading)\n const pendingFile = pendingJSONFiles.get(tableName);\n if (pendingFile) {\n // Table was just created by DDL - now load the JSON data\n await loadJSONData(connection, tableName, pendingFile);\n pendingJSONFiles.delete(tableName);\n } else if (writeStrategy !== 'none') {\n // No pending data - export empty table (preserves SMRT system tables)\n try {\n const { access } = await import('node:fs/promises');\n const jsonFilePath = join(url, `${tableName}.json`);\n try {\n await access(jsonFilePath);\n // File exists, don't overwrite\n } catch {\n // File doesn't exist, export empty table\n await exportTableToJSON(connection, tableName, url);\n }\n } catch (error) {\n console.warn(\n `[json-adapter] Could not export newly created table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n } catch (e) {\n throw new DatabaseError('Failed to execute query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * @param str - SQL query string\n * @param values - Variables to use as parameters\n * @returns Promise resolving to query result with rows and metadata\n * @throws Error if the query fails\n */\n const query = async (str: string, ...values: any[]) => {\n const sql = str;\n const args = Array.isArray(values[0]) ? values[0] : values;\n\n try {\n const reader = await connection.runAndReadAll(sql, args);\n const rows = convertBigInts(reader.getRowObjects());\n\n return {\n command: sql.split(' ')[0].toUpperCase(),\n rowCount: rows.length,\n oid: null,\n fields:\n rows.length > 0\n ? Object.keys(rows[0]).map((name) => ({\n name,\n tableID: 0,\n columnID: 0,\n dataTypeID: 0,\n dataTypeSize: -1,\n dataTypeModifier: -1,\n format: 'text',\n }))\n : [],\n rows,\n };\n } catch (e) {\n throw new DatabaseError('Failed to execute raw query', {\n sql,\n args,\n originalError: formatDbError(e),\n });\n }\n };\n\n // Shorthand aliases for query methods\n const oo = many; // (o)bjective-(o)bjects: returns multiple rows\n const oO = single; // (o)bjective-(O)bject: returns a single row\n const ox = pluck; // (o)bjective-(x): returns a single value\n const xx = execute; // e(x)ecute-e(x)ecute: executes without returning\n\n /**\n * Synchronizes database schema with provided SQL DDL\n *\n * Filters out CREATE TRIGGER statements since triggers are not supported\n * in the JSON adapter (timestamps managed at application level).\n *\n * @param schema - SQL schema definition with CREATE TABLE statements\n * @returns Promise that resolves when schema is synchronized\n */\n const syncSchema = async (schema: string): Promise<void> => {\n const statements = schema\n .trim()\n .split(';')\n .filter((stmt) => stmt.trim() !== '');\n\n const createTableStatements: string[] = [];\n const indexStatements: string[] = [];\n const otherStatements: string[] = [];\n\n // Separate CREATE TABLE, CREATE INDEX, and other statements\n for (const stmt of statements) {\n const trimmed = stmt.trim();\n if (!trimmed) continue;\n\n const upperTrimmed = trimmed.toUpperCase();\n\n // Skip trigger creation - not supported in JSON adapter\n if (upperTrimmed.startsWith('CREATE TRIGGER')) {\n console.warn(\n '[json-adapter] Skipping trigger creation - timestamps managed at application level',\n );\n continue;\n }\n\n if (\n upperTrimmed.startsWith('CREATE INDEX') ||\n upperTrimmed.startsWith('CREATE UNIQUE INDEX')\n ) {\n indexStatements.push(trimmed);\n } else if (upperTrimmed.startsWith('CREATE TABLE')) {\n createTableStatements.push(trimmed);\n } else {\n otherStatements.push(trimmed);\n }\n }\n\n // Process each CREATE TABLE statement\n for (const ddl of createTableStatements) {\n // Transform UNIQUE indexes to inline constraints for DuckDB compatibility\n const { ddl: transformedDDL, indexes: remainingIndexes } =\n convertUniqueIndexesToInlineConstraints(ddl, indexStatements);\n\n // Extract table name from DDL before executing\n const createTableMatch = transformedDDL.match(\n /CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?[\"']?(\\w+)[\"']?/i,\n );\n const tableName = createTableMatch ? createTableMatch[1] : null;\n\n // If table was created with inferred schema, drop it first\n // (proper schema with UNIQUE constraints takes precedence)\n if (tableName && inferredSchemaTables.has(tableName)) {\n try {\n await connection.run(`DROP TABLE IF EXISTS \"${tableName}\"`);\n inferredSchemaTables.delete(tableName);\n console.log(\n `[json-adapter] Dropped inferred-schema table ${tableName} for schema upgrade`,\n );\n } catch (error) {\n console.warn(\n `[json-adapter] Could not drop inferred-schema table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Execute transformed DDL\n try {\n await connection.run(transformedDDL);\n\n if (tableName) {\n // Check if there's pending JSON data for this table (deferred loading)\n const pendingFile = pendingJSONFiles.get(tableName);\n if (pendingFile) {\n // Table was just created by DDL - now load the JSON data\n await loadJSONData(connection, tableName, pendingFile);\n pendingJSONFiles.delete(tableName);\n } else if (writeStrategy !== 'none') {\n // No pending data - export empty table (preserves SMRT system tables)\n try {\n // Only export if JSON file doesn't already exist\n // This prevents overwriting existing data when tables are manually created\n const { access } = await import('node:fs/promises');\n const jsonFilePath = join(url, `${tableName}.json`);\n try {\n await access(jsonFilePath);\n // File exists, don't overwrite\n } catch {\n // File doesn't exist, export empty table\n await exportTableToJSON(connection, tableName, url);\n }\n } catch (error) {\n console.warn(\n `[json-adapter] Could not export newly created table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n } catch (e) {\n console.error('Schema sync error (CREATE TABLE):', e);\n }\n\n // Execute remaining (non-UNIQUE) indexes for this table\n for (const indexSQL of remainingIndexes) {\n try {\n await connection.run(indexSQL);\n } catch (e) {\n console.error('Schema sync error (CREATE INDEX):', e);\n }\n }\n }\n\n // Execute other statements\n for (const stmt of otherStatements) {\n try {\n await connection.run(stmt);\n } catch (e) {\n console.error('Schema sync error:', e);\n }\n }\n };\n\n /**\n * Initialize database schemas from JSON manifest\n * Supports dependency resolution and schema overrides\n *\n * @param options - Schema initialization options\n * @returns Promise that resolves when schemas are initialized\n */\n const initializeSchemas = async (\n options: SchemaInitializationOptions,\n ): Promise<void> => {\n const schemaManager = new DatabaseSchemaManager();\n const currentDb: DatabaseInterface = {\n url,\n client: connection,\n query,\n insert,\n update,\n upsert,\n get,\n list,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n tableExists,\n many,\n single,\n pluck,\n execute,\n oo,\n oO,\n ox,\n xx,\n syncSchema,\n };\n\n await schemaManager.initializeSchemas(currentDb, options);\n };\n\n /**\n * Executes a callback within a database transaction\n * Automatically commits on success or rolls back on error\n *\n * @param callback - Function to execute within transaction\n * @returns Promise resolving to callback result\n */\n const transaction = async <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ): Promise<T> => {\n try {\n await connection.run('BEGIN TRANSACTION');\n\n // Create a transaction-scoped database interface\n const txDb: DatabaseInterface = {\n url,\n client: connection,\n insert,\n get,\n list,\n update,\n upsert,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n transaction,\n };\n\n const result = await callback(txDb);\n await connection.run('COMMIT');\n return result;\n } catch (error) {\n await connection.run('ROLLBACK');\n throw error;\n }\n };\n\n /**\n * Begins a new transaction and returns a handle for manual control\n *\n * Unlike transaction(), this gives you explicit control over commit/rollback.\n * Ideal for test isolation where you want to rollback after each test.\n *\n * @returns Promise resolving to a TransactionHandle\n */\n const beginTransaction = async (): Promise<TransactionHandle> => {\n await connection.run('BEGIN TRANSACTION');\n\n let active = true;\n\n const commit = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await connection.run('COMMIT');\n active = false;\n };\n\n const rollback = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await connection.run('ROLLBACK');\n active = false;\n };\n\n const isActive = (): boolean => active;\n\n // Create a transaction-scoped database interface with commit/rollback\n const txHandle: TransactionHandle = {\n url,\n client: connection,\n insert,\n get,\n list,\n update,\n upsert,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n transaction,\n commit,\n rollback,\n isActive,\n };\n\n return txHandle;\n };\n\n return {\n url,\n requiresSchemaCheck: true,\n client: connection,\n query,\n insert,\n update,\n upsert,\n get,\n list,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n tableExists,\n many,\n single,\n pluck,\n execute,\n oo,\n oO,\n ox,\n xx,\n syncSchema,\n initializeSchemas,\n transaction,\n beginTransaction,\n // JSON-specific methods\n exportTable,\n inferSchemaFromJSON,\n } as DatabaseInterface & {\n exportTable: (table: string) => Promise<void>;\n inferSchemaFromJSON: (\n tableName: string,\n jsonPath?: string,\n ) => Promise<void>;\n };\n })();\n\n // Store the pending connection promise for concurrent requests\n pendingConnections.set(cacheKey, connectionPromise);\n\n try {\n // Wait for the connection to be established\n const db = await connectionPromise;\n\n // Cache the connection for reuse\n memoryConnectionCache.set(cacheKey, db);\n\n return db;\n } finally {\n // Clean up pending connection promise\n pendingConnections.delete(cacheKey);\n }\n}\n","/**\n * Shared utilities for ALTER TABLE operations\n *\n * Provides database-agnostic utilities for generating ALTER TABLE statements,\n * handling column definitions, and creating indexes.\n */\n\nimport type { ColumnDefinitionWithName, IndexDefinition } from './types.js';\n\n/**\n * Database dialect type for SQL generation\n */\nexport type DatabaseDialect = 'sqlite' | 'postgres' | 'duckdb';\n\n/**\n * Generates an ALTER TABLE ADD COLUMN statement\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @param dialect - Database dialect\n * @returns SQL statement string\n *\n * @example\n * ```typescript\n * const sql = generateAddColumnStatement('users', {\n * name: 'email',\n * type: 'TEXT',\n * unique: true,\n * notNull: false\n * }, 'sqlite');\n * // Returns: \"ALTER TABLE users ADD COLUMN email TEXT UNIQUE\"\n * ```\n */\nexport function generateAddColumnStatement(\n table: string,\n column: ColumnDefinitionWithName,\n _dialect: DatabaseDialect,\n): string {\n const parts: string[] = [column.name, column.type];\n\n // Primary key\n if (column.primaryKey) {\n parts.push('PRIMARY KEY');\n }\n\n // NOT NULL constraint\n if (column.notNull) {\n parts.push('NOT NULL');\n }\n\n // UNIQUE constraint\n if (column.unique) {\n parts.push('UNIQUE');\n }\n\n // DEFAULT clause\n if (column.defaultValue !== undefined) {\n const defaultClause = generateDefaultClause(\n column.type,\n column.defaultValue,\n );\n parts.push(`DEFAULT ${defaultClause}`);\n }\n\n // CHECK constraint\n if (column.check) {\n parts.push(`CHECK (${column.check})`);\n }\n\n // Foreign key (inline for some databases)\n if (column.foreignKey) {\n const fk = column.foreignKey;\n const fkParts = [`REFERENCES ${fk.table}(${fk.column})`];\n\n if (fk.onDelete) {\n fkParts.push(`ON DELETE ${fk.onDelete}`);\n }\n\n if (fk.onUpdate) {\n fkParts.push(`ON UPDATE ${fk.onUpdate}`);\n }\n\n parts.push(fkParts.join(' '));\n }\n\n const columnDef = parts.join(' ');\n return `ALTER TABLE ${table} ADD COLUMN ${columnDef}`;\n}\n\n/**\n * Generates a DEFAULT clause for a column definition\n *\n * Handles proper formatting and escaping of default values based on column type.\n *\n * @param columnType - SQL column type (TEXT, INTEGER, BOOLEAN, etc.)\n * @param defaultValue - Default value to format\n * @returns Formatted default value string\n *\n * @example\n * ```typescript\n * generateDefaultClause('TEXT', 'hello'); // Returns: \"'hello'\"\n * generateDefaultClause('INTEGER', 42); // Returns: \"42\"\n * generateDefaultClause('BOOLEAN', true); // Returns: \"true\"\n * generateDefaultClause('TEXT', null); // Returns: \"NULL\"\n * ```\n */\nexport function generateDefaultClause(\n columnType: string,\n defaultValue: any,\n): string {\n if (defaultValue === null) {\n return 'NULL';\n }\n\n const typeUpper = columnType.toUpperCase();\n\n // String types - need quotes\n if (\n typeUpper.includes('TEXT') ||\n typeUpper.includes('CHAR') ||\n typeUpper.includes('VARCHAR') ||\n typeUpper.includes('STRING')\n ) {\n // Handle empty strings\n if (defaultValue === '') {\n return \"''\";\n }\n // Escape single quotes\n const escaped = String(defaultValue).replace(/'/g, \"''\");\n return `'${escaped}'`;\n }\n\n // Boolean types\n if (typeUpper.includes('BOOL')) {\n return defaultValue ? 'true' : 'false';\n }\n\n // Numeric types - no quotes\n if (\n typeUpper.includes('INT') ||\n typeUpper.includes('REAL') ||\n typeUpper.includes('FLOAT') ||\n typeUpper.includes('DOUBLE') ||\n typeUpper.includes('NUMERIC') ||\n typeUpper.includes('DECIMAL')\n ) {\n return String(defaultValue);\n }\n\n // JSON types\n if (typeUpper.includes('JSON')) {\n if (typeof defaultValue === 'string') {\n return `'${defaultValue.replace(/'/g, \"''\")}'`;\n }\n return `'${JSON.stringify(defaultValue).replace(/'/g, \"''\")}'`;\n }\n\n // Date/timestamp types\n if (\n typeUpper.includes('DATE') ||\n typeUpper.includes('TIME') ||\n typeUpper.includes('TIMESTAMP')\n ) {\n if (defaultValue instanceof Date) {\n return `'${defaultValue.toISOString()}'`;\n }\n return `'${String(defaultValue).replace(/'/g, \"''\")}'`;\n }\n\n // Default: treat as string\n if (typeof defaultValue === 'string') {\n return `'${defaultValue.replace(/'/g, \"''\")}'`;\n }\n\n return String(defaultValue);\n}\n\n/**\n * Generates a CREATE INDEX statement\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns SQL CREATE INDEX statement\n *\n * @example\n * ```typescript\n * const sql = generateCreateIndexStatement('users', {\n * name: 'idx_users_email',\n * columns: ['email'],\n * unique: true\n * });\n * // Returns: \"CREATE UNIQUE INDEX idx_users_email ON users (email)\"\n * ```\n */\nexport function generateCreateIndexStatement(\n table: string,\n index: IndexDefinition,\n): string {\n const parts: string[] = ['CREATE'];\n\n // UNIQUE modifier\n if (index.unique) {\n parts.push('UNIQUE');\n }\n\n parts.push('INDEX');\n\n // Index name\n parts.push(index.name);\n\n // ON table\n parts.push(`ON ${table}`);\n\n // Column list\n const columns = index.columns.join(', ');\n parts.push(`(${columns})`);\n\n // WHERE clause (partial index)\n if (index.where) {\n parts.push(`WHERE ${index.where}`);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Validates a table name to prevent SQL injection\n *\n * @param tableName - Table name to validate\n * @throws Error if table name contains invalid characters\n */\nexport function validateTableName(tableName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {\n throw new Error(\n `Invalid table name: ${tableName}. Table names must start with a letter or underscore and contain only alphanumeric characters and underscores.`,\n );\n }\n}\n\n/**\n * Validates a column name to prevent SQL injection\n *\n * @param columnName - Column name to validate\n * @throws Error if column name contains invalid characters\n */\nexport function validateColumnName(columnName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(columnName)) {\n throw new Error(\n `Invalid column name: ${columnName}. Column names must start with a letter or underscore and contain only alphanumeric characters and underscores.`,\n );\n }\n}\n\n/**\n * Validates an index name to prevent SQL injection\n *\n * @param indexName - Index name to validate\n * @throws Error if index name contains invalid characters\n */\nexport function validateIndexName(indexName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(indexName)) {\n throw new Error(\n `Invalid index name: ${indexName}. Index names must start with a letter or underscore and contain only alphanumeric characters and underscores.`,\n );\n }\n}\n","import { DatabaseError, loadEnvConfig } from '@happyvertical/utils';\nimport { Pool } from 'pg';\nimport { DatabaseSchemaManager } from './schema-manager';\nimport {\n generateAddColumnStatement,\n generateCreateIndexStatement,\n validateColumnName,\n validateIndexName,\n validateTableName,\n} from './shared/alter-utils';\nimport type {\n QueryResult as BaseQueryResult,\n ColumnDefinition,\n ColumnDefinitionWithName,\n DatabaseInterface,\n IndexDefinition,\n SchemaInitializationOptions,\n SessionHandle,\n TableInterface,\n TableSchemaInfo,\n TransactionHandle,\n UpsertOptions,\n VectorCapabilities,\n VectorIndexOptions,\n VectorSearchOptions,\n VectorSearchResult,\n} from './shared/types';\nimport { buildWhere, formatDbError } from './shared/utils';\n\n/**\n * Configuration options for PostgreSQL database connections\n */\nexport interface PostgresOptions {\n /**\n * Connection URL for PostgreSQL\n */\n url?: string;\n\n /**\n * Database name\n */\n database?: string;\n\n /**\n * Database server hostname\n */\n host?: string;\n\n /**\n * Username for authentication\n */\n user?: string;\n\n /**\n * Password for authentication\n */\n password?: string;\n\n /**\n * Port number for the PostgreSQL server\n */\n port?: number;\n\n /**\n * Cache key for connection pooling.\n * If provided, the same dbid returns the same cached connection.\n * When omitted, a key is derived from the connection URL.\n */\n dbid?: string;\n\n /**\n * Maximum number of connections in the pool.\n * Defaults to 20. The pg library defaults to 10, which is too low\n * for applications with many SMRT collections.\n */\n max?: number;\n\n /**\n * Schema definitions for tables.\n * Accepts a record or a lazy function (see SchemasOption).\n *\n * **Postgres ignores this option** — tables are managed by migrations.\n * The option exists so callers can pass schemas uniformly to all adapters\n * without knowing the adapter type. Only JSON/DuckDB adapters resolve it.\n */\n schemas?: import('./shared/types').SchemasOption;\n}\n\n/**\n * Module-level cache for PostgreSQL connections.\n * Keyed by dbid (or derived from connection URL).\n * Prevents creating multiple pg.Pool instances for the same database.\n */\nconst connectionCache = new Map<string, DatabaseInterface>();\nconst pendingConnections = new Map<string, Promise<DatabaseInterface>>();\n\ntype PostgresQueryExecutor = {\n query: (\n sql: string,\n values?: any[],\n ) => Promise<{ rows: any[]; rowCount: number | null }>;\n};\n\n/**\n * Clears the PostgreSQL connection cache.\n * Useful for test isolation and reconnection scenarios.\n */\nexport function clearPostgresConnectionCache(): void {\n connectionCache.clear();\n pendingConnections.clear();\n}\n\n/**\n * Operator for the given distance metric in pgvector\n */\nfunction vectorOperator(metric: 'cosine' | 'l2' | 'ip'): string {\n switch (metric) {\n case 'cosine':\n return '<=>';\n case 'l2':\n return '<->';\n case 'ip':\n return '<#>';\n default:\n return '<=>';\n }\n}\n\nfunction getMaxPostgresParameterIndex(sql: string): number {\n let maxIndex = 0;\n for (const match of sql.matchAll(/\\$(\\d+)/g)) {\n const index = Number(match[1]);\n if (Number.isSafeInteger(index) && index > maxIndex) {\n maxIndex = index;\n }\n }\n return maxIndex;\n}\n\nfunction usesSingleArrayParameter(sql: string): boolean {\n const identifier = String.raw`(?:\"[^\"]+\"|[a-z_][\\w$]*)`;\n const qualifiedIdentifier = String.raw`${identifier}(?:\\s*\\.\\s*${identifier})?`;\n const arrayType = String.raw`${qualifiedIdentifier}(?:\\s*\\([^)]*\\))?\\s*\\[\\]`;\n\n return (\n new RegExp(String.raw`\\$1\\s*::\\s*${arrayType}`, 'i').test(sql) ||\n new RegExp(\n String.raw`\\bCAST\\s*\\(\\s*\\$1\\s+AS\\s+${arrayType}\\s*\\)`,\n 'i',\n ).test(sql) ||\n /\\b(?:ANY|ALL|SOME)\\s*\\(\\s*\\$1\\s*\\)/i.test(sql)\n );\n}\n\nfunction normalizeRawQueryValues(sql: string, values: any[]): any[] {\n if (values.length !== 1 || !Array.isArray(values[0])) {\n return values;\n }\n\n const valuesArray = values[0];\n const maxParameterIndex = getMaxPostgresParameterIndex(sql);\n\n if (maxParameterIndex === 1 && usesSingleArrayParameter(sql)) {\n return values;\n }\n\n if (maxParameterIndex === 0 || maxParameterIndex === valuesArray.length) {\n return valuesArray;\n }\n\n return values;\n}\n\nfunction rewriteQuestionMarkPlaceholders(sql: string): {\n sql: string;\n count: number;\n} {\n let output = '';\n let count = 0;\n let index = 0;\n\n const copyQuoted = (quote: \"'\" | '\"', escaped = false) => {\n output += quote;\n index += 1;\n\n while (index < sql.length) {\n const char = sql[index];\n output += char;\n index += 1;\n\n if (escaped && char === '\\\\' && index < sql.length) {\n output += sql[index];\n index += 1;\n continue;\n }\n\n if (char === quote) {\n if (sql[index] === quote) {\n output += sql[index];\n index += 1;\n continue;\n }\n break;\n }\n }\n };\n\n const copyUntil = (end: string) => {\n const endIndex = sql.indexOf(end, index + end.length);\n if (endIndex === -1) {\n output += sql.slice(index);\n index = sql.length;\n return;\n }\n\n output += sql.slice(index, endIndex + end.length);\n index = endIndex + end.length;\n };\n\n while (index < sql.length) {\n const char = sql[index];\n const next = sql[index + 1];\n\n if ((char === 'E' || char === 'e') && next === \"'\") {\n output += char;\n index += 1;\n copyQuoted(\"'\", true);\n continue;\n }\n\n if (char === \"'\") {\n copyQuoted(\"'\");\n continue;\n }\n\n if (char === '\"') {\n copyQuoted('\"');\n continue;\n }\n\n if (char === '-' && next === '-') {\n const endIndex = sql.indexOf('\\n', index + 2);\n if (endIndex === -1) {\n output += sql.slice(index);\n index = sql.length;\n } else {\n output += sql.slice(index, endIndex + 1);\n index = endIndex + 1;\n }\n continue;\n }\n\n if (char === '/' && next === '*') {\n copyUntil('*/');\n continue;\n }\n\n if (char === '$') {\n const tag = sql.slice(index).match(/^\\$[A-Za-z_][\\w$]*\\$|^\\$\\$/);\n if (tag) {\n copyUntil(tag[0]);\n continue;\n }\n }\n\n if (char === '?' && next !== '|' && next !== '&') {\n count += 1;\n output += `$${count}`;\n index += 1;\n continue;\n }\n\n output += char;\n index += 1;\n }\n\n return { sql: output, count };\n}\n\nfunction usesSingleQuestionArrayParameter(sql: string): boolean {\n const identifier = String.raw`(?:\"[^\"]+\"|[a-z_][\\w$]*)`;\n const qualifiedIdentifier = String.raw`${identifier}(?:\\s*\\.\\s*${identifier})?`;\n const arrayType = String.raw`${qualifiedIdentifier}(?:\\s*\\([^)]*\\))?\\s*\\[\\]`;\n\n return (\n new RegExp(String.raw`\\?\\s*::\\s*${arrayType}`, 'i').test(sql) ||\n new RegExp(String.raw`\\bCAST\\s*\\(\\s*\\?\\s+AS\\s+${arrayType}\\s*\\)`, 'i').test(\n sql,\n ) ||\n /\\b(?:ANY|ALL|SOME)\\s*\\(\\s*\\?\\s*\\)/i.test(sql)\n );\n}\n\nfunction normalizeQuestionMarkQueryValues(\n sql: string,\n values: any[],\n placeholderCount: number,\n): any[] {\n if (values.length !== 1 || !Array.isArray(values[0])) {\n return values;\n }\n\n if (placeholderCount === 1 && usesSingleQuestionArrayParameter(sql)) {\n return values;\n }\n\n if (placeholderCount === values[0].length) {\n return values[0];\n }\n\n return values;\n}\n\nfunction normalizePostgresRawQuery(\n sql: string,\n values: any[],\n): { sql: string; values: any[] } {\n if (getMaxPostgresParameterIndex(sql) > 0) {\n return { sql, values: normalizeRawQueryValues(sql, values) };\n }\n\n const rewritten = rewriteQuestionMarkPlaceholders(sql);\n const placeholderCount = rewritten.count;\n const queryValues = normalizeQuestionMarkQueryValues(\n sql,\n values,\n placeholderCount,\n );\n\n if (placeholderCount > 0 && placeholderCount === queryValues.length) {\n return {\n sql: rewritten.sql,\n values: queryValues,\n };\n }\n\n return { sql, values: normalizeRawQueryValues(sql, values) };\n}\n\n/**\n * pgvector index operator class for CREATE INDEX\n */\nfunction vectorOpsClass(metric: 'cosine' | 'l2' | 'ip'): string {\n switch (metric) {\n case 'cosine':\n return 'vector_cosine_ops';\n case 'l2':\n return 'vector_l2_ops';\n case 'ip':\n return 'vector_ip_ops';\n default:\n return 'vector_cosine_ops';\n }\n}\n\n/**\n * Convert a number[] to a pgvector literal string: '[0.1,0.2,0.3]'\n */\nfunction toVectorLiteral(embedding: number[]): string {\n if (embedding.length === 0) {\n throw new DatabaseError('Vector embedding must not be empty', {});\n }\n for (let i = 0; i < embedding.length; i++) {\n if (!Number.isFinite(embedding[i])) {\n throw new DatabaseError(\n 'Vector embedding contains invalid value (NaN or Infinity)',\n { index: i, value: embedding[i] },\n );\n }\n }\n return `[${embedding.join(',')}]`;\n}\n\n/**\n * Creates vector capabilities backed by pgvector for a PostgreSQL pool.\n *\n * @param pool - PostgreSQL connection pool\n * @returns VectorCapabilities implementation\n */\nfunction createVectorCapabilities(pool: Pool): VectorCapabilities {\n return {\n async ensureColumn(\n table: string,\n column: string,\n dimensions: number,\n ): Promise<void> {\n if (!Number.isInteger(dimensions) || dimensions <= 0) {\n throw new DatabaseError(\n 'Vector dimensions must be a positive integer',\n { dimensions },\n );\n }\n try {\n await pool.query('CREATE EXTENSION IF NOT EXISTS vector');\n await pool.query(\n `ALTER TABLE \"${table}\" ADD COLUMN IF NOT EXISTS \"${column}\" vector(${dimensions})`,\n );\n } catch (e) {\n throw new DatabaseError('Failed to ensure vector column', {\n table,\n column,\n dimensions,\n originalError: formatDbError(e),\n });\n }\n },\n\n async ensureIndex(\n table: string,\n column: string,\n options?: VectorIndexOptions,\n ): Promise<void> {\n const metric = options?.metric || 'cosine';\n const indexType = options?.type || 'hnsw';\n const opsClass = vectorOpsClass(metric);\n const indexName = `idx_${table}_${column}_${metric}_${indexType}`;\n\n try {\n await pool.query(\n `CREATE INDEX IF NOT EXISTS \"${indexName}\" ON \"${table}\" USING ${indexType} (\"${column}\" ${opsClass})`,\n );\n } catch (e) {\n throw new DatabaseError('Failed to ensure vector index', {\n table,\n column,\n indexName,\n originalError: formatDbError(e),\n });\n }\n },\n\n async upsertVector(\n table: string,\n where: Record<string, any>,\n column: string,\n embedding: number[],\n ): Promise<void> {\n const keys = Object.keys(where);\n const values = Object.values(where);\n const conditions = keys\n .map((key, i) => `\"${key}\" IS NOT DISTINCT FROM $${i + 1}`)\n .join(' AND ');\n const vectorParam = `$${values.length + 1}`;\n\n try {\n await pool.query(\n `UPDATE \"${table}\" SET \"${column}\" = ${vectorParam}::vector WHERE ${conditions}`,\n [...values, toVectorLiteral(embedding)],\n );\n } catch (e) {\n throw new DatabaseError('Failed to upsert vector', {\n table,\n column,\n where,\n originalError: formatDbError(e),\n });\n }\n },\n\n async search(\n table: string,\n column: string,\n embedding: number[],\n options?: VectorSearchOptions,\n ): Promise<VectorSearchResult[]> {\n const metric = options?.metric || 'cosine';\n const limit = options?.limit || 10;\n const op = vectorOperator(metric);\n\n // $1 is the query vector; user-provided WHERE params use $2, $3, etc.\n const queryParams: any[] = [toVectorLiteral(embedding)];\n\n let whereClause = `\"${column}\" IS NOT NULL`;\n if (options?.where) {\n whereClause += ` AND (${options.where})`;\n if (options.params) {\n queryParams.push(...options.params);\n }\n }\n\n const limitParam = `$${queryParams.length + 1}`;\n queryParams.push(limit);\n\n const sql = `SELECT *, (\"${column}\" ${op} $1::vector) AS distance FROM \"${table}\" WHERE ${whereClause} ORDER BY \"${column}\" ${op} $1::vector LIMIT ${limitParam}`;\n\n try {\n const result = await pool.query(sql, queryParams);\n\n return result.rows.map((row: Record<string, any>) => ({\n ...row,\n id: row.id as string,\n distance: Number.parseFloat(row.distance),\n }));\n } catch (e) {\n throw new DatabaseError('Failed to execute vector search', {\n table,\n column,\n metric,\n limit,\n originalError: formatDbError(e),\n });\n }\n },\n };\n}\n\n/**\n * Creates a PostgreSQL database adapter\n *\n * Loads configuration from environment variables with backward compatibility:\n * - First checks HAVE_SQL_* environment variables (new standard)\n * - Falls back to SQLOO_* environment variables (legacy)\n * - User-provided options always take precedence\n *\n * Environment variables:\n * - HAVE_SQL_URL / SQLOO_URL → Connection string (takes precedence)\n * - HAVE_SQL_DATABASE / SQLOO_DATABASE → Database name\n * - HAVE_SQL_HOST / SQLOO_HOST → Host (default: 'localhost')\n * - HAVE_SQL_USER / SQLOO_USER → Username\n * - HAVE_SQL_PASSWORD / SQLOO_PASSWORD → Password\n * - HAVE_SQL_PORT / SQLOO_PORT → Port (default: 5432)\n *\n * @param options - PostgreSQL connection options\n * @returns Database interface for PostgreSQL\n */\nexport async function getDatabase(\n options: PostgresOptions = {},\n): Promise<DatabaseInterface> {\n // --- Connection cache: return existing pool for same dbid/URL ---\n // Derive cache key from explicit dbid, options, or env vars so that\n // env-only callers also benefit from caching/deduplication.\n const envUrl = process.env.HAVE_SQL_URL || process.env.SQLOO_URL || null;\n const envDatabase =\n process.env.HAVE_SQL_DATABASE || process.env.SQLOO_DATABASE || null;\n const envHost =\n process.env.HAVE_SQL_HOST || process.env.SQLOO_HOST || 'localhost';\n const envUser = process.env.HAVE_SQL_USER || process.env.SQLOO_USER || '';\n const envPortRaw = process.env.HAVE_SQL_PORT || process.env.SQLOO_PORT;\n const envPort = envPortRaw ? Number(envPortRaw) || 5432 : 5432;\n\n const derivedHost = options.host || envHost;\n const derivedPort = options.port || envPort;\n const derivedDatabase = options.database || envDatabase;\n const derivedUser = options.user || envUser;\n\n const cacheKey =\n options.dbid ||\n options.url ||\n (derivedDatabase\n ? `pg:${derivedUser ? `${derivedUser}@` : ''}${derivedHost}:${derivedPort}/${derivedDatabase}`\n : envUrl || null);\n\n if (cacheKey) {\n const cached = connectionCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // Deduplicate concurrent calls for the same key\n const pending = pendingConnections.get(cacheKey);\n if (pending) return pending;\n }\n\n const connectionPromise = createDatabase(options, cacheKey);\n\n if (cacheKey) {\n pendingConnections.set(cacheKey, connectionPromise);\n connectionPromise.finally(() => {\n if (cacheKey) pendingConnections.delete(cacheKey);\n });\n }\n\n return connectionPromise;\n}\n\n/**\n * Internal: creates the actual database connection and caches it.\n */\nasync function createDatabase(\n options: PostgresOptions,\n cacheKey: string | null,\n): Promise<DatabaseInterface> {\n // Load HAVE_SQL_* environment variables first\n const config = loadEnvConfig(options, {\n packageName: 'sql',\n schema: {\n url: 'string',\n database: 'string',\n host: 'string',\n port: 'number',\n user: 'string',\n password: 'string',\n },\n });\n\n // For backward compatibility, fall back to SQLOO_* if HAVE_SQL_* not set\n // Only check legacy vars if the new ones aren't present\n if (!config.url && !config.host && !config.database && !config.user) {\n const legacyConfig = loadEnvConfig(\n {},\n {\n prefix: 'SQLOO',\n schema: {\n url: 'string',\n database: 'string',\n host: 'string',\n port: 'number',\n user: 'string',\n password: 'string',\n },\n },\n );\n\n // Merge legacy config, but don't override user options or HAVE_SQL_* vars\n for (const [key, value] of Object.entries(legacyConfig)) {\n if ((config as any)[key] === undefined && value !== undefined) {\n (config as any)[key] = value;\n }\n }\n }\n\n // Apply defaults\n const { database, host = 'localhost', user, password, port = 5432 } = config;\n\n // Construct url if not provided (for DatabaseInterface requirement)\n const url: string =\n (config.url as string) ||\n `postgresql://${user}${password ? `:${password}` : ''}@${host}:${port}/${database || 'postgres'}`;\n\n // Create a connection pool with explicit max to prevent exhaustion.\n // pg defaults to 10 which is too low for SMRT apps that sync 30+ table\n // schemas on startup. Default to 20 but allow callers to override.\n const poolMax = options.max ?? 20;\n const pool = new Pool(\n config.url\n ? { connectionString: config.url as string, max: poolMax }\n : {\n host: host as string,\n user: user as string,\n password: password as string,\n port: port as number,\n database: database as string,\n max: poolMax,\n },\n );\n\n // Wrap pool.end() to evict from cache so stale pools are never returned.\n // This fixes the \"Cannot use a pool after calling end on the pool\" error\n // when tests or shutdown code calls db.client.end() and subsequent calls\n // to getDatabase() would otherwise return the ended pool.\n const originalEnd = pool.end.bind(pool);\n const evictFromCache = () => {\n for (const [key, cached] of connectionCache.entries()) {\n if (cached.client === pool) {\n connectionCache.delete(key);\n }\n }\n };\n (pool as any).end = (callback?: () => void) => {\n evictFromCache();\n if (callback) {\n return originalEnd(callback);\n }\n return originalEnd();\n };\n\n const client = pool;\n\n /**\n * Serializes a value for database storage\n * Converts objects and arrays to JSON strings\n * Converts Dates to ISO strings\n * Passes through primitives unchanged\n */\n const serializeValue = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return value;\n };\n\n /**\n * Serializes all values in an object for database storage\n */\n const serializeRecord = (\n record: Record<string, any>,\n ): Record<string, any> => {\n const serialized: Record<string, any> = {};\n for (const [key, value] of Object.entries(record)) {\n // Skip undefined values - they cannot be passed to the database\n if (value === undefined) {\n continue;\n }\n serialized[key] = serializeValue(value);\n }\n return serialized;\n };\n\n let serverVersionNumPromise: Promise<number> | undefined;\n const nullsNotDistinctIndexCache = new Map<string, Promise<boolean>>();\n\n const hasNullConflictValue = (\n conflictColumns: string[],\n data: Record<string, any>,\n ): boolean => conflictColumns.some((col) => data[col] === null);\n\n const validateUpsertConflictColumns = (\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): void => {\n const missingColumns = conflictColumns.filter(\n (col) => !(col in serializedData),\n );\n\n if (missingColumns.length > 0) {\n throw new DatabaseError('Conflict columns missing from data', {\n table,\n conflictColumns,\n missingColumns,\n availableColumns: Object.keys(serializedData),\n hint: 'All columns specified in ON CONFLICT must be present in the data being inserted. Undefined values should be replaced with null or an appropriate default.',\n });\n }\n };\n\n const getServerVersionNum = async (): Promise<number> => {\n serverVersionNumPromise ??= client\n .query('SHOW server_version_num')\n .then((result) => Number(result.rows[0]?.server_version_num) || 0);\n return serverVersionNumPromise;\n };\n\n const hasNativeNullsNotDistinctIndex = async (\n table: string,\n conflictColumns: string[],\n ): Promise<boolean> => {\n const versionNum = await getServerVersionNum();\n if (versionNum < 150000) return false;\n\n const cacheKey = `${table}:${conflictColumns.join(',')}`;\n let cached = nullsNotDistinctIndexCache.get(cacheKey);\n if (!cached) {\n cached = client\n .query(\n `\n SELECT 1\n FROM pg_index i\n WHERE i.indrelid = to_regclass($1)\n AND i.indisunique\n AND i.indnullsnotdistinct\n AND ARRAY(\n SELECT a.attname\n FROM unnest(i.indkey) WITH ORDINALITY AS cols(attnum, ord)\n JOIN pg_attribute a\n ON a.attrelid = i.indrelid\n AND a.attnum = cols.attnum\n ORDER BY cols.ord\n ) = $2::text[]\n LIMIT 1\n `,\n [table, conflictColumns],\n )\n .then((result) => result.rows.length > 0)\n .catch(() => false);\n nullsNotDistinctIndexCache.set(cacheKey, cached);\n }\n\n return cached;\n };\n\n const buildPostgresUpsertParts = (\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ) => {\n const keys = Object.keys(serializedData);\n const values = Object.values(serializedData);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const updateSet = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const conflict = conflictColumns.join(', ');\n\n return { keys, values, placeholders, updateSet, conflict };\n };\n\n const executeStandardPostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const { keys, values, placeholders, updateSet, conflict } =\n buildPostgresUpsertParts(conflictColumns, serializedData);\n const sql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders}) ON CONFLICT(${conflict}) DO UPDATE SET ${updateSet}`;\n const result = await executor.query(sql, values);\n return { operation: 'upsert', affected: result.rowCount ?? 0 };\n };\n\n const executeNullAwarePostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const { keys, values, placeholders } = buildPostgresUpsertParts(\n conflictColumns,\n serializedData,\n );\n const lockKey = conflictColumns\n .map((col) => `${col}:${JSON.stringify(serializedData[col])}`)\n .join('|');\n\n await executor.query(\n 'SELECT pg_advisory_xact_lock(hashtext($1), hashtext($2))',\n [`@happyvertical/sql.upsert:${table}`, lockKey],\n );\n\n const updateSet = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const whereStart = values.length + 1;\n const whereClause = conflictColumns\n .map((col, i) => `${col} IS NOT DISTINCT FROM $${whereStart + i}`)\n .join(' AND ');\n const whereValues = conflictColumns.map((col) => serializedData[col]);\n const updateSql = `UPDATE ${table} SET ${updateSet} WHERE ${whereClause}`;\n const updateResult = await executor.query(updateSql, [\n ...values,\n ...whereValues,\n ]);\n\n if ((updateResult.rowCount ?? 0) > 0) {\n return { operation: 'upsert', affected: updateResult.rowCount ?? 0 };\n }\n\n const insertSql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;\n const insertResult = await executor.query(insertSql, values);\n return { operation: 'upsert', affected: insertResult.rowCount ?? 0 };\n };\n\n const executeNullAwarePostgresUpsertInTransaction = async (\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const txClient = await client.connect();\n\n try {\n await txClient.query('BEGIN');\n const result = await executeNullAwarePostgresUpsert(\n txClient,\n table,\n conflictColumns,\n serializedData,\n );\n await txClient.query('COMMIT');\n return result;\n } catch (error) {\n await txClient.query('ROLLBACK');\n throw error;\n } finally {\n txClient.release();\n }\n };\n\n const executePostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options: UpsertOptions | undefined,\n acquireTransaction: boolean,\n ): Promise<BaseQueryResult> => {\n const serializedData = serializeRecord(data);\n validateUpsertConflictColumns(table, conflictColumns, serializedData);\n\n if (\n options?.nullsDistinct ||\n !hasNullConflictValue(conflictColumns, serializedData)\n ) {\n return executeStandardPostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n if (await hasNativeNullsNotDistinctIndex(table, conflictColumns)) {\n return executeStandardPostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n if (!acquireTransaction) {\n return executeNullAwarePostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n return executeNullAwarePostgresUpsertInTransaction(\n table,\n conflictColumns,\n serializedData,\n );\n };\n\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n * @throws Error if the insert operation fails\n *\n * @example Single record insert:\n * ```typescript\n * await db.insert('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * ```\n *\n * @example Multiple record insert:\n * ```typescript\n * await db.insert('users', [\n * { name: 'John', email: 'john@example.com' },\n * { name: 'Jane', email: 'jane@example.com' }\n * ]);\n * ```\n */\n const insert = async (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ): Promise<BaseQueryResult> => {\n // If data is an array, we need to handle multiple rows\n if (Array.isArray(data)) {\n // Serialize all records in the array\n const serializedRecords = data.map((record) => serializeRecord(record));\n const keys = Object.keys(serializedRecords[0]);\n const placeholders = serializedRecords\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(\n ', ',\n )}) VALUES ${placeholders}`;\n const values = serializedRecords.reduce<any[]>(\n (acc, row) => acc.concat(Object.values(row)),\n [],\n );\n const result = await client.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n // If data is an object, we handle a single row\n const serializedData = serializeRecord(data);\n const keys = Object.keys(serializedData);\n const values = Object.values(serializedData);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(\n ', ',\n )}) VALUES (${placeholders})`;\n const result = await client.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n };\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to query result\n */\n const get = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any> | null> => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n try {\n const result = await client.query(query, values);\n return result.rows[0] || null;\n } catch (e) {\n throw new DatabaseError('Failed to retrieve record from table', {\n table,\n sql: query,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to array of records\n */\n const list = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any>[]> => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n try {\n const result = await client.query(query, values);\n return result.rows;\n } catch (e) {\n throw new DatabaseError('Failed to list records from table', {\n table,\n sql: query,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update\n * @param data - New data to set\n * @returns Promise resolving to operation result\n */\n const update = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n // Serialize the data to update\n const serializedData = serializeRecord(data);\n const keys = Object.keys(serializedData);\n const values = Object.values(serializedData);\n const setClause = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n try {\n const result = await client.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n } catch (e) {\n throw new DatabaseError('Failed to update records in table', {\n table,\n sql,\n values: [...values, ...whereValues],\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n * @throws Error if the upsert operation fails\n */\n const upsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ): Promise<BaseQueryResult> => {\n try {\n return await executePostgresUpsert(\n client,\n table,\n conflictColumns,\n data,\n options,\n true,\n );\n } catch (e) {\n if (\n e instanceof DatabaseError &&\n e.message === 'Conflict columns missing from data'\n ) {\n throw e;\n }\n\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n values: data,\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record\n * @returns Promise resolving to the query result or insert result\n */\n const getOrInsert = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<Record<string, any>> => {\n const result = await get(table, where);\n if (result) return result;\n await insert(table, data);\n\n const inserted = await get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n };\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion\n * @returns Promise resolving to operation result with count of deleted rows\n * @throws Error if the delete operation fails\n */\n const deleteRecords = async (\n table: string,\n where: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n validateTableName(table);\n\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n\n try {\n const result = await client.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n } catch (e) {\n throw new DatabaseError('Failed to delete records from table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted)\n * @returns Promise resolving to count of matching records\n * @throws Error if the count operation fails\n */\n const count = async (\n table: string,\n where?: Record<string, any>,\n ): Promise<number> => {\n validateTableName(table);\n\n try {\n if (!where || Object.keys(where).length === 0) {\n // Count all records\n const result = await client.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n\n // Count with conditions\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n\n const result = await client.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n\n return Number(result.rows[0]?.count) || 0;\n } catch (e) {\n throw new DatabaseError('Failed to count records in table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param tableName - Table name\n * @returns TableMethods interface for the specified table\n */\n const table = (tableName: string): TableInterface => {\n return {\n insert: (data) => insert(tableName, data),\n get: (data) => get(tableName, data),\n list: (data) => list(tableName, data),\n };\n };\n\n /**\n * Template and values extracted from a tagged template literal\n */\n interface SqlTemplate {\n /**\n * SQL query with parameter placeholders\n */\n sql: string;\n\n /**\n * Values to use as parameters\n */\n values: any[];\n }\n\n /**\n * Parses a tagged template literal into a SQL query and values\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Object with SQL query and values array\n */\n const parseTemplate = (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): SqlTemplate => {\n let sql = strings[0];\n const values = [];\n for (let i = 0; i < vars.length; i++) {\n values.push(vars[i]);\n sql += `$${i + 1}${strings[i + 1]}`;\n }\n return { sql, values };\n };\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n */\n const pluck = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<any> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await client.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n // Return the first column value from the first row\n return Object.values(firstRow)[0];\n } catch (e) {\n throw new DatabaseError('Failed to execute pluck query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n */\n const single = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any> | null> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await client.query(sql, values);\n return result.rows[0] || null;\n } catch (e) {\n throw new DatabaseError('Failed to execute single query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n */\n const many = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any>[]> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await client.query(sql, values);\n return result.rows;\n } catch (e) {\n throw new DatabaseError('Failed to execute many query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n */\n const execute = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<void> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n await client.query(sql, values);\n } catch (e) {\n throw new DatabaseError('Failed to execute query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * Uses PostgreSQL-native placeholders ($1, $2, ...). Legacy ? placeholders\n * are converted only when the placeholder count matches the supplied values,\n * so Postgres operators such as JSONB ? remain intact.\n *\n * @param sql - SQL query string\n * @param values - Variables to use as parameters\n * @returns Promise resolving to query result with rows and count\n */\n const query = async (\n sql: string,\n ...values: any[]\n ): Promise<{ rows: Record<string, any>[]; rowCount: number }> => {\n const query = normalizePostgresRawQuery(sql, values);\n try {\n const result = await client.query(query.sql, query.values);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } catch (e) {\n throw new DatabaseError('Failed to execute raw query', {\n sql: query.sql,\n values: query.values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Acquire a pinned connection from the pool for session-scoped state such as\n * `pg_advisory_lock`. Every query on the returned handle runs on the same\n * client until {@link SessionHandle.release} drops the connection (which\n * frees any session locks it held). The connection is held for the handle's\n * lifetime, so hold one session per process, not per operation.\n */\n const acquireSession = async (): Promise<SessionHandle> => {\n const sessionClient = await pool.connect();\n let released = false;\n let lost = false;\n\n // pg-pool removes its idle 'error' listener when a client is checked out.\n // A session is pinned for the process lifetime and mostly idle between\n // queries, so a backend disconnect/failover would emit 'error' on a\n // listener-less client and crash the process. Absorb it and mark the\n // session dead instead; the next query()/isActive() surfaces it.\n sessionClient.on('error', () => {\n lost = true;\n });\n\n return {\n query: async (sql: string, ...values: any[]) => {\n if (released) {\n throw new DatabaseError('Session has been released', {});\n }\n if (lost) {\n throw new DatabaseError('Session connection was lost', {});\n }\n const normalized = normalizePostgresRawQuery(sql, values);\n try {\n const result = await sessionClient.query(\n normalized.sql,\n normalized.values,\n );\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } catch (e) {\n throw new DatabaseError('Failed to execute session query', {\n sql: normalized.sql,\n values: normalized.values,\n originalError: formatDbError(e),\n });\n }\n },\n isActive: () => !released && !lost,\n release: async () => {\n if (released) return;\n released = true;\n // Free session advisory locks before tearing down so the contract\n // \"after release() the locks are gone\" holds deterministically — the\n // destroy below is async (TCP teardown) and resolves later. Skip on a\n // lost connection (nothing to talk to; backend exit frees them anyway).\n if (!lost) {\n try {\n // A caller that left the connection in an aborted transaction\n // (BEGIN, a failed statement, then release) would make\n // pg_advisory_unlock_all() error with \"current transaction is\n // aborted\". Roll back first (a no-op when no transaction is open)\n // so the unlock runs and the deterministic-release contract holds.\n await sessionClient.query('ROLLBACK');\n } catch {\n // No open transaction, or already gone — proceed to unlock.\n }\n try {\n await sessionClient.query('SELECT pg_advisory_unlock_all()');\n } catch {\n // Best-effort; the destroy below frees locks at backend exit.\n }\n }\n // Destroy the physical connection rather than returning it to the pool.\n // Returning it would NOT clear residual session state, which could then\n // leak onto a connection later handed to unrelated code.\n sessionClient.release(true);\n },\n };\n };\n\n /**\n * Checks if a table exists in the database\n *\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\n const tableExists = async (tableName: string): Promise<boolean> => {\n const result = await client.query(\n `SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = 'public')`,\n [tableName],\n );\n return result.rows[0].exists;\n };\n\n /**\n * Synchronizes database schema with provided SQL DDL\n * Creates tables if they don't exist and adds missing columns\n * Also executes CREATE INDEX statements\n *\n * @param schema - SQL schema definition with CREATE TABLE and CREATE INDEX statements\n * @returns Promise that resolves when schema is synchronized\n */\n const syncSchema = async (schema: string): Promise<void> => {\n const commands = schema\n .trim()\n .split(';')\n .filter((command) => command.trim() !== '');\n\n // Match CREATE INDEX statements (Issue #867)\n // Supports: CREATE INDEX, CREATE UNIQUE INDEX, with IF NOT EXISTS\n const createIndexRegex =\n /CREATE (UNIQUE )?INDEX (IF NOT EXISTS )?\"?(\\w+)\"? ON \"?(\\w+)\"?\\s*\\(([^)]+)\\)/i;\n\n // Pre-scan commands to collect all index names for batch existence check (Issue #798)\n const indexNames: string[] = [];\n for (const command of commands) {\n const indexMatch = command.trim().match(createIndexRegex);\n if (indexMatch) {\n indexNames.push(indexMatch[3]);\n }\n }\n\n // Batch query to check which indexes already exist\n const existingIndexes = new Set<string>();\n if (indexNames.length > 0) {\n const result = await client.query(\n `SELECT indexname FROM pg_indexes\n WHERE schemaname = 'public' AND indexname = ANY($1::text[])`,\n [indexNames],\n );\n for (const row of result.rows) {\n existingIndexes.add(row.indexname);\n }\n }\n\n for (const command of commands) {\n const trimmedCommand = command.trim();\n\n // Match CREATE TABLE with optional quotes around table name\n // Supports: CREATE TABLE foo, CREATE TABLE \"foo\", CREATE TABLE IF NOT EXISTS \"foo\"\n const createTableRegex =\n /CREATE TABLE (IF NOT EXISTS )?\"?(\\w+)\"? \\(([\\s\\S]+)\\)/i;\n const tableMatch = trimmedCommand.match(createTableRegex);\n\n if (tableMatch) {\n const tableName = tableMatch[2];\n const columns = tableMatch[3].trim().split(',\\n');\n\n // Check if table exists\n const exists = await tableExists(tableName);\n\n if (!exists) {\n // Table doesn't exist, create it\n await client.query(trimmedCommand);\n } else {\n // Table exists, check for missing columns\n for (const column of columns) {\n const columnDef = column.trim();\n // Match column name with optional quotes: \"id\" or id\n const columnMatch = columnDef.match(/\"?(\\w+)\"?\\s+(\\w+[^,]*)/);\n\n if (columnMatch) {\n const columnName = columnMatch[1];\n\n // Skip constraint definitions\n if (\n columnName.toUpperCase() === 'PRIMARY' ||\n columnName.toUpperCase() === 'FOREIGN' ||\n columnName.toUpperCase() === 'UNIQUE' ||\n columnName.toUpperCase() === 'CHECK' ||\n columnName.toUpperCase() === 'CONSTRAINT'\n ) {\n continue;\n }\n\n try {\n // Check if column exists\n const columnExists = await client.query(\n `SELECT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = $1\n AND column_name = $2\n AND table_schema = 'public'\n )`,\n [tableName, columnName],\n );\n\n if (!columnExists.rows[0].exists) {\n // Column doesn't exist, add it\n // Quote the table name for safety\n const alterCommand = `ALTER TABLE \"${tableName}\" ADD COLUMN ${columnDef}`;\n await client.query(alterCommand);\n }\n } catch (error) {\n // If there's an error checking/adding the column, log it but continue\n console.error(\n `Error adding column ${columnName} to ${tableName}:`,\n error,\n );\n }\n }\n }\n }\n continue;\n }\n\n const indexMatch = trimmedCommand.match(createIndexRegex);\n\n if (indexMatch) {\n const indexName = indexMatch[3];\n const indexTableName = indexMatch[4];\n\n // Use pre-fetched batch result instead of per-index query\n if (!existingIndexes.has(indexName)) {\n try {\n await client.query(trimmedCommand);\n // Track newly created index for idempotency within this call\n existingIndexes.add(indexName);\n } catch (error) {\n // Log error but continue - index creation failures shouldn't block schema sync\n console.warn(\n `Warning: Failed to create index ${indexName} on ${indexTableName}:`,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n continue;\n }\n\n // For any other DDL statements (like other CREATE commands), try to execute them\n // This provides forward compatibility for future DDL types\n if (\n trimmedCommand.toUpperCase().startsWith('CREATE ') &&\n !trimmedCommand.toUpperCase().includes('CREATE TABLE')\n ) {\n try {\n await client.query(trimmedCommand);\n } catch (error) {\n // Log but don't fail - the statement may have already been executed\n console.warn(\n `Warning: DDL statement may have failed:`,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n }\n };\n\n /**\n * Executes a callback within a database transaction\n * Automatically commits on success or rolls back on error\n *\n * @param callback - Function to execute within transaction\n * @returns Promise resolving to callback result\n */\n const transaction = async <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ): Promise<T> => {\n // Get a client from the pool for the transaction\n const txClient = await client.connect();\n\n try {\n await txClient.query('BEGIN');\n\n // Create a transaction-scoped database interface\n const txDb: DatabaseInterface = {\n url,\n client: txClient,\n insert: async (table, data) => {\n // Reuse insert logic but with transaction client\n if (Array.isArray(data)) {\n const keys = Object.keys(data[0]);\n const placeholders = data\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES ${placeholders}`;\n const values = data.reduce(\n (acc, row) => acc.concat(Object.values(row)),\n [] as any[],\n );\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n const keys = Object.keys(data);\n const values = Object.values(data);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n },\n get: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows[0] || null;\n },\n list: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows;\n },\n update: async (table, where, data) => {\n const keys = Object.keys(data);\n const values = Object.values(data);\n const setClause = keys\n .map((key, i) => `${key} = $${i + 1}`)\n .join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n const result = await txClient.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n },\n upsert: async (table, conflictColumns, data, options) =>\n executePostgresUpsert(\n txClient,\n table,\n conflictColumns,\n data,\n options,\n false,\n ),\n getOrInsert: async (table, where, data) => {\n const result = await txDb.get(table, where);\n if (result) return result;\n await txDb.insert(table, data);\n const inserted = await txDb.get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n },\n delete: async (table, where) => {\n validateTableName(table);\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n },\n count: async (table, where) => {\n validateTableName(table);\n if (!where || Object.keys(where).length === 0) {\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n return Number(result.rows[0]?.count) || 0;\n },\n table: (tableName) => ({\n insert: (data) => txDb.insert(tableName, data),\n get: (data) => txDb.get(tableName, data),\n list: (data) => txDb.list(tableName, data),\n }),\n many: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n single: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n pluck: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n execute: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n query: async (sql, ...values) => {\n const query = normalizePostgresRawQuery(sql, values);\n const result = await txClient.query(query.sql, query.values);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n },\n oo: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n oO: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n ox: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n xx: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n tableExists,\n syncSchema,\n transaction,\n };\n\n const result = await callback(txDb);\n await txClient.query('COMMIT');\n return result;\n } catch (error) {\n await txClient.query('ROLLBACK');\n throw error;\n } finally {\n txClient.release();\n }\n };\n\n /**\n * Begins a new transaction and returns a handle for manual control\n *\n * Unlike transaction(), this gives you explicit control over commit/rollback.\n * Ideal for test isolation where you want to rollback after each test.\n *\n * @returns Promise resolving to a TransactionHandle\n */\n const beginTransaction = async (): Promise<TransactionHandle> => {\n // Get a client from the pool for the transaction\n const txClient = await client.connect();\n await txClient.query('BEGIN');\n\n let active = true;\n\n const commit = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await txClient.query('COMMIT');\n active = false;\n txClient.release();\n };\n\n const rollback = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await txClient.query('ROLLBACK');\n active = false;\n txClient.release();\n };\n\n const isActive = (): boolean => active;\n\n // Create a transaction-scoped database interface with commit/rollback\n const txHandle: TransactionHandle = {\n url,\n client: txClient,\n insert: async (table, data) => {\n if (Array.isArray(data)) {\n const keys = Object.keys(data[0]);\n const placeholders = data\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES ${placeholders}`;\n const values = data.reduce(\n (acc, row) => acc.concat(Object.values(row)),\n [] as any[],\n );\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n const keys = Object.keys(data);\n const values = Object.values(data);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n },\n get: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows[0] || null;\n },\n list: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows;\n },\n update: async (table, where, data) => {\n const keys = Object.keys(data);\n const values = Object.values(data);\n const setClause = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n const result = await txClient.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n },\n upsert: async (table, conflictColumns, data, options) =>\n executePostgresUpsert(\n txClient,\n table,\n conflictColumns,\n data,\n options,\n false,\n ),\n getOrInsert: async (table, where, data) => {\n const result = await txHandle.get(table, where);\n if (result) return result;\n await txHandle.insert(table, data);\n const inserted = await txHandle.get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n },\n delete: async (table, where) => {\n validateTableName(table);\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n },\n count: async (table, where) => {\n validateTableName(table);\n if (!where || Object.keys(where).length === 0) {\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n return Number(result.rows[0]?.count) || 0;\n },\n table: (tableName) => ({\n insert: (data) => txHandle.insert(tableName, data),\n get: (data) => txHandle.get(tableName, data),\n list: (data) => txHandle.list(tableName, data),\n }),\n many: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n single: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n pluck: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n execute: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n query: async (sql, ...values) => {\n const query = normalizePostgresRawQuery(sql, values);\n const result = await txClient.query(query.sql, query.values);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n },\n oo: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n oO: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n ox: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n xx: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n tableExists,\n syncSchema,\n transaction,\n commit,\n rollback,\n isActive,\n };\n\n return txHandle;\n };\n\n // Shorthand aliases for query methods\n const oo = many; // (o)bjective-(o)bjects: returns multiple rows\n const oO = single; // (o)bjective-(O)bject: returns a single row\n const ox = pluck; // (o)bjective-(x): returns a single value\n const xx = execute; // (x)ecute-(x)ecute: executes without returning\n\n /**\n * Initialize database schemas from JSON manifest\n * Supports dependency resolution and schema overrides\n *\n * @param options - Schema initialization options\n * @returns Promise that resolves when schemas are initialized\n */\n const initializeSchemas = async (\n options: SchemaInitializationOptions,\n ): Promise<void> => {\n const schemaManager = new DatabaseSchemaManager();\n const currentDb: DatabaseInterface = {\n url,\n client,\n insert,\n update,\n upsert,\n get,\n getOrInsert,\n delete: deleteRecords,\n count,\n list,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n transaction,\n };\n\n await schemaManager.initializeSchemas(currentDb, options);\n };\n\n /**\n * Retrieves the schema information for a table\n *\n * @param table - Table name\n * @returns Promise resolving to table schema info or null if table doesn't exist\n * @throws Error if the query fails\n */\n const getTableSchema = async (\n table: string,\n ): Promise<TableSchemaInfo | null> => {\n validateTableName(table);\n\n try {\n // Check if table exists\n const exists = await tableExists(table);\n if (!exists) {\n return null;\n }\n\n // Get column information from information_schema\n const columnRows = await many`\n SELECT\n column_name,\n data_type,\n is_nullable,\n column_default\n FROM information_schema.columns\n WHERE table_name = ${table}\n AND table_schema = 'public'\n ORDER BY ordinal_position\n `;\n\n // Get primary key columns\n const pkRows = await many`\n SELECT kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.table_name = ${table}\n AND tc.table_schema = 'public'\n AND tc.constraint_type = 'PRIMARY KEY'\n `;\n\n const pkColumns = new Set(pkRows.map((row) => row.column_name));\n\n const columns: Record<string, ColumnDefinition> = {};\n for (const row of columnRows) {\n const colName = row.column_name as string;\n columns[colName] = {\n type: row.data_type as string,\n primaryKey: pkColumns.has(colName),\n notNull: row.is_nullable === 'NO',\n defaultValue: row.column_default,\n };\n }\n\n // Get index information from pg_indexes\n const indexRows = await many`\n SELECT\n indexname,\n indexdef\n FROM pg_indexes\n WHERE tablename = ${table}\n AND schemaname = 'public'\n AND indexname NOT LIKE '%_pkey'\n `;\n\n const indexes: IndexDefinition[] = [];\n for (const row of indexRows) {\n const indexName = row.indexname as string;\n const indexDef = row.indexdef as string;\n\n // Parse column names from index definition\n // Example: CREATE INDEX idx_name ON table (col1, col2)\n const colMatch = indexDef.match(/\\(([^)]+)\\)/);\n const indexColumns = colMatch\n ? colMatch[1].split(',').map((col) => col.trim())\n : [];\n\n const isUnique = indexDef.toUpperCase().includes('UNIQUE');\n\n indexes.push({\n name: indexName,\n columns: indexColumns,\n unique: isUnique,\n });\n }\n\n // Get foreign key information\n const fkRows = await many`\n SELECT\n kcu.column_name,\n ccu.table_name AS foreign_table_name,\n ccu.column_name AS foreign_column_name,\n rc.delete_rule,\n rc.update_rule\n FROM information_schema.table_constraints AS tc\n JOIN information_schema.key_column_usage AS kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n JOIN information_schema.constraint_column_usage AS ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n JOIN information_schema.referential_constraints AS rc\n ON rc.constraint_name = tc.constraint_name\n AND rc.constraint_schema = tc.table_schema\n WHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_name = ${table}\n AND tc.table_schema = 'public'\n `;\n\n const foreignKeys: Array<{\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete?: string;\n onUpdate?: string;\n }> = [];\n\n for (const fkRow of fkRows) {\n foreignKeys.push({\n column: fkRow.column_name as string,\n referencesTable: fkRow.foreign_table_name as string,\n referencesColumn: fkRow.foreign_column_name as string,\n onDelete: fkRow.delete_rule as string | undefined,\n onUpdate: fkRow.update_rule as string | undefined,\n });\n }\n\n return {\n tableName: table,\n columns,\n indexes,\n foreignKeys,\n };\n } catch (e) {\n throw new DatabaseError('Failed to retrieve table schema', {\n table,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * ALTER TABLE operations for schema evolution\n */\n const alterTable = {\n /**\n * Adds a new column to an existing table\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @returns Promise that resolves when column is added\n * @throws Error if the alter operation fails\n */\n addColumn: async (\n table: string,\n column: ColumnDefinitionWithName,\n ): Promise<void> => {\n validateTableName(table);\n validateColumnName(column.name);\n\n try {\n const sql = generateAddColumnStatement(table, column, 'postgres');\n await client.query(sql);\n } catch (e) {\n throw new DatabaseError('Failed to add column to table', {\n table,\n column: column.name,\n originalError: formatDbError(e),\n });\n }\n },\n\n /**\n * Adds a new index to an existing table\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns Promise that resolves when index is created\n * @throws Error if the create index operation fails\n */\n addIndex: async (table: string, index: IndexDefinition): Promise<void> => {\n validateTableName(table);\n validateIndexName(index.name);\n\n for (const col of index.columns) {\n validateColumnName(col);\n }\n\n try {\n const sql = generateCreateIndexStatement(table, index);\n await client.query(sql);\n } catch (e) {\n throw new DatabaseError('Failed to create index on table', {\n table,\n index: index.name,\n originalError: formatDbError(e),\n });\n }\n },\n };\n\n const db: DatabaseInterface = {\n url,\n client,\n insert,\n update,\n upsert,\n get,\n getOrInsert,\n delete: deleteRecords,\n count,\n list,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n initializeSchemas,\n transaction,\n beginTransaction,\n acquireSession,\n getTableSchema,\n alterTable,\n vector: createVectorCapabilities(pool),\n };\n\n // Cache the connection for reuse by subsequent calls with the same dbid/URL\n const finalCacheKey = cacheKey || url;\n connectionCache.set(finalCacheKey, db);\n\n return db;\n}\n","import { loadEnvConfig } from '@happyvertical/utils';\nimport type { PostgresOptions } from './postgres';\nimport type {\n DatabaseInterface,\n DuckDBOptions,\n JSONOptions,\n} from './shared/types';\nimport type { SqliteOptions } from './sqlite';\n\n/**\n * Union type of options for creating different database types\n */\ntype GetDatabaseOptions =\n | (PostgresOptions & { type?: 'postgres' })\n | (SqliteOptions & { type?: 'sqlite' })\n | (DuckDBOptions & { type?: 'duckdb' })\n | JSONOptions;\n\n/**\n * Checks if the provided value is a database instance rather than configuration options\n *\n * @param value - Value to check\n * @returns True if the value appears to be a DatabaseInterface instance\n */\nfunction isDatabaseInstance(value: any): value is DatabaseInterface {\n return (\n value &&\n typeof value === 'object' &&\n typeof value.client !== 'undefined' &&\n typeof value.insert === 'function' &&\n typeof value.get === 'function' &&\n typeof value.query === 'function'\n );\n}\n\n/**\n * Creates a database connection based on the provided options, or returns an existing database instance\n *\n * Loads configuration from environment variables using the HAVE_SQL_* pattern:\n * - HAVE_SQL_TYPE → type ('sqlite' | 'postgres' | 'duckdb' | 'json')\n * - HAVE_SQL_URL → url (connection string)\n * - HAVE_SQL_HOST → host (database server hostname)\n * - HAVE_SQL_PORT → port (database server port number)\n * - HAVE_SQL_DATABASE → database (database name)\n * - HAVE_SQL_USER → user (authentication username)\n * - HAVE_SQL_PASSWORD → password (authentication password)\n *\n * User-provided options always take precedence over environment variables.\n *\n * ## Lazy schemas\n *\n * The `schemas` option accepts either an eagerly-built record or a lazy\n * function (`() => Record<string, SchemaProvider>`). Adapters that manage\n * tables via migrations (Postgres, SQLite) never resolve the function, so\n * there is zero cost for callers that pass schemas uniformly regardless of\n * adapter type. Only JSON and DuckDB adapters call the function.\n *\n * ```typescript\n * // Caller doesn't need to know the adapter type:\n * await getDatabase({\n * ...config,\n * schemas: () => ObjectRegistry.getAllSchemas(),\n * });\n * ```\n *\n * @param options - Configuration options for the database connection or an existing database instance\n * @returns Promise resolving to a DatabaseInterface implementation\n * @throws Error if the database type is invalid\n */\nexport async function getDatabase(\n options: GetDatabaseOptions | DatabaseInterface = {},\n): Promise<DatabaseInterface> {\n // If a database instance is passed, return it directly\n if (isDatabaseInstance(options)) {\n return options;\n }\n\n // Load HAVE_SQL_* environment variables and merge into options\n // This ensures options object is mutated (needed for dbid propagation)\n Object.assign(\n options,\n loadEnvConfig(options as any, {\n packageName: 'sql',\n schema: {\n type: 'string',\n url: 'string',\n host: 'string',\n port: 'number',\n database: 'string',\n user: 'string',\n password: 'string',\n },\n }) as Partial<GetDatabaseOptions>,\n );\n\n // if no type but url starts with file:, set to sqlite\n if (\n !options.type &&\n (options.url?.startsWith('file:') || options.url === ':memory:')\n ) {\n options.type = 'sqlite';\n }\n\n if (options.type === 'postgres') {\n const postgres = await import('./postgres.js');\n return postgres.getDatabase(options as PostgresOptions);\n }\n if (options.type === 'sqlite') {\n const sqlite = await import('./sqlite.js');\n return sqlite.getDatabase(options as SqliteOptions);\n }\n if (options.type === 'duckdb') {\n const duckdb = await import('./duckdb.js');\n return duckdb.getDatabase(options as DuckDBOptions);\n }\n if (options.type === 'json') {\n const json = await import('./json.js');\n return json.getDatabase(options as JSONOptions);\n }\n throw new Error('Invalid database type');\n}\n\n/**\n * Validates if a table name consists only of alphanumeric characters and underscores\n *\n * @param name - Table name to validate\n * @returns Boolean indicating if the name is valid\n */\nfunction _isValidTableName(name: string): boolean {\n // Simple regex to allow only alphanumeric characters and underscores\n return /^[a-zA-Z0-9_]+$/.test(name);\n}\n\n/**\n * Synchronizes a SQL schema definition with a database\n * Creates tables if they don't exist and adds missing columns to existing tables\n *\n * @param options - Object containing database and schema\n * @param options.db - Database interface to use\n * @param options.schema - SQL schema definition\n * @throws Error if db or schema are missing or if the database doesn't support syncSchema\n */\nexport async function syncSchema(options: {\n db: DatabaseInterface;\n schema: string;\n}) {\n const { db, schema } = options;\n if (!db || !schema) {\n throw new Error('db and schema are required');\n }\n\n // Delegate to the database adapter's syncSchema implementation\n if (db.syncSchema) {\n await db.syncSchema(schema);\n } else {\n throw new Error('Database adapter does not support schema synchronization');\n }\n}\n\n/**\n * Checks if a table exists in the database\n *\n * @param db - Database interface to use\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\nexport async function tableExists(db: DatabaseInterface, tableName: string) {\n return db.tableExists(tableName);\n}\n\n/**\n * Escapes and formats a value for use in SQL queries\n *\n * @param value - Value to escape\n * @returns String representation of the value safe for SQL use\n */\nexport function escapeSqlValue(value: any): string {\n if (value === null) {\n return 'NULL';\n }\n if (value instanceof Date) {\n return `'${value.toISOString()}'`;\n }\n if (typeof value === 'number') {\n return value.toString();\n }\n if (typeof value === 'boolean') {\n return value ? '1' : '0';\n }\n // Escape single quotes and wrap in quotes\n return `'${String(value).replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Validates a column name for use in SQL queries\n *\n * @param column - Column name to validate\n * @returns The validated column name\n * @throws Error if the column name contains invalid characters\n */\nexport function validateColumnName(column: string): string {\n // Only allow alphanumeric characters, underscores, and dots (for table.column notation)\n if (!/^[a-zA-Z0-9_.]+$/.test(column)) {\n throw new Error(`Invalid column name: ${column}`);\n }\n return column;\n}\n\n// Import utilities from shared utils\nimport { buildWhere, formatDbError } from './shared/utils';\n\nexport {\n type AggregateBuildResult,\n type AggregateFunction,\n type AggregateSelectExpr,\n type AggregateSpec,\n type AggregateTimeBucketUnit,\n bucketExpr,\n buildAggregate,\n} from './aggregate.js';\nexport type { SqlAdapterType } from './shared/utils';\nexport { buildWhere, formatDbError };\n\n// Import DuckDB schema transformation utilities\nimport { convertUniqueIndexesToInlineConstraints } from './shared/duckdb-schema-utils';\n\n// Generic database integrity-check framework\nexport {\n checkExpectedTables,\n checkRelationship,\n checkUniqueColumn,\n type DoctorCheck,\n type DoctorContext,\n type DoctorIssue,\n type DoctorLevel,\n type DoctorResult,\n type RelationshipSpec,\n type RunDoctorOptions,\n runDoctor,\n type UniqueColumnSpec,\n} from './doctor';\n\n// Export adapter cache utilities (for testing)\nexport { clearConnectionCache } from './json.js';\nexport { clearPostgresConnectionCache } from './postgres.js';\n// Postgres CLI shell-outs and URL helpers\nexport {\n assertCanExportDatabase,\n assertCanImportDatabase,\n type CreateDropOptions,\n createPostgresDatabase,\n type DumpOptions,\n databaseNameFromUrl,\n dropPostgresDatabase,\n dumpPostgresDatabase,\n isLocalDatabaseUrl,\n type PostgresImportLocalityOptions,\n type PostgresLocalityOptions,\n postgresEnvFromUrl,\n type RestoreOptions,\n redactDatabaseUrl,\n restorePostgresDatabase,\n} from './postgres-cli';\nexport type { SchemaInitializationResult } from './schema-manager';\n// Export schema management\nexport { DatabaseSchemaManager } from './schema-manager';\nexport * from './shared/types';\nexport { convertUniqueIndexesToInlineConstraints };\n\nexport default {\n getDatabase,\n syncSchema,\n tableExists,\n buildWhere,\n};\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"names":["index","alias","expression","tableExists","pendingConnections","validateTableName","getDatabase","table","options","result","rows","connection","syncSchema","validateColumnName","cacheKey","keys","placeholders","_","query","values","postgres","json"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-CzdYvRFp.js","sources":["../../src/shared/utils.ts","../../src/aggregate.ts","../../src/shared/duckdb-schema-utils.ts","../../src/doctor.ts","../../src/schema-manager.ts","../../src/shared/types.ts","../../src/json.ts","../../src/shared/alter-utils.ts","../../src/postgres.ts","../../src/index.ts"],"sourcesContent":["/**\n * Shared SQL utilities that work in both browser and Node.js environments\n */\n\nimport type { WhereClause } from './types.js';\n\n/**\n * Formats a database error to include all relevant details\n *\n * Database drivers often include additional properties beyond just `message`:\n * - PostgreSQL: code, detail, hint, severity\n * - DuckDB: may include additional context\n * - SQLite/LibSQL: may include errno, code\n *\n * This function extracts all available error properties to provide\n * better debugging information.\n *\n * @param error - The caught error object\n * @returns Formatted error string with all available error details\n */\nexport function formatDbError(error: unknown): string {\n const dbError = error as {\n message?: string;\n code?: string;\n detail?: string;\n hint?: string;\n severity?: string;\n errno?: number;\n cause?: unknown;\n };\n\n const parts: string[] = [];\n\n if (dbError.message) parts.push(dbError.message);\n if (dbError.code) parts.push(`code=${dbError.code}`);\n if (dbError.detail) parts.push(`detail=${dbError.detail}`);\n if (dbError.hint) parts.push(`hint=${dbError.hint}`);\n if (dbError.severity) parts.push(`severity=${dbError.severity}`);\n if (dbError.errno !== undefined) parts.push(`errno=${dbError.errno}`);\n\n return parts.length > 0 ? parts.join(', ') : String(error);\n}\n\n/**\n * Map of valid SQL operators for use in WHERE clauses\n */\nconst VALID_OPERATORS = {\n '=': '=',\n '>': '>',\n '>=': '>=',\n '<': '<',\n '<=': '<=',\n '!=': '!=',\n like: 'LIKE',\n in: 'IN',\n 'not in': 'NOT IN',\n} as const;\n\nfunction isSimpleSqlIdentifier(field: string): boolean {\n return /^[a-zA-Z0-9_.]+$/.test(field);\n}\n\nexport function parseConditionKey(fullKey: string): {\n field: string;\n operator: string;\n explicitOperator: boolean;\n} {\n const trimmed = fullKey.trim();\n const lower = trimmed.toLowerCase();\n const operators = ['not in', 'like', 'in', '!=', '>=', '<=', '>', '<', '='];\n\n for (const operator of operators) {\n if (lower.endsWith(` ${operator}`)) {\n return {\n field: trimmed.slice(0, -(operator.length + 1)).trim(),\n operator,\n explicitOperator: true,\n };\n }\n }\n\n return { field: trimmed, operator: '=', explicitOperator: false };\n}\n\n/**\n * SQL adapter type for adapter-specific query generation\n */\nexport type SqlAdapterType = 'sqlite' | 'postgres' | 'duckdb' | 'json';\n\n/**\n * Builds a single condition for a WHERE clause\n * @internal\n */\nconst buildCondition = (\n fullKey: string,\n value: any,\n currIndex: { value: number },\n adapterType?: SqlAdapterType,\n): { sql: string; values: any[] } => {\n const { field, operator, explicitOperator } = parseConditionKey(fullKey);\n if (!explicitOperator && !isSimpleSqlIdentifier(field)) {\n throw new Error(`Invalid SQL identifier: ${field}`);\n }\n const sqlOperator =\n VALID_OPERATORS[operator as keyof typeof VALID_OPERATORS] || '=';\n const values: any[] = [];\n\n let sql: string;\n\n if (value === null) {\n sql = `${field} IS ${sqlOperator === '=' ? 'NULL' : 'NOT NULL'}`;\n } else if (\n (sqlOperator === 'IN' || sqlOperator === 'NOT IN') &&\n Array.isArray(value)\n ) {\n if (value.length === 0) {\n throw new Error(`${sqlOperator} requires at least one value`);\n }\n const placeholders = value.map(() => `$${currIndex.value++}`).join(', ');\n sql = `${field} ${sqlOperator} (${placeholders})`;\n values.push(...value);\n } else if (value instanceof Date) {\n // DuckDB/JSON need CAST to TIMESTAMP to prevent ANY type inference (issue #540)\n // SQLite/PostgreSQL handle ISO strings natively without CAST\n const needsCast = adapterType === 'duckdb' || adapterType === 'json';\n if (needsCast) {\n sql = `${field} ${sqlOperator} CAST($${currIndex.value++} AS TIMESTAMP)`;\n } else {\n sql = `${field} ${sqlOperator} $${currIndex.value++}`;\n }\n values.push(value.toISOString());\n } else {\n sql = `${field} ${sqlOperator} $${currIndex.value++}`;\n values.push(value);\n }\n\n return { sql, values };\n};\n\n/**\n * Builds a SQL WHERE clause with parameterized values and flexible operators\n *\n * @param where - Conditions as object (AND-only) or 2D array (OR/AND compound)\n * @param startIndex - Starting index for parameter numbering (default: 1)\n * @param adapterType - Database adapter type. Controls Date handling:\n * - `'duckdb'` / `'json'`: Wraps Date values in `CAST($N AS TIMESTAMP)` to\n * prevent DuckDB ANY-type inference issues.\n * - `'sqlite'` / `'postgres'` / `undefined`: Passes ISO strings directly\n * (these adapters handle ISO timestamp strings natively).\n *\n * Keys with explicit operator suffixes are treated as SQL field/expression\n * text. Keep those keys developer-controlled; do not pass end-user input as a\n * condition key.\n *\n * @returns Object containing the SQL clause and array of values\n *\n * @example Basic Usage (Object format - AND-only):\n * ```typescript\n * buildWhere({\n * 'status': 'active', // equals operator is default\n * 'price >': 100, // greater than\n * 'stock <=': 5, // less than or equal\n * 'category in': ['A', 'B'], // IN clause for arrays\n * 'name like': '%shirt%' // LIKE for pattern matching\n * });\n * ```\n *\n * @example 2D Array Format (OR/AND compound logic):\n * ```typescript\n * // WHERE (status = 'active' AND price > 100) OR (status = 'pending' AND priority = 'high')\n * buildWhere([\n * [{ status: 'active' }, { 'price >': 100 }],\n * [{ status: 'pending' }, { priority: 'high' }]\n * ]);\n * ```\n *\n * @example NULL Handling:\n * ```typescript\n * buildWhere({\n * 'deleted_at': null, // becomes \"deleted_at IS NULL\"\n * 'updated_at !=': null, // becomes \"updated_at IS NOT NULL\"\n * 'status': 'active' // regular comparison\n * });\n * ```\n *\n * @example Common Patterns:\n * ```typescript\n * // Price range\n * buildWhere({\n * 'price >=': 10,\n * 'price <': 100\n * });\n *\n * // Date filtering\n * buildWhere({\n * 'created_at >': startDate,\n * 'created_at <=': endDate,\n * 'deleted_at': null\n * });\n *\n * // Search with LIKE\n * buildWhere({\n * 'title like': '%search%',\n * 'description like': '%search%',\n * 'status': 'published'\n * });\n *\n * // Multiple values with IN\n * buildWhere({\n * 'role in': ['admin', 'editor'],\n * 'active': true,\n * 'last_login !=': null\n * });\n * ```\n *\n * The function handles:\n * - Standard comparisons (=, >, >=, <, <=, !=)\n * - NULL checks (IS NULL, IS NOT NULL)\n * - IN clauses for arrays\n * - LIKE for pattern matching\n * - Object format: Multiple conditions combined with AND\n * - 2D array format: Inner arrays ANDed, outer array ORed\n */\nexport const buildWhere = (\n where: WhereClause,\n startIndex = 1,\n adapterType?: SqlAdapterType,\n) => {\n let sql = '';\n const values: any[] = [];\n const currIndex = { value: startIndex };\n\n // Handle 2D array format for OR/AND compound logic\n if (Array.isArray(where)) {\n if (where.length === 0) {\n return { sql: '', values: [] };\n }\n\n const orGroups: string[] = [];\n\n for (const andGroup of where) {\n if (!Array.isArray(andGroup) || andGroup.length === 0) {\n continue;\n }\n\n const andConditions: string[] = [];\n\n for (const conditionObj of andGroup) {\n for (const [fullKey, value] of Object.entries(conditionObj)) {\n const result = buildCondition(fullKey, value, currIndex, adapterType);\n andConditions.push(result.sql);\n values.push(...result.values);\n }\n }\n\n if (andConditions.length > 0) {\n // Wrap AND group in parentheses\n orGroups.push(`(${andConditions.join(' AND ')})`);\n }\n }\n\n if (orGroups.length > 0) {\n sql = `WHERE ${orGroups.join(' OR ')}`;\n }\n\n return { sql, values };\n }\n\n // Handle object format (original behavior - AND-only)\n if (where && Object.keys(where).length > 0) {\n sql = 'WHERE ';\n for (const [fullKey, value] of Object.entries(where)) {\n const result = buildCondition(fullKey, value, currIndex, adapterType);\n\n if (sql !== 'WHERE ') {\n sql += ' AND ';\n }\n\n sql += result.sql;\n values.push(...result.values);\n }\n }\n\n return { sql, values };\n};\n","import type { WhereClause } from './shared/types.js';\nimport {\n buildWhere,\n parseConditionKey,\n type SqlAdapterType,\n} from './shared/utils.js';\n\nexport type AggregateTimeBucketUnit =\n | 'minute'\n | 'hour'\n | 'day'\n | 'week'\n | 'month'\n | 'quarter'\n | 'year';\n\nexport type AggregateFunction =\n | 'count'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | (string & {});\n\nexport type AggregateSelectExpr =\n | { column: string; as?: string }\n | {\n fn: AggregateFunction;\n column?: string;\n as: string;\n distinct?: boolean;\n }\n | {\n bucket: AggregateTimeBucketUnit;\n column: string;\n as: string;\n };\n\nexport interface AggregateSpec {\n from: string;\n select: AggregateSelectExpr[];\n where?: WhereClause;\n groupBy?: string[];\n having?: WhereClause;\n orderBy?: string | string[];\n limit?: number;\n offset?: number;\n}\n\nexport interface AggregateBuildResult {\n sql: string;\n values: any[];\n}\n\nconst VALID_DIRECTIONS = new Set(['ASC', 'DESC']);\nconst VALID_BUCKET_UNITS = new Set<AggregateTimeBucketUnit>([\n 'minute',\n 'hour',\n 'day',\n 'week',\n 'month',\n 'quarter',\n 'year',\n]);\n\nfunction validateSqlIdentifier(identifier: string): string {\n if (!/^[a-zA-Z0-9_.]+$/.test(identifier)) {\n throw new Error(`Invalid SQL identifier: ${identifier}`);\n }\n return identifier;\n}\n\nfunction normalizeAdapter(adapterType?: SqlAdapterType): SqlAdapterType {\n return adapterType ?? 'sqlite';\n}\n\nfunction placeholder(index: number): string {\n return `$${index}`;\n}\n\nexport function bucketExpr(\n adapterType: SqlAdapterType | undefined,\n unit: AggregateTimeBucketUnit,\n column: string,\n): string {\n if (!VALID_BUCKET_UNITS.has(unit)) {\n throw new Error(`Invalid aggregate bucket unit: ${unit}`);\n }\n\n const col = validateSqlIdentifier(column);\n const adapter = normalizeAdapter(adapterType);\n\n if (adapter === 'postgres' || adapter === 'duckdb' || adapter === 'json') {\n return `date_trunc('${unit}', ${col})`;\n }\n\n switch (unit) {\n case 'minute':\n return `strftime('%Y-%m-%d %H:%M:00', ${col})`;\n case 'hour':\n return `strftime('%Y-%m-%d %H:00:00', ${col})`;\n case 'day':\n return `strftime('%Y-%m-%d 00:00:00', ${col})`;\n case 'week':\n return `strftime('%Y-%m-%d 00:00:00', date(${col}, printf('-%d days', (CAST(strftime('%w', ${col}) AS INTEGER) + 6) % 7)))`;\n case 'month':\n return `strftime('%Y-%m-01 00:00:00', ${col})`;\n case 'quarter':\n return `strftime('%Y-%m-%d 00:00:00', date(strftime('%Y-', ${col}) || printf('%02d', ((CAST(strftime('%m', ${col}) AS INTEGER) - 1) / 3) * 3 + 1) || '-01'))`;\n case 'year':\n return `strftime('%Y-01-01 00:00:00', ${col})`;\n }\n}\n\nfunction aggregateExpression(\n expr: Extract<AggregateSelectExpr, { fn: AggregateFunction }>,\n): string {\n const normalizedFn = String(expr.fn).toLowerCase();\n const fn = validateSqlIdentifier(String(expr.fn)).toUpperCase();\n if (normalizedFn === 'count' && !expr.column) {\n if (expr.distinct) {\n throw new Error(`Aggregate ${expr.fn} with distinct requires a column`);\n }\n return 'COUNT(*)';\n }\n if (!expr.column) {\n throw new Error(`Aggregate ${expr.fn} requires a column`);\n }\n const col = validateSqlIdentifier(expr.column);\n const distinct = expr.distinct ? 'DISTINCT ' : '';\n return `${fn}(${distinct}${col})`;\n}\n\nfunction selectExpression(\n expr: AggregateSelectExpr,\n adapterType: SqlAdapterType | undefined,\n): { expression: string; alias: string; groupingCandidate: boolean } {\n if ('column' in expr && !('fn' in expr) && !('bucket' in expr)) {\n const column = validateSqlIdentifier(expr.column);\n const alias = validateSqlIdentifier(expr.as ?? expr.column);\n return { expression: column, alias, groupingCandidate: true };\n }\n if ('bucket' in expr) {\n const expression = bucketExpr(adapterType, expr.bucket, expr.column);\n const alias = validateSqlIdentifier(expr.as);\n return { expression, alias, groupingCandidate: true };\n }\n\n const expression = aggregateExpression(expr);\n const alias = validateSqlIdentifier(expr.as);\n return { expression, alias, groupingCandidate: false };\n}\n\nfunction validateWhereShape(where: AggregateSpec['where']): void {\n if (!where) return;\n const validateKey = (key: string) => {\n const { field } = parseConditionKey(key);\n if (field) validateSqlIdentifier(field);\n };\n if (Array.isArray(where)) {\n for (const andGroup of where) {\n for (const condition of andGroup) {\n for (const key of Object.keys(condition)) validateKey(key);\n }\n }\n return;\n }\n for (const key of Object.keys(where)) validateKey(key);\n}\n\nfunction expandHavingKey(\n key: string,\n expressionByAlias: Map<string, string>,\n): string {\n const parsed = parseConditionKey(key);\n const expression =\n expressionByAlias.get(parsed.field) ?? validateSqlIdentifier(parsed.field);\n\n return `${expression} ${parsed.operator}`;\n}\n\nfunction expandHaving(\n having: WhereClause,\n expressionByAlias: Map<string, string>,\n): WhereClause {\n const expandCondition = (condition: Record<string, any>) =>\n Object.fromEntries(\n Object.entries(condition).map(([key, value]) => [\n expandHavingKey(key, expressionByAlias),\n value,\n ]),\n );\n if (Array.isArray(having)) {\n return having.map((andGroup: Record<string, any>[]) =>\n andGroup.map((condition: Record<string, any>) =>\n expandCondition(condition),\n ),\n );\n }\n\n return expandCondition(having);\n}\n\nfunction buildHaving(\n having: AggregateSpec['having'],\n expressionByAlias: Map<string, string>,\n startIndex: number,\n adapterType: SqlAdapterType | undefined,\n): AggregateBuildResult {\n if (!having) return { sql: '', values: [] };\n const expanded = expandHaving(having, expressionByAlias);\n const built = buildWhere(expanded, startIndex, adapterType);\n\n return {\n sql: built.sql ? built.sql.replace(/^WHERE/, 'HAVING') : '',\n values: built.values,\n };\n}\n\nfunction buildOrderBy(orderBy: string | string[] | undefined): string {\n if (!orderBy) return '';\n const items = Array.isArray(orderBy) ? orderBy : [orderBy];\n const parts = items.map((item) => {\n const [field, direction = 'ASC'] = item.trim().split(/\\s+/);\n const normalizedDirection = direction.toUpperCase();\n if (!VALID_DIRECTIONS.has(normalizedDirection)) {\n throw new Error(`Invalid aggregate order direction: ${direction}`);\n }\n const orderExpr = validateSqlIdentifier(field);\n return `${orderExpr} ${normalizedDirection}`;\n });\n return `ORDER BY ${parts.join(', ')}`;\n}\n\nexport function buildAggregate(\n spec: AggregateSpec,\n startIndex = 1,\n adapterType?: SqlAdapterType,\n): AggregateBuildResult {\n const from = validateSqlIdentifier(spec.from);\n if (spec.select.length === 0) {\n throw new Error(\n 'AggregateSpec.select must contain at least one expression',\n );\n }\n\n validateWhereShape(spec.where);\n\n const expressionByAlias = new Map<string, string>();\n const groupingAliases: string[] = [];\n const selectSql = spec.select.map((expr) => {\n const selected = selectExpression(expr, adapterType);\n expressionByAlias.set(selected.alias, selected.expression);\n if (selected.groupingCandidate) {\n groupingAliases.push(selected.alias);\n }\n return `${selected.expression} AS ${selected.alias}`;\n });\n\n const where = spec.where\n ? buildWhere(spec.where, startIndex, adapterType)\n : { sql: '', values: [] };\n let nextParamIndex = startIndex + where.values.length;\n\n const groupByItems = spec.groupBy ?? groupingAliases;\n const groupBySql =\n groupByItems.length > 0\n ? `GROUP BY ${groupByItems\n .map((item) =>\n expressionByAlias.has(item)\n ? expressionByAlias.get(item)\n : validateSqlIdentifier(item),\n )\n .join(', ')}`\n : '';\n\n const having = buildHaving(\n spec.having,\n expressionByAlias,\n nextParamIndex,\n adapterType,\n );\n nextParamIndex += having.values.length;\n\n const orderBySql = buildOrderBy(spec.orderBy);\n\n const pagingValues: any[] = [];\n const pagingSql: string[] = [];\n if (spec.limit !== undefined) {\n pagingSql.push(`LIMIT ${placeholder(nextParamIndex++)}`);\n pagingValues.push(spec.limit);\n } else if (\n spec.offset !== undefined &&\n normalizeAdapter(adapterType) === 'sqlite'\n ) {\n pagingSql.push('LIMIT -1');\n }\n if (spec.offset !== undefined) {\n pagingSql.push(`OFFSET ${placeholder(nextParamIndex++)}`);\n pagingValues.push(spec.offset);\n }\n\n const sql = [\n `SELECT ${selectSql.join(', ')}`,\n `FROM ${from}`,\n where.sql,\n groupBySql,\n having.sql,\n orderBySql,\n pagingSql.join(' '),\n ]\n .filter(Boolean)\n .join(' ');\n\n return {\n sql,\n values: [...where.values, ...having.values, ...pagingValues],\n };\n}\n","/**\n * DuckDB-specific schema transformation utilities\n *\n * DuckDB has a known limitation (issue #12684) where ON CONFLICT clauses\n * fail with UNIQUE INDEX but work with inline UNIQUE constraints.\n *\n * This module provides utilities to transform SMRT-generated schemas\n * (which use separate CREATE UNIQUE INDEX statements) into DuckDB-compatible\n * schemas (which use inline UNIQUE constraints).\n */\n\n/**\n * Index definition extracted from CREATE INDEX statement\n */\ninterface ParsedIndex {\n name: string;\n columns: string[];\n unique: boolean;\n sql: string;\n}\n\n/**\n * Parses a CREATE INDEX statement to extract index details\n *\n * @param indexSQL - CREATE INDEX statement\n * @returns Parsed index definition or null if parsing fails\n *\n * @example\n * ```typescript\n * const index = parseIndexStatement(\n * 'CREATE UNIQUE INDEX ds_slug_context_idx ON ds (slug, context)'\n * );\n * // Returns: {\n * // name: 'ds_slug_context_idx',\n * // columns: ['slug', 'context'],\n * // unique: true,\n * // sql: '...'\n * // }\n * ```\n */\nexport function parseIndexStatement(indexSQL: string): ParsedIndex | null {\n const trimmed = indexSQL.trim();\n\n // Match: CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON table (columns)\n // Support both quoted and unquoted identifiers: table, \"table\", columns, \"columns\"\n const match = trimmed.match(\n /CREATE\\s+(UNIQUE\\s+)?INDEX\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(\\w+)\\s+ON\\s+(?:\"?\\w+\"?)\\s*\\(([^)]+)\\)/i,\n );\n\n if (!match) {\n return null;\n }\n\n const [, uniqueKeyword, name, columnsStr] = match;\n\n // Remove quotes from column names\n const columns = columnsStr\n .split(',')\n .map((col) => col.trim().replace(/^\"|\"$/g, ''));\n\n return {\n name,\n columns,\n unique: Boolean(uniqueKeyword),\n sql: trimmed,\n };\n}\n\n/**\n * Converts UNIQUE INDEX statements to inline UNIQUE constraints for DuckDB compatibility\n *\n * DuckDB's ON CONFLICT clause requires inline UNIQUE constraints, not separate indexes.\n * This function transforms SMRT-generated schemas to work with DuckDB's limitations.\n *\n * @param ddl - CREATE TABLE DDL statement\n * @param indexes - Array of CREATE INDEX statements (optional)\n * @returns Transformed DDL with inline UNIQUE constraints and filtered index list\n *\n * @example\n * ```typescript\n * const ddl = `\n * CREATE TABLE ds (\n * id TEXT PRIMARY KEY,\n * slug TEXT NOT NULL,\n * context TEXT NOT NULL\n * )\n * `;\n * const indexes = [\n * 'CREATE UNIQUE INDEX ds_slug_context_idx ON ds (slug, context)'\n * ];\n *\n * const result = convertUniqueIndexesToInlineConstraints(ddl, indexes);\n * // result.ddl:\n * // CREATE TABLE ds (\n * // id TEXT PRIMARY KEY,\n * // slug TEXT NOT NULL,\n * // context TEXT NOT NULL,\n * // UNIQUE(slug, context)\n * // )\n * // result.indexes: [] (UNIQUE index removed, non-UNIQUE indexes preserved)\n * ```\n */\nexport function convertUniqueIndexesToInlineConstraints(\n ddl: string,\n indexes?: string[],\n): {\n ddl: string;\n indexes: string[];\n} {\n if (!indexes || indexes.length === 0) {\n return { ddl, indexes: [] };\n }\n\n // Parse all indexes\n const parsedIndexes = indexes\n .map(parseIndexStatement)\n .filter((idx): idx is ParsedIndex => idx !== null);\n\n // Separate UNIQUE indexes from regular indexes\n const uniqueIndexes = parsedIndexes.filter((idx) => idx.unique);\n const regularIndexes = parsedIndexes.filter((idx) => !idx.unique);\n\n // If no UNIQUE indexes, return unchanged\n if (uniqueIndexes.length === 0) {\n return { ddl, indexes };\n }\n\n // Find the closing parenthesis of the CREATE TABLE statement\n const lines = ddl.split('\\n');\n let closingParenIndex = -1;\n\n for (let i = lines.length - 1; i >= 0; i--) {\n const trimmed = lines[i].trim();\n if (trimmed === ')' || trimmed.startsWith(');')) {\n closingParenIndex = i;\n break;\n }\n }\n\n if (closingParenIndex === -1) {\n // Can't find closing paren - return unchanged\n console.warn(\n '[duckdb-schema-utils] Could not find closing parenthesis in CREATE TABLE statement',\n );\n return { ddl, indexes };\n }\n\n // Build inline UNIQUE constraints with quoted column names\n const uniqueConstraints = uniqueIndexes.map((idx) => {\n const columns = idx.columns.map((col) => `\"${col}\"`).join(', ');\n return ` UNIQUE(${columns})`;\n });\n\n // Insert UNIQUE constraints before closing parenthesis\n const modifiedLines = [...lines];\n const closingLine = modifiedLines[closingParenIndex].trim();\n\n // Add comma to previous line if it doesn't have one\n if (closingParenIndex > 0) {\n const prevLine = modifiedLines[closingParenIndex - 1].trim();\n if (!prevLine.endsWith(',')) {\n modifiedLines[closingParenIndex - 1] = modifiedLines[\n closingParenIndex - 1\n ].replace(/\\s*$/, ',');\n }\n }\n\n // Insert UNIQUE constraints\n const constraintLines = uniqueConstraints.map((constraint, idx) => {\n // Add comma after all but the last constraint\n return idx < uniqueConstraints.length - 1 ? `${constraint},` : constraint;\n });\n\n modifiedLines.splice(closingParenIndex, 0, ...constraintLines);\n\n const transformedDDL = modifiedLines.join('\\n');\n\n // Return regular (non-UNIQUE) indexes only\n const remainingIndexes = regularIndexes.map((idx) => idx.sql);\n\n return {\n ddl: transformedDDL,\n indexes: remainingIndexes,\n };\n}\n\n/**\n * Checks if a schema definition contains UNIQUE indexes that need conversion\n *\n * @param indexes - Array of CREATE INDEX statements\n * @returns True if any UNIQUE indexes are present\n */\nexport function hasUniqueIndexes(indexes?: string[]): boolean {\n if (!indexes || indexes.length === 0) {\n return false;\n }\n\n return indexes.some((indexSQL) => {\n const parsed = parseIndexStatement(indexSQL);\n return parsed?.unique === true;\n });\n}\n","/**\n * Database integrity-check framework.\n *\n * The runner is a thin loop over user-supplied checks; the value here is\n * the reusable check builders (expected tables, unique columns, FK-like\n * relationships) that codify the common shapes of integrity bugs that\n * sneak past schema migrations.\n *\n * No SMRT awareness — checks operate on the `DatabaseInterface` from this\n * package and on plain table/column names.\n *\n * **Postgres-only today.** The bundled check builders and\n * `listPublicTables` use Postgres syntax (`pg_tables`, `::int`/`::text`\n * casts). The shape is portable in principle — `DoctorContext` carries a\n * generic `DatabaseInterface` so apps can add engine-aware checks — but\n * the out-of-the-box runner expects a Postgres connection. `runDoctor`\n * throws early if pointed at a non-Postgres URL rather than failing\n * mid-execution with a confusing `pg_tables`-doesn't-exist error.\n */\nimport { redactDatabaseUrl } from './postgres-cli';\nimport type { DatabaseInterface } from './shared/types';\n\nexport type DoctorLevel = 'fail' | 'warn';\n\nexport interface DoctorIssue {\n level: DoctorLevel;\n message: string;\n}\n\nexport interface DoctorContext {\n db: DatabaseInterface;\n tables: Set<string>;\n}\n\nexport type DoctorCheck = (ctx: DoctorContext) => Promise<DoctorIssue[]>;\n\nexport interface RunDoctorOptions {\n db: DatabaseInterface;\n checks: DoctorCheck[];\n}\n\nexport interface DoctorResult {\n failures: DoctorIssue[];\n warnings: DoctorIssue[];\n issues: DoctorIssue[];\n}\n\n/**\n * Execute every check against the public-schema tables of `db` and\n * partition the results by severity. Returns the aggregate; callers\n * format/exit as they see fit.\n *\n * The current table set is enumerated once and shared across checks so\n * each check can cheaply decide whether its target tables exist.\n */\nexport async function runDoctor(\n options: RunDoctorOptions,\n): Promise<DoctorResult> {\n assertPostgresAdapter(options.db);\n const tables = await listPublicTables(options.db);\n const issues: DoctorIssue[] = [];\n\n for (const check of options.checks) {\n const checkIssues = await check({ db: options.db, tables });\n issues.push(...checkIssues);\n }\n\n return {\n failures: issues.filter((issue) => issue.level === 'fail'),\n warnings: issues.filter((issue) => issue.level === 'warn'),\n issues,\n };\n}\n\n/**\n * Throw early if the supplied database isn't Postgres. The check builders\n * and `listPublicTables` use Postgres syntax; pointing them at SQLite or\n * DuckDB would fail mid-execution with a confusing \"table pg_tables does\n * not exist\" error from the adapter. Fail fast with a useful message\n * instead.\n */\nfunction assertPostgresAdapter(db: DatabaseInterface): void {\n const url = String(db.url ?? '');\n if (!url.startsWith('postgres://') && !url.startsWith('postgresql://')) {\n throw new Error(\n `runDoctor requires a Postgres database connection. Got URL: ${url ? redactDatabaseUrl(url) : '(empty)'}. ` +\n 'The bundled check builders use Postgres-specific syntax (pg_tables, ::int/::text casts).',\n );\n }\n}\n\n/**\n * Emit a 'warn' for each table in `expected` that's missing.\n *\n * Marked as `warn` rather than `fail` because a missing table often\n * indicates a migration that hasn't been run yet, not active data\n * corruption — callers can promote to fail by mapping the issues.\n */\nexport function checkExpectedTables(expected: readonly string[]): DoctorCheck {\n return async ({ tables }) => {\n const issues: DoctorIssue[] = [];\n for (const table of expected) {\n if (!tables.has(table)) {\n issues.push({\n level: 'warn',\n message: `Missing expected table: ${table}`,\n });\n }\n }\n return issues;\n };\n}\n\nexport interface UniqueColumnSpec {\n table: string;\n column: string;\n /** Human-readable label used in the issue message. */\n label: string;\n}\n\n/**\n * Emit a 'fail' for each value that appears more than once in\n * `(table, column)` (ignoring NULL and empty-string values).\n *\n * Useful for catching slug/key collisions that the schema didn't\n * declare a UNIQUE constraint for (or where the constraint was added\n * after data already existed).\n */\nexport function checkUniqueColumn(spec: UniqueColumnSpec): DoctorCheck {\n return async ({ db, tables }) => {\n if (!tables.has(spec.table)) return [];\n const result = await db.query(`\n SELECT ${quoteIdentifier(spec.column)} AS value, count(*)::text AS count\n FROM ${quoteIdentifier(spec.table)}\n WHERE NULLIF(trim(${quoteIdentifier(spec.column)}::text), '') IS NOT NULL\n GROUP BY ${quoteIdentifier(spec.column)}\n HAVING count(*) > 1\n ORDER BY count DESC, ${quoteIdentifier(spec.column)}\n `);\n return result.rows.map((row) => ({\n level: 'fail' as const,\n message: `Duplicate ${spec.label} \"${String(row.value)}\" in ${spec.table} (${countValueFromRow(\n row.count,\n )} rows).`,\n }));\n };\n}\n\nexport interface RelationshipSpec {\n childTable: string;\n childColumn: string;\n parentTable: string;\n /** Defaults to 'id'. */\n parentColumn?: string;\n /** Human-readable label used in the issue message. */\n label: string;\n}\n\n/**\n * Emit a 'fail' counting orphan rows where the child column points at a\n * parent row that doesn't exist (FK-shaped check, but doesn't require an\n * actual FK constraint to be declared — useful for soft references like\n * tag-id-or-slug lookup columns).\n */\nexport function checkRelationship(spec: RelationshipSpec): DoctorCheck {\n return async ({ db, tables }) => {\n if (!tables.has(spec.childTable) || !tables.has(spec.parentTable))\n return [];\n const parentColumn = spec.parentColumn ?? 'id';\n const result = await db.query(`\n SELECT count(*)::text AS count\n FROM ${quoteIdentifier(spec.childTable)} child\n LEFT JOIN ${quoteIdentifier(spec.parentTable)} parent\n ON parent.${quoteIdentifier(parentColumn)} = child.${quoteIdentifier(spec.childColumn)}\n WHERE NULLIF(trim(child.${quoteIdentifier(spec.childColumn)}::text), '') IS NOT NULL\n AND parent.${quoteIdentifier(parentColumn)} IS NULL\n `);\n const orphanCount = countValueFromRow(result.rows[0]?.count);\n if (orphanCount === '0') return [];\n return [\n {\n level: 'fail',\n message: `${spec.label}: ${orphanCount} orphaned row${orphanCount === '1' ? '' : 's'}.`,\n },\n ];\n };\n}\n\nasync function listPublicTables(db: DatabaseInterface): Promise<Set<string>> {\n const result = await db.query(\n \"SELECT tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename\",\n );\n return new Set(result.rows.map((row) => String(row.tablename ?? '')));\n}\n\nfunction quoteIdentifier(value: string): string {\n return `\"${value.replace(/\"/gu, '\"\"')}\"`;\n}\n\nfunction countValueFromRow(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'bigint') {\n return String(value);\n }\n return '0';\n}\n","/**\n * Schema management and dependency resolution for JSON manifests\n * Moved from SMRT package to SQL package for proper separation of concerns\n */\n\nimport type {\n DatabaseInterface,\n IndexDefinition,\n SchemaDefinition,\n SchemaInitializationOptions,\n TriggerDefinition,\n} from './shared/types.js';\n\n/**\n * Result returned by DatabaseSchemaManager.initializeSchemas()\n *\n * Contains the list of schemas that were successfully initialized,\n * any that were skipped (already up to date), errors encountered,\n * and the total execution time in milliseconds.\n */\nexport interface SchemaInitializationResult {\n initialized: string[];\n skipped: string[];\n errors: Array<{ schema: string; error: string }>;\n executionTime: number;\n}\n\n/**\n * Manages schema initialization from JSON manifests with dependency resolution\n *\n * Handles topological sorting of schema dependencies, table creation,\n * index and trigger setup, and version tracking to avoid redundant re-initialization.\n */\nexport class DatabaseSchemaManager {\n private static initializationLock = new Map<string, Promise<void>>();\n private initializedSchemas = new Set<string>();\n private schemaVersions = new Map<string, string>();\n\n /**\n * Initializes database schemas from a JSON manifest with dependency resolution\n *\n * Schemas are topologically sorted by their declared dependencies and\n * initialized in order. Supports legacy raw-SQL schemas via the `schema` option,\n * JSON manifests via the `manifest` option, and schema overrides for extending\n * base schemas.\n *\n * @param db - Database interface to execute DDL against\n * @param options - Schema initialization options (manifest, overrides, force, debug)\n * @returns Result with lists of initialized/skipped schemas, errors, and execution time\n */\n async initializeSchemas(\n db: DatabaseInterface,\n options: SchemaInitializationOptions,\n ): Promise<SchemaInitializationResult> {\n const startTime = Date.now();\n const result: SchemaInitializationResult = {\n initialized: [],\n skipped: [],\n errors: [],\n executionTime: 0,\n };\n\n try {\n let schemas: Record<string, SchemaDefinition> = {};\n\n // Handle legacy SQL schema format\n if (options.schema) {\n console.log(\n '[schema] Legacy SQL schema provided, converting to manifest format',\n );\n // For legacy support, we'll still use the original syncSchema method\n if (db.syncSchema) {\n await db.syncSchema(options.schema);\n result.initialized.push('legacy-sql');\n }\n result.executionTime = Date.now() - startTime;\n return result;\n }\n\n // Handle JSON manifest format\n if (options.manifest) {\n schemas = { ...options.manifest.schemas };\n }\n\n // Apply schema overrides\n if (options.overrides) {\n schemas = { ...schemas, ...options.overrides };\n }\n\n if (Object.keys(schemas).length === 0) {\n console.warn('[schema] No schemas provided for initialization');\n result.executionTime = Date.now() - startTime;\n return result;\n }\n\n // Build dependency graph\n const dependencyGraph = this.buildDependencyGraph(schemas);\n\n // Get initialization order\n const initializationOrder = this.resolveDependencies(dependencyGraph);\n\n if (options.debug) {\n console.log('[schema] Initialization order:', initializationOrder);\n }\n\n // Initialize schemas in dependency order\n for (const schemaName of initializationOrder) {\n const schema = schemas[schemaName];\n if (!schema) continue;\n\n try {\n await this.initializeSchema(db, schemaName, schema, {\n force: options.force,\n debug: options.debug,\n });\n result.initialized.push(schemaName);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n result.errors.push({ schema: schemaName, error: errorMessage });\n\n if (options.debug) {\n console.error(\n `[schema] Failed to initialize ${schemaName}:`,\n error,\n );\n }\n }\n }\n\n result.executionTime = Date.now() - startTime;\n\n if (options.debug) {\n console.log('[schema] Initialization complete:', result);\n }\n\n return result;\n } catch (error) {\n result.executionTime = Date.now() - startTime;\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n result.errors.push({\n schema: 'dependency-resolution',\n error: errorMessage,\n });\n return result;\n }\n }\n\n /**\n * Initialize a single schema\n */\n private async initializeSchema(\n db: DatabaseInterface,\n schemaName: string,\n schema: SchemaDefinition,\n options: { force?: boolean; debug?: boolean },\n ): Promise<void> {\n const { tableName, version } = schema;\n const lockKey = `${schemaName}:${tableName}`;\n\n // Check if already being initialized\n if (DatabaseSchemaManager.initializationLock.has(lockKey)) {\n await DatabaseSchemaManager.initializationLock.get(lockKey);\n return;\n }\n\n // Check if already initialized and up to date\n if (!options.force && this.isSchemaUpToDate(schemaName, version)) {\n if (options.debug) {\n console.log(`[schema] Skipping ${schemaName} - already up to date`);\n }\n return;\n }\n\n // Create initialization promise\n const initPromise = this.performSchemaInitialization(\n db,\n schemaName,\n schema,\n options,\n );\n DatabaseSchemaManager.initializationLock.set(lockKey, initPromise);\n\n try {\n await initPromise;\n this.markSchemaInitialized(schemaName, version);\n } finally {\n DatabaseSchemaManager.initializationLock.delete(lockKey);\n }\n }\n\n /**\n * Perform the actual schema initialization\n */\n private async performSchemaInitialization(\n db: DatabaseInterface,\n schemaName: string,\n schema: SchemaDefinition,\n options: { force?: boolean; debug?: boolean },\n ): Promise<void> {\n const { tableName, columns, indexes, triggers } = schema;\n\n if (options.debug) {\n console.log(`[schema] Initializing ${schemaName} (${tableName})`);\n }\n\n // Check if table exists\n const tableExists = await db.tableExists(tableName);\n\n if (!tableExists) {\n // Create table\n await this.createTable(db, schema);\n\n // Create indexes\n for (const index of indexes) {\n await this.createIndex(db, tableName, index);\n }\n\n // Create triggers\n for (const trigger of triggers) {\n await this.createTrigger(db, trigger);\n }\n } else if (options.force) {\n // Recreate table if forced\n await db.query(`DROP TABLE IF EXISTS ${tableName}`);\n await this.createTable(db, schema);\n\n for (const index of indexes) {\n await this.createIndex(db, tableName, index);\n }\n\n for (const trigger of triggers) {\n await this.createTrigger(db, trigger);\n }\n } else {\n // Table exists, check for schema changes\n await this.updateSchemaIfNeeded(db, schema);\n }\n }\n\n /**\n * Create table from schema definition\n */\n private async createTable(\n db: DatabaseInterface,\n schema: SchemaDefinition,\n ): Promise<void> {\n const { tableName, columns, foreignKeys } = schema;\n\n const columnDefinitions: string[] = [];\n\n // Add column definitions\n for (const [columnName, columnDef] of Object.entries(columns)) {\n let def = `${columnName} ${columnDef.type}`;\n\n if (columnDef.primaryKey) def += ' PRIMARY KEY';\n if (columnDef.unique && !columnDef.primaryKey) def += ' UNIQUE';\n if (columnDef.notNull) def += ' NOT NULL';\n if (columnDef.defaultValue !== undefined) {\n def += ` DEFAULT ${columnDef.defaultValue}`;\n }\n if (columnDef.check) def += ` CHECK (${columnDef.check})`;\n\n columnDefinitions.push(def);\n }\n\n // Add foreign key constraints\n for (const fk of foreignKeys) {\n let fkDef = `FOREIGN KEY (${fk.column}) REFERENCES ${fk.referencesTable}(${fk.referencesColumn})`;\n if (fk.onDelete) fkDef += ` ON DELETE ${fk.onDelete}`;\n if (fk.onUpdate) fkDef += ` ON UPDATE ${fk.onUpdate}`;\n columnDefinitions.push(fkDef);\n }\n\n const createTableSQL = `CREATE TABLE ${tableName} (\\n ${columnDefinitions.join(',\\n ')}\\n)`;\n await db.query(createTableSQL);\n }\n\n /**\n * Create index from definition\n */\n private async createIndex(\n db: DatabaseInterface,\n tableName: string,\n index: IndexDefinition,\n ): Promise<void> {\n const uniqueClause = index.unique ? 'UNIQUE ' : '';\n const whereClause = index.where ? ` WHERE ${index.where}` : '';\n const createIndexSQL = `CREATE ${uniqueClause}INDEX ${index.name} ON ${tableName} (${index.columns.join(', ')})${whereClause}`;\n\n await db.query(createIndexSQL);\n }\n\n /**\n * Create trigger from definition\n */\n private async createTrigger(\n db: DatabaseInterface,\n trigger: TriggerDefinition,\n ): Promise<void> {\n const conditionClause = trigger.condition\n ? ` WHEN ${trigger.condition}`\n : '';\n const createTriggerSQL = `CREATE TRIGGER ${trigger.name} ${trigger.when} ${trigger.event} ON ${trigger.table}${conditionClause} BEGIN ${trigger.body} END`;\n\n await db.query(createTriggerSQL);\n }\n\n /**\n * Update schema if changes are detected\n */\n private async updateSchemaIfNeeded(\n _db: DatabaseInterface,\n schema: SchemaDefinition,\n ): Promise<void> {\n // For now, just log that update is needed\n // In future, implement ALTER TABLE logic\n console.log(\n `[schema] Schema update logic not yet implemented for ${schema.tableName}`,\n );\n }\n\n /**\n * Build dependency graph from schemas\n */\n private buildDependencyGraph(\n schemas: Record<string, SchemaDefinition>,\n ): Map<string, string[]> {\n const graph = new Map<string, string[]>();\n\n for (const [schemaName, schema] of Object.entries(schemas)) {\n const dependencies = schema.dependencies.filter((dep) =>\n Object.values(schemas).some((s) => s.tableName === dep),\n );\n graph.set(\n schemaName,\n dependencies.map(\n (dep) =>\n Object.entries(schemas).find(\n ([_, s]) => s.tableName === dep,\n )?.[0] || dep,\n ),\n );\n }\n\n return graph;\n }\n\n /**\n * Resolve dependencies using topological sort\n */\n private resolveDependencies(graph: Map<string, string[]>): string[] {\n const resolved: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (node: string) => {\n if (visiting.has(node)) {\n throw new Error(`Circular dependency detected involving ${node}`);\n }\n if (visited.has(node)) return;\n\n visiting.add(node);\n const dependencies = graph.get(node) || [];\n\n for (const dep of dependencies) {\n if (graph.has(dep)) {\n visit(dep);\n }\n }\n\n visiting.delete(node);\n visited.add(node);\n resolved.push(node);\n };\n\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n visit(node);\n }\n }\n\n return resolved;\n }\n\n /**\n * Check if schema is up to date\n */\n private isSchemaUpToDate(schemaName: string, version: string): boolean {\n return (\n this.initializedSchemas.has(schemaName) &&\n this.schemaVersions.get(schemaName) === version\n );\n }\n\n /**\n * Mark schema as initialized\n */\n private markSchemaInitialized(schemaName: string, version: string): void {\n this.initializedSchemas.add(schemaName);\n this.schemaVersions.set(schemaName, version);\n }\n\n /**\n * Reset initialization state (for testing)\n */\n reset(): void {\n this.initializedSchemas.clear();\n this.schemaVersions.clear();\n DatabaseSchemaManager.initializationLock.clear();\n }\n}\n","/**\n * WHERE clause input for database queries\n *\n * Supports two formats:\n * 1. Object format (AND-only): `{ status: 'active', 'price >': 100 }`\n * - All conditions are AND-joined\n *\n * 2. 2D array format (OR/AND compound logic): `[[cond1, cond2], [cond3, cond4]]`\n * - Inner arrays are AND-joined: `(cond1 AND cond2)`\n * - Outer array is OR-joined: `(cond1 AND cond2) OR (cond3 AND cond4)`\n *\n * @example Object format (backward compatible)\n * ```typescript\n * // WHERE status = 'active' AND price > 100\n * const where = { status: 'active', 'price >': 100 };\n * ```\n *\n * @example 2D array format for OR/AND compound logic\n * ```typescript\n * // WHERE (status = 'active' AND price > 100) OR (status = 'pending' AND priority = 'high')\n * const where = [\n * [{ status: 'active' }, { 'price >': 100 }],\n * [{ status: 'pending' }, { priority: 'high' }]\n * ];\n * ```\n */\nexport type WhereClause = Record<string, any> | Record<string, any>[][];\n\n/**\n * Common database connection options\n */\nexport interface DatabaseOptions {\n /**\n * Database connection URL\n */\n url?: string;\n\n /**\n * Authentication token for the database connection\n */\n authToken?: string;\n}\n\n/**\n * DuckDB-specific connection options\n */\nexport interface DuckDBOptions extends DatabaseOptions {\n /**\n * Database type identifier\n */\n type?: 'duckdb';\n\n /**\n * Path to directory containing JSON files to auto-register as tables\n * @default './data'\n */\n dataDir?: string;\n\n /**\n * Automatically register JSON files in dataDir as queryable tables\n * @default true\n */\n autoRegisterJSON?: boolean;\n\n /**\n * Strategy for writing data back to JSON files\n * - 'immediate': Write changes to JSON files immediately\n * - 'manual': Require explicit export calls\n * - 'none': Read-only mode, no writes to JSON files\n * @default 'none'\n */\n writeStrategy?: 'immediate' | 'manual' | 'none';\n\n /**\n * Whether to use a persistent DuckDB file for caching/indexes\n * If true, uses url or defaults to ':memory:'\n * @default false\n */\n persistent?: boolean;\n\n /**\n * Explicit schema definitions for tables\n * When provided, these schemas will be used for table creation\n */\n schemas?: SchemasOption;\n}\n\n/**\n * JSON database adapter options (DuckDB-backed)\n *\n * Uses DuckDB's in-memory engine to query JSON files directly.\n * No WAL files or persistent database files are created.\n */\nexport interface JSONOptions {\n /**\n * Database type identifier\n */\n type: 'json';\n\n /**\n * Path to directory containing JSON files (required)\n * JSON files in this directory will be loaded as queryable tables\n */\n url: string;\n\n /**\n * Automatically load all JSON files in dataDir as tables\n * @default true\n */\n autoRegister?: boolean;\n\n /**\n * Strategy for writing changes back to JSON files\n * - 'immediate': Auto-save after every insert/update (default)\n * - 'manual': Require explicit exportTable() calls\n * - 'none': Read-only mode, throws error on writes\n * @default 'immediate'\n */\n writeStrategy?: 'immediate' | 'manual' | 'none';\n\n /**\n * Explicit schema definitions for tables\n *\n * When provided, these schemas will be used instead of auto-detection.\n * This allows frameworks to provide explicit schemas via dependency injection.\n *\n * @example\n * ```typescript\n * const db = await getDatabase({\n * type: 'json',\n * url: './data',\n * schemas: {\n * users: {\n * tableName: 'users',\n * ddl: 'CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT)',\n * indexes: ['CREATE INDEX idx_users_name ON users(name)']\n * }\n * }\n * });\n * ```\n */\n schemas?: SchemasOption;\n\n /**\n * Unique identifier for in-memory DuckDB instances to enable connection sharing\n * When multiple getDatabase() calls use the same dbid, they receive\n * the same database connection instance.\n *\n * Auto-generated if not provided, enabling connection sharing by default.\n * This solves the issue where multiple collections create separate in-memory\n * databases that can't see each other's tables.\n */\n dbid?: string;\n\n /**\n * Eagerly load all JSON files as tables at connection time\n *\n * When true (default), creates tables with inferred schemas for all JSON files\n * in the data directory, even those without explicit schemas or .schema.sql files.\n * This enables cross-table queries (JOINs, NOT EXISTS subqueries) before\n * syncSchema() is called.\n *\n * Note: Inferred schemas don't include UNIQUE constraints. UPSERT operations\n * require syncSchema() to be called first to establish proper constraints.\n * When syncSchema() is called, tables with inferred schemas are dropped and\n * recreated with the proper schema.\n *\n * @default true\n */\n eagerLoadTables?: boolean;\n\n /**\n * Force a fresh database connection, bypassing the connection cache\n *\n * When true, clears any cached connection for this URL before creating a new one.\n * Useful when you need to reload the database from disk after external changes.\n *\n * @default false\n *\n * @example\n * // Initial connection - cached\n * const db1 = await getDatabase({ type: 'json', url: './data' });\n *\n * // External process adds JSON files...\n *\n * // Force reload from disk\n * const db2 = await getDatabase({\n * type: 'json',\n * url: './data',\n * clearCache: true\n * });\n */\n clearCache?: boolean;\n}\n\n/**\n * Result of a database operation that modifies data\n */\nexport interface QueryResult {\n /**\n * Type of operation performed (e.g., \"insert\", \"update\", \"delete\")\n */\n operation: string;\n\n /**\n * Number of rows affected by the operation\n */\n affected: number;\n}\n\n/**\n * Options for upsert operations.\n */\nexport interface UpsertOptions {\n /**\n * Preserve database-native NULL-distinct conflict behavior.\n *\n * By default, upsert treats NULL values in conflict columns as matching\n * existing NULL values. Set this to true to opt out and use the underlying\n * database's native ON CONFLICT behavior where NULLs are distinct.\n */\n nullsDistinct?: boolean;\n}\n\n/**\n * Schema definition that can be provided to database adapters\n *\n * Allows frameworks like SMRT to provide explicit schemas instead of\n * relying on auto-detection or circular dependencies.\n *\n * This is a simpler, DDL-based alternative to SchemaDefinition which is\n * used for structured JSON manifests.\n */\nexport interface SchemaProvider {\n /**\n * Table name in snake_case plural form\n */\n tableName: string;\n\n /**\n * DDL statement(s) to create the table\n * Can be a single CREATE TABLE statement or multiple statements\n */\n ddl: string;\n\n /**\n * Index creation statements (optional)\n * Each string should be a complete CREATE INDEX statement\n */\n indexes?: string[];\n\n /**\n * Trigger creation statements (optional, adapter-specific support)\n * Each string should be a complete CREATE TRIGGER statement\n */\n triggers?: string[];\n\n /**\n * Schema version for migration tracking (optional)\n */\n version?: string;\n\n /**\n * Field metadata (optional, for advanced use cases)\n * Can be used by frameworks for runtime type information and validation\n */\n fields?: Map<string, any>;\n}\n\n/**\n * Schema definitions for getDatabase(), either eagerly built or lazy.\n *\n * Callers can pass schemas as a lazy function so that building the schema\n * map (potentially 200+ objects from ObjectRegistry) is deferred until an\n * adapter actually needs it. Adapters that manage tables via migrations\n * (Postgres, SQLite) never call the function, making the cost zero.\n *\n * @example Lazy — only resolved by JSON/DuckDB adapters\n * ```typescript\n * await getDatabase({\n * type: 'postgres',\n * url: '...',\n * schemas: () => ObjectRegistry.getAllSchemas(), // never called\n * });\n * ```\n *\n * @example Eager — built upfront (fine for JSON/DuckDB)\n * ```typescript\n * await getDatabase({\n * type: 'json',\n * url: './data',\n * schemas: { users: { tableName: 'users', ddl: '...' } },\n * });\n * ```\n */\nexport type SchemasOption =\n | Record<string, SchemaProvider>\n | (() => Record<string, SchemaProvider>);\n\n/**\n * Resolves a SchemasOption to its concrete value.\n *\n * Adapters that need schemas (JSON, DuckDB) call this to unwrap the\n * lazy function. Adapters that don't (Postgres, SQLite) simply ignore\n * the `schemas` option without calling this.\n */\nexport function resolveSchemas(\n schemas: SchemasOption | undefined,\n): Record<string, SchemaProvider> | undefined {\n if (!schemas) return undefined;\n if (typeof schemas === 'function') return schemas();\n return schemas;\n}\n\n/**\n * Schema manifest structure for JSON-based schema management\n */\nexport interface SchemaManifest {\n version: string;\n timestamp: number;\n packageName: string;\n schemas: Record<string, SchemaDefinition>;\n dependencies: string[];\n}\n\n/**\n * Schema definition for individual tables\n */\nexport interface SchemaDefinition {\n tableName: string;\n columns: Record<string, ColumnDefinition>;\n indexes: IndexDefinition[];\n triggers: TriggerDefinition[];\n foreignKeys: ForeignKeyDefinition[];\n dependencies: string[];\n version: string;\n packageName: string;\n baseClass?: string;\n}\n\n/**\n * Column definition structure\n */\nexport interface ColumnDefinition {\n type: string;\n primaryKey?: boolean;\n unique?: boolean;\n notNull?: boolean;\n defaultValue?: any;\n check?: string;\n foreignKey?: {\n table: string;\n column: string;\n onDelete?: string;\n onUpdate?: string;\n };\n description?: string;\n}\n\n/**\n * Column definition with name for ALTER TABLE operations\n */\nexport interface ColumnDefinitionWithName extends ColumnDefinition {\n name: string;\n}\n\n/**\n * Index definition structure\n */\nexport interface IndexDefinition {\n name: string;\n columns: string[];\n unique?: boolean;\n where?: string;\n description?: string;\n}\n\n/**\n * Trigger definition structure\n */\nexport interface TriggerDefinition {\n name: string;\n when: string;\n event: string;\n table: string;\n condition?: string;\n body: string;\n description?: string;\n}\n\n/**\n * Foreign key constraint definition\n */\nexport interface ForeignKeyDefinition {\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete?: string;\n onUpdate?: string;\n}\n\n/**\n * Options for schema initialization and management\n */\nexport interface SchemaInitializationOptions {\n /** Schema manifest containing table definitions */\n manifest?: SchemaManifest;\n /** Raw SQL DDL schema string (legacy support) */\n schema?: string;\n /** Schema overrides for extending base schemas */\n overrides?: Record<string, SchemaDefinition>;\n /** Force recreation of tables */\n force?: boolean;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Table schema information returned by getTableSchema()\n */\nexport interface TableSchemaInfo {\n /** Table name */\n tableName: string;\n /** Columns in the table */\n columns: Record<string, ColumnDefinition>;\n /** Indexes on the table */\n indexes: IndexDefinition[];\n /** Foreign key constraints */\n foreignKeys: ForeignKeyDefinition[];\n}\n\n/**\n * Options for vector similarity search\n */\nexport interface VectorSearchOptions {\n /** Maximum number of results to return */\n limit?: number;\n /** Distance metric for similarity comparison @default 'cosine' */\n metric?: 'cosine' | 'l2' | 'ip';\n /**\n * Additional SQL WHERE clause.\n * Use $2, $3, etc. for parameter placeholders ($1 is reserved for the query vector).\n * @example `category = $2`\n */\n where?: string;\n /** Parameters for the WHERE clause, bound to $2, $3, etc. */\n params?: any[];\n}\n\n/**\n * Result of a vector similarity search\n */\nexport interface VectorSearchResult {\n /** Row primary key */\n id: string;\n /**\n * Distance from query vector (lower = more similar).\n * Range varies by metric: cosine [0, 2], L2 [0, Infinity), ip (-Infinity, Infinity).\n */\n distance: number;\n /** Additional columns from the row */\n [key: string]: any;\n}\n\n/**\n * Options for creating a vector index\n */\nexport interface VectorIndexOptions {\n /** Number of dimensions (informational only, dimensions are set via ensureColumn) */\n dimensions?: number;\n /** Distance metric @default 'cosine' */\n metric?: 'cosine' | 'l2' | 'ip';\n /** Index type @default 'hnsw' */\n type?: 'hnsw' | 'ivfflat';\n}\n\n/**\n * Vector operations capability for database adapters\n *\n * Provides native vector similarity search, storage, and indexing.\n * Implemented by PostgreSQL via pgvector and optionally by SQLite via\n * sqlite-vector.\n */\nexport interface VectorCapabilities {\n /**\n * Search for similar vectors\n *\n * @param table - Table containing vector column\n * @param column - Name of the vector column\n * @param embedding - Query vector\n * @param options - Search options\n * @returns Ranked results by similarity\n */\n search(\n table: string,\n column: string,\n embedding: number[],\n options?: VectorSearchOptions,\n ): Promise<VectorSearchResult[]>;\n\n /**\n * Ensure a vector column exists on a table\n *\n * @param table - Table name\n * @param column - Column name\n * @param dimensions - Number of vector dimensions\n */\n ensureColumn(\n table: string,\n column: string,\n dimensions: number,\n ): Promise<void>;\n\n /**\n * Ensure a vector index exists on a column\n *\n * @param table - Table name\n * @param column - Column name\n * @param options - Index options\n */\n ensureIndex(\n table: string,\n column: string,\n options?: VectorIndexOptions,\n ): Promise<void>;\n\n /**\n * Store or update a vector in a specific row\n *\n * @param table - Table name\n * @param where - Conditions to identify the row\n * @param column - Vector column name\n * @param embedding - Vector data\n */\n upsertVector(\n table: string,\n where: Record<string, any>,\n column: string,\n embedding: number[],\n ): Promise<void>;\n}\n\n/**\n * SQLite notification delivered by optional notification capabilities.\n */\nexport interface DatabaseNotification {\n id: number;\n channel: string;\n payload: any;\n createdAt?: number | string | Date | null;\n}\n\n/**\n * Options for notification listeners.\n */\nexport interface NotificationListenOptions {\n /**\n * Fallback poll interval in milliseconds when the native watcher does not\n * receive an update signal.\n */\n fallbackPollMs?: number | null;\n}\n\n/**\n * Options for waiting on the next database update.\n */\nexport interface NotificationWaitOptions {\n /**\n * Maximum time to wait in milliseconds. When omitted, waits indefinitely.\n */\n timeoutMs?: number;\n\n /**\n * Optional abort signal to cancel the wait.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for pruning persisted notification rows.\n */\nexport interface NotificationPruneOptions {\n /** Delete notifications older than this many seconds. */\n olderThanS?: number | null;\n /** Keep at most this many most-recent notifications. */\n maxKeep?: number | null;\n}\n\n/**\n * Optional notification/pub-sub capabilities for database adapters.\n */\nexport interface NotificationCapabilities {\n notify(channel: string, payload: any): Promise<number>;\n listen(\n channel: string,\n options?: NotificationListenOptions,\n ): AsyncIterable<DatabaseNotification>;\n waitForUpdate(options?: NotificationWaitOptions): Promise<boolean>;\n prune(options?: NotificationPruneOptions): Promise<number>;\n}\n\n/**\n * Options for SQLite native notification support.\n */\nexport interface SqliteNotificationCapabilityOptions {\n watcherBackend?: 'polling' | 'kernel' | 'shm';\n maxReaders?: number;\n}\n\n/**\n * Options for SQLite native vector support.\n */\nexport interface SqliteVectorCapabilityOptions {\n preload?: boolean;\n quantization?: 'turbo4' | 'turbo3' | 'turbo2' | 'uint8' | 'int8' | '1bit';\n maxMemory?: string;\n}\n\n/**\n * Optional SQLite-only native capabilities.\n */\nexport interface SqliteCapabilitiesOptions {\n notifications?: boolean | SqliteNotificationCapabilityOptions;\n vector?: boolean | SqliteVectorCapabilityOptions;\n}\n\n/**\n * Common interface for database adapters\n * Provides a unified API for different database backends\n */\nexport interface DatabaseInterface {\n /**\n * Database location identifier\n * For file-based databases: file path\n * For directory-based databases (JSON/DuckDB with JSON): directory path\n * For in-memory databases: ':memory:'\n * For remote databases: connection URL\n */\n url: string;\n\n /**\n * Underlying database client instance\n */\n client: any;\n\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n */\n insert: (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ) => Promise<QueryResult>;\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to matching record or null if not found\n */\n get: (\n table: string,\n where: WhereClause,\n ) => Promise<Record<string, any> | null>;\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to array of matching records\n */\n list: (table: string, where: WhereClause) => Promise<Record<string, any>[]>;\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update (object for AND-only, 2D array for OR/AND)\n * @param data - New data to set\n * @returns Promise resolving to operation result\n */\n update: (\n table: string,\n where: WhereClause,\n data: Record<string, any>,\n ) => Promise<QueryResult>;\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n * Uses database-specific ON CONFLICT / ON DUPLICATE KEY syntax\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n *\n * @example\n * ```typescript\n * // Upsert a user by email\n * await db.upsert('users', ['email'], {\n * email: 'user@example.com',\n * name: 'John Doe',\n * updated_at: new Date().toISOString()\n * });\n *\n * // Upsert with composite key\n * await db.upsert('settings', ['user_id', 'key'], {\n * user_id: '123',\n * key: 'theme',\n * value: 'dark'\n * });\n * ```\n */\n upsert: (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ) => Promise<QueryResult>;\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record (object for AND-only, 2D array for OR/AND)\n * @param data - Data to insert if no record found\n * @returns Promise resolving to the record (either retrieved or newly inserted)\n */\n getOrInsert: (\n table: string,\n where: WhereClause,\n data: Record<string, any>,\n ) => Promise<Record<string, any>>;\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to operation result with count of deleted rows\n *\n * @example\n * ```typescript\n * // Delete by ID\n * await db.delete('products', { id: 'prod-123' });\n *\n * // Delete by criteria\n * await db.delete('orders', { status: 'cancelled' });\n *\n * // Delete with multiple conditions\n * await db.delete('sessions', {\n * user_id: 'user-123',\n * expired: true\n * });\n * ```\n */\n delete: (table: string, where: WhereClause) => Promise<QueryResult>;\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted; object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to count of matching records\n *\n * @example\n * ```typescript\n * // Count all records\n * const total = await db.count('products');\n *\n * // Count with single condition\n * const activeCount = await db.count('products', { active: true });\n *\n * // Count with multiple conditions\n * const filteredCount = await db.count('orders', {\n * status: 'pending',\n * priority: 'high'\n * });\n * ```\n */\n count: (table: string, where?: WhereClause) => Promise<number>;\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param table - Table name\n * @returns TableInterface for the specified table\n */\n table: (table: string) => TableInterface;\n\n /**\n * Checks if a table exists in the database\n *\n * @param table - Table name\n * @returns Promise resolving to boolean indicating existence\n */\n tableExists: (table: string) => Promise<boolean>;\n\n /**\n * Whether this adapter requires schema existence checks at runtime.\n *\n * Set to `true` on adapters where tables may not exist yet and need\n * to be verified before use (e.g. JSON/DuckDB with auto-created tables).\n *\n * When absent or `false`, frameworks skip `tableExists()` calls during\n * collection initialization — tables are assumed to exist because\n * schema is managed by migrations (e.g. `smrt db:migrate`).\n *\n * - Postgres adapter: not set (migration-managed)\n * - SQLite adapter: not set (migration-managed)\n * - JSON/DuckDB adapter: `true` (tables may be auto-created)\n */\n requiresSchemaCheck?: boolean;\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n */\n many: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any>[]>;\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n */\n single: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any> | null>;\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n */\n pluck: (strings: TemplateStringsArray, ...vars: any[]) => Promise<any>;\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n */\n execute: (strings: TemplateStringsArray, ...vars: any[]) => Promise<void>;\n\n /**\n * Alias for many() - Executes a SQL query and returns multiple rows\n */\n oo: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any>[]>;\n\n /**\n * Alias for single() - Executes a SQL query and returns a single row\n */\n oO: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any> | null>;\n\n /**\n * Alias for pluck() - Executes a SQL query and returns a single value\n */\n ox: (strings: TemplateStringsArray, ...vars: any[]) => Promise<any>;\n\n /**\n * Alias for execute() - Executes a SQL query without returning results\n */\n xx: (strings: TemplateStringsArray, ...vars: any[]) => Promise<void>;\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * Raw queries use the adapter's native placeholder syntax.\n * Parameters may be passed as rest arguments or as one values array.\n * For adapter-specific array parameter caveats, see the package docs.\n *\n * @param str - SQL query string\n * @param vars - Variables to use as parameters\n * @returns Promise resolving to query result with rows and count\n */\n query: (\n str: string,\n ...vars: any[]\n ) => Promise<{ rows: Record<string, any>[]; rowCount: number }>;\n\n /**\n * Synchronizes database schema with provided SQL DDL\n * Creates tables if they don't exist and adds missing columns\n *\n * @param schema - SQL schema definition with CREATE TABLE statements\n * @returns Promise that resolves when schema is synchronized\n */\n syncSchema?: (schema: string) => Promise<void>;\n\n /**\n * Initialize database schemas from JSON manifest\n * Supports dependency resolution and schema overrides\n *\n * @param options - Schema initialization options\n * @returns Promise that resolves when schemas are initialized\n */\n initializeSchemas?: (options: SchemaInitializationOptions) => Promise<void>;\n\n /**\n * Executes a callback within a database transaction\n * Automatically commits on success or rolls back on error\n *\n * @param callback - Function to execute within transaction\n * @returns Promise resolving to callback result\n */\n transaction?: <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ) => Promise<T>;\n\n /**\n * Begins a new transaction and returns a handle for manual control\n *\n * Unlike transaction(), this gives you explicit control over commit/rollback.\n * Ideal for test isolation where you want to rollback after each test.\n *\n * @returns Promise resolving to a TransactionHandle\n *\n * @example Test isolation pattern\n * ```typescript\n * let tx: TransactionHandle;\n *\n * beforeEach(async () => {\n * tx = await db.beginTransaction();\n * });\n *\n * afterEach(async () => {\n * await tx.rollback(); // Discard all test changes\n * });\n *\n * it('creates user', async () => {\n * await tx.insert('users', { id: '1', name: 'Test' });\n * const user = await tx.get('users', { id: '1' });\n * expect(user).toBeDefined();\n * // Changes rolled back in afterEach\n * });\n * ```\n */\n beginTransaction?: () => Promise<TransactionHandle>;\n\n /**\n * Acquire a pinned single-connection session.\n *\n * Returns a {@link SessionHandle} whose queries all run on one underlying\n * connection, enabling session-scoped state (e.g. PostgreSQL session advisory\n * locks) that the pooled top-level {@link query} cannot hold reliably. The\n * caller must {@link SessionHandle.release} it.\n *\n * Only meaningful for engines with session-scoped state, so it is currently\n * implemented for PostgreSQL only; check for the method before calling\n * (`if (db.acquireSession)`). Single-connection engines (SQLite, DuckDB) have\n * no session-scoped locks to hold, so they leave it undefined.\n *\n * @returns Promise resolving to a SessionHandle\n *\n * @example Hold a Postgres session advisory lock\n * ```typescript\n * const session = await db.acquireSession();\n * try {\n * await session.query('SELECT pg_advisory_lock($1)', 42);\n * // ... lock is held for the life of this session ...\n * } finally {\n * await session.release(); // frees the lock and drops the connection\n * }\n * ```\n */\n acquireSession?: () => Promise<SessionHandle>;\n\n /**\n * Retrieves the schema information for a table\n *\n * @param table - Table name\n * @returns Promise resolving to table schema info or null if table doesn't exist\n */\n getTableSchema?: (table: string) => Promise<TableSchemaInfo | null>;\n\n /**\n * Vector operations for native similarity search\n *\n * When available, enables database-level vector operations (e.g., pgvector).\n * Consumers should check for this capability rather than checking the database type.\n */\n vector?: VectorCapabilities;\n\n /**\n * Optional notification/pub-sub operations.\n */\n notifications?: NotificationCapabilities;\n\n /**\n * Close the database adapter and release native resources when supported.\n */\n close?: () => Promise<void>;\n\n /**\n * ALTER TABLE operations for schema evolution\n */\n alterTable?: {\n /**\n * Adds a new column to an existing table\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @returns Promise that resolves when column is added\n */\n addColumn: (\n table: string,\n column: ColumnDefinitionWithName,\n ) => Promise<void>;\n\n /**\n * Adds a new index to an existing table\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns Promise that resolves when index is created\n */\n addIndex: (table: string, index: IndexDefinition) => Promise<void>;\n };\n}\n\n/**\n * Transaction handle for manual transaction control\n *\n * Extends DatabaseInterface with commit() and rollback() methods.\n * Use beginTransaction() to obtain a handle, then explicitly\n * commit or rollback when done.\n *\n * @example Test isolation with rollback\n * ```typescript\n * const tx = await db.beginTransaction();\n * try {\n * // All operations happen in the transaction\n * await tx.insert('users', { id: '1', name: 'Test' });\n * const user = await tx.get('users', { id: '1' });\n *\n * // Rollback discards all changes (useful for test isolation)\n * await tx.rollback();\n * } catch (error) {\n * await tx.rollback();\n * throw error;\n * }\n * ```\n *\n * @example Manual commit\n * ```typescript\n * const tx = await db.beginTransaction();\n * try {\n * await tx.insert('orders', { id: '1', total: 100 });\n * await tx.insert('order_items', { order_id: '1', product: 'Widget' });\n * await tx.commit(); // Persist changes\n * } catch (error) {\n * await tx.rollback();\n * throw error;\n * }\n * ```\n */\nexport interface TransactionHandle extends DatabaseInterface {\n /**\n * Commits the transaction, persisting all changes\n *\n * After commit, the transaction handle should not be used.\n */\n commit: () => Promise<void>;\n\n /**\n * Rolls back the transaction, discarding all changes\n *\n * After rollback, the transaction handle should not be used.\n * This is the key method for test isolation - rollback after each test.\n */\n rollback: () => Promise<void>;\n\n /**\n * Whether the transaction is still active (not committed or rolled back)\n */\n isActive: () => boolean;\n}\n\n/**\n * Pinned single-connection session handle.\n *\n * Obtained via {@link DatabaseInterface.acquireSession}. Unlike the pooled\n * top-level `query` (which may run each statement on a different connection),\n * every call on a session handle runs on the *same* underlying connection for\n * the handle's lifetime. This is required for session-scoped state such as\n * PostgreSQL session advisory locks (`pg_advisory_lock`), which must be\n * acquired, observed, and released on one connection — and which release\n * automatically if the connection drops (e.g. the process dies).\n *\n * A session holds one connection out of the pool (default max 20) for its\n * entire lifetime, so it is meant to be held one-per-process, not per-operation.\n * Always {@link SessionHandle.release} the handle when done, and release it\n * *before* calling `db.client.end()` — a pinned connection keeps `pool.end()`\n * from resolving.\n */\nexport interface SessionHandle {\n /**\n * Execute a raw query on this session's pinned connection.\n * Same placeholder/return contract as {@link DatabaseInterface.query}.\n * Throws if the session has been released or its connection was lost.\n */\n query: (\n sql: string,\n ...vars: any[]\n ) => Promise<{ rows: Record<string, any>[]; rowCount: number }>;\n\n /**\n * Whether the session is still usable — not released and its connection has\n * not errored/dropped. A long-lived lock holder can poll this without\n * issuing a query.\n */\n isActive: () => boolean;\n\n /**\n * Release the session. Idempotent. After release the handle must not be used.\n * Best-effort frees session-scoped locks, then drops the underlying\n * connection (it is NOT returned to the pool) so the database releases any\n * remaining session state — returning it to the pool would leak that state\n * onto a later, unrelated checkout.\n */\n release: () => Promise<void>;\n}\n\n/**\n * Simplified interface for table-specific operations\n */\nexport interface TableInterface {\n /**\n * Inserts one or more records into the table\n *\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n */\n insert: (\n data: Record<string, any> | Record<string, any>[],\n ) => Promise<QueryResult>;\n\n /**\n * Retrieves a single record from the table matching the where criteria\n *\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to matching record or null if not found\n */\n get: (where: WhereClause) => Promise<Record<string, any> | null>;\n\n /**\n * Retrieves multiple records from the table matching the where criteria\n *\n * @param where - Criteria to match records (object for AND-only, 2D array for OR/AND)\n * @returns Promise resolving to array of matching records\n */\n list: (where: WhereClause) => Promise<Record<string, any>[]>;\n}\n","import { mkdir, readdir } from 'node:fs/promises';\nimport { basename, extname, join } from 'node:path';\nimport { DatabaseError } from '@happyvertical/utils';\nimport { DatabaseSchemaManager } from './schema-manager';\nimport { convertUniqueIndexesToInlineConstraints } from './shared/duckdb-schema-utils';\nimport type {\n DatabaseInterface,\n JSONOptions,\n QueryResult,\n SchemaInitializationOptions,\n TableInterface,\n TransactionHandle,\n UpsertOptions,\n} from './shared/types';\nimport { resolveSchemas } from './shared/types';\nimport { buildWhere, formatDbError } from './shared/utils';\n\n/**\n * Extend globalThis to include our connection cache properties.\n * Using globalThis ensures all module instances share the same cache,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/sdk/issues/678\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __haveSqlMemoryConnectionCache:\n | Map<string, DatabaseInterface>\n | undefined;\n // eslint-disable-next-line no-var\n var __haveSqlPendingConnections:\n | Map<string, Promise<DatabaseInterface>>\n | undefined;\n}\n\n/**\n * Connection cache for in-memory DuckDB instances keyed by data directory URL\n * Enables sharing of in-memory databases across multiple getDatabase() calls\n * with the same data directory.\n *\n * Uses globalThis to ensure cache is shared across all module instances,\n * fixing the lost update bug in monorepos with workspace symlinks.\n *\n * @see https://github.com/happyvertical/sdk/issues/678\n */\nglobalThis.__haveSqlMemoryConnectionCache ??= new Map<\n string,\n DatabaseInterface\n>();\nconst memoryConnectionCache = globalThis.__haveSqlMemoryConnectionCache;\n\n/**\n * Pending connection promises to handle concurrent getDatabase() calls\n * Prevents creating duplicate connections when parallel calls happen.\n *\n * Uses globalThis to ensure cache is shared across all module instances.\n *\n * @see https://github.com/happyvertical/sdk/issues/678\n */\nglobalThis.__haveSqlPendingConnections ??= new Map<\n string,\n Promise<DatabaseInterface>\n>();\nconst pendingConnections = globalThis.__haveSqlPendingConnections;\n\n/**\n * Clears all cached connections\n * Useful for testing to ensure test isolation\n */\nexport function clearConnectionCache(): void {\n memoryConnectionCache.clear();\n pendingConnections.clear();\n}\n\n/**\n * Creates a JSON database connection using DuckDB in-memory engine\n *\n * This adapter uses DuckDB as a query engine for JSON files, storing everything\n * in-memory and writing changes back to JSON files. No WAL files or persistent\n * database files are created.\n *\n * @param options - JSON database options\n * @returns Promise resolving to a DuckDB connection\n */\nasync function createJSONConnection(options: JSONOptions) {\n const { url, autoRegister = true, eagerLoadTables = true } = options;\n const schemas = resolveSchemas(options.schemas) ?? {};\n\n if (!url) {\n throw new DatabaseError('url is required for JSON adapter', {\n options,\n });\n }\n\n // Track JSON files pending deferred loading (tableName → filePath)\n const pendingJSONFiles = new Map<string, string>();\n\n // Track tables created with inferred schemas (need DROP before syncSchema())\n const inferredSchemaTables = new Set<string>();\n\n try {\n // Dynamic import to avoid bundling\n const duckdbModule = '@duckdb/node-api';\n const { DuckDBInstance } = await import(/* @vite-ignore */ duckdbModule);\n\n // Always use in-memory database - no persistent files\n const instance = await DuckDBInstance.create(':memory:');\n const connection = await instance.connect();\n\n // Ensure data directory exists\n try {\n await mkdir(url, { recursive: true });\n } catch (_error) {\n // Directory might already exist, that's okay\n }\n\n // Scan JSON files - tables with schemas are created now, others are deferred\n if (autoRegister) {\n await loadJSONTables(\n connection,\n url,\n schemas,\n pendingJSONFiles,\n eagerLoadTables,\n inferredSchemaTables,\n );\n }\n\n return { connection, pendingJSONFiles, inferredSchemaTables };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new DatabaseError(\n `Failed to create JSON database connection: ${errorMessage}`,\n {\n url,\n originalError: errorMessage,\n },\n );\n }\n}\n\n/**\n * Loads JSON data into an existing table\n *\n * This function only loads data - it assumes the table already exists with proper schema.\n * Used after DDL creates the table to load persisted JSON data.\n *\n * @param connection - DuckDB connection\n * @param tableName - Name of the table to load data into\n * @param filePath - Path to the JSON file\n */\nasync function loadJSONData(\n connection: any,\n tableName: string,\n filePath: string,\n): Promise<void> {\n try {\n const { readFile } = await import('node:fs/promises');\n const jsonContent = await readFile(filePath, 'utf-8');\n const records = JSON.parse(jsonContent);\n\n if (Array.isArray(records) && records.length > 0) {\n await insertRecordsWithCast(connection, tableName, records);\n console.log(\n `[json-adapter] Loaded ${records.length} records into ${tableName} from JSON`,\n );\n }\n } catch (error) {\n // If load fails (e.g., empty file, parse error), that's okay - table structure is what matters\n console.warn(\n `[json-adapter] Could not load data for ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\n/**\n * Scans the data directory and registers JSON files for deferred loading\n *\n * Unlike the DuckDB adapter which creates views, this creates actual tables\n * so that indexes can be added.\n *\n * Schema resolution priority:\n * 1. Explicit schemas provided via options.schemas - table created immediately\n * 2. Schema file (.schema.sql) in data directory - table created with schema\n * 3. All other tables - DEFERRED until syncSchema() provides DDL\n *\n * IMPORTANT: Tables without explicit schemas are NOT auto-created from JSON.\n * This ensures UNIQUE constraints from syncSchema() are in place before data\n * is loaded, which is required for UPSERT operations to work correctly.\n *\n * For users who want auto-inference, use the inferSchemaFromJSON() method\n * after database creation.\n *\n * @param connection - DuckDB connection\n * @param dataDir - Directory containing JSON files\n * @param providedSchemas - Explicit schema definitions provided by caller (optional)\n * @param pendingJSONFiles - Map to store JSON files pending deferred loading\n * @param eagerLoadTables - Whether to eagerly create tables with inferred schemas\n * @param inferredSchemaTables - Set to track tables created with inferred schemas\n */\nasync function loadJSONTables(\n connection: any,\n dataDir: string,\n providedSchemas: Record<string, import('./shared/types').SchemaProvider> = {},\n pendingJSONFiles: Map<string, string> = new Map(),\n eagerLoadTables: boolean = true,\n inferredSchemaTables: Set<string> = new Set(),\n) {\n try {\n const files = await readdir(dataDir);\n const jsonFiles = files.filter(\n (file) => extname(file).toLowerCase() === '.json',\n );\n\n for (const file of jsonFiles) {\n const filePath = join(dataDir, file);\n const tableName = basename(file, '.json');\n\n // Check for explicitly provided schema\n const schema = providedSchemas[tableName];\n\n if (schema) {\n // Create table with provided schema (proper typing)\n console.log(\n `[json-adapter] Creating ${tableName} with provided schema definition`,\n );\n await createTableFromSchema(connection, tableName, schema);\n\n // Load JSON data into properly-typed table\n await loadJSONData(connection, tableName, filePath);\n } else {\n // Check for schema file first (preserves constraints like PRIMARY KEY, UNIQUE, etc.)\n const schemaPath = join(dataDir, `${tableName}.schema.sql`);\n const { readFile, access } = await import('node:fs/promises');\n const { constants } = await import('node:fs');\n\n let schemaExists = false;\n try {\n await access(schemaPath, constants.F_OK);\n schemaExists = true;\n } catch {\n schemaExists = false;\n }\n\n if (schemaExists) {\n // Schema file exists - create table and load data now\n try {\n const schemaDDL = await readFile(schemaPath, 'utf-8');\n await connection.run(schemaDDL);\n await loadJSONData(connection, tableName, filePath);\n } catch (error) {\n console.warn(\n `[json-adapter] Could not load ${tableName} with schema file: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n } else {\n // No schema file - either eager load with inferred schema or defer\n if (eagerLoadTables) {\n // Eager load: create table with inferred schema from JSON\n // This enables cross-table queries before syncSchema() is called\n // Note: Inferred schemas don't have UNIQUE constraints, so UPSERT won't work\n // until syncSchema() is called to upgrade the schema\n try {\n await connection.run(\n `CREATE TABLE IF NOT EXISTS \"${tableName}\" AS SELECT * FROM read_json_auto('${filePath}')`,\n );\n inferredSchemaTables.add(tableName);\n console.log(\n `[json-adapter] Eagerly created ${tableName} with inferred schema (no UNIQUE constraints)`,\n );\n } catch (error) {\n console.warn(\n `[json-adapter] Could not eagerly load ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n } else {\n console.log(\n `[json-adapter] Deferring ${tableName} - will load after syncSchema() creates table`,\n );\n }\n // Always track for later schema upgrade and data reload\n pendingJSONFiles.set(tableName, filePath);\n }\n }\n }\n } catch (error) {\n // If directory doesn't exist or is empty, that's okay\n if ((error as any).code !== 'ENOENT') {\n // Log the error for debugging\n console.error('[json-adapter] Error loading JSON tables:', error);\n throw new DatabaseError(`Failed to load JSON tables from ${dataDir}`, {\n dataDir,\n originalError: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n}\n\n/**\n * Converts DuckDB-specific type representations to JavaScript types\n *\n * Handles three cases:\n * 1. JavaScript BigInt values → converted to numbers\n * 2. DuckDB hugeint objects ({ hugeint: number }) → converted to strings\n * 3. DuckDB timestamp objects ({ micros: number }) → converted to Date objects\n *\n * DuckDB represents HUGEINT (128-bit integers) as objects with a single\n * property called 'hugeint'. When UUID strings (stored as TEXT) are\n * exported to JSON via COPY TO, DuckDB sometimes converts them to hugeint\n * representation. This function converts them back to strings.\n *\n * DuckDB represents TIMESTAMP values as objects with a single property\n * called 'micros' containing microseconds since Unix epoch. This function\n * converts them to JavaScript Date objects for proper round-trip serialization.\n *\n * @param obj - Object that may contain BigInt, hugeint, or timestamp values\n * @returns Object with DuckDB types converted to JavaScript types\n */\nfunction convertBigInts(obj: any): any {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === 'bigint') return Number(obj);\n\n // Handle DuckDB hugeint objects: { hugeint: number }\n // Convert to string to preserve UUID/TEXT values\n if (\n typeof obj === 'object' &&\n !Array.isArray(obj) &&\n 'hugeint' in obj &&\n Object.keys(obj).length === 1\n ) {\n // Convert hugeint to string representation\n // For UUIDs and other TEXT values that DuckDB converted\n return String(obj.hugeint);\n }\n\n // Handle DuckDB timestamp objects: { micros: number | bigint }\n // Convert to JavaScript Date for proper round-trip serialization\n // Fixes issue #319: JSON adapter fails to serialize Date fields during UPSERT\n if (\n typeof obj === 'object' &&\n !Array.isArray(obj) &&\n 'micros' in obj &&\n Object.keys(obj).length === 1 &&\n (typeof obj.micros === 'number' || typeof obj.micros === 'bigint')\n ) {\n // Convert microseconds to milliseconds for Date constructor\n // DuckDB stores timestamps as microseconds since Unix epoch\n // Handle both number and bigint types (DuckDB can return either)\n const micros =\n typeof obj.micros === 'bigint' ? Number(obj.micros) : obj.micros;\n const milliseconds = micros / 1000;\n return new Date(milliseconds);\n }\n\n if (Array.isArray(obj)) return obj.map(convertBigInts);\n if (typeof obj === 'object') {\n const result: any = {};\n for (const key in obj) {\n result[key] = convertBigInts(obj[key]);\n }\n return result;\n }\n return obj;\n}\n\n/**\n * Creates a table from a schema definition with proper typing\n *\n * DuckDB has issues with type inference when DEFAULT values are empty strings.\n * This function explicitly casts all DEFAULT values to their column types to\n * prevent DuckDB from inferring ANY type.\n *\n * Additionally, DuckDB has a known limitation (issue #12684) where ON CONFLICT\n * clauses fail with UNIQUE INDEX but work with inline UNIQUE constraints.\n * This function converts UNIQUE indexes to inline constraints for compatibility.\n *\n * @param connection - DuckDB connection\n * @param tableName - Name of the table to create\n * @param schema - Schema definition with DDL and indexes\n */\nasync function createTableFromSchema(\n connection: any,\n tableName: string,\n schema: import('./shared/types').SchemaProvider,\n): Promise<void> {\n // Extract CREATE TABLE statement (without triggers which aren't supported)\n const ddlLines = schema.ddl.split('\\n');\n const createTableEnd = ddlLines.findIndex((line) => {\n const trimmed = line.trim();\n return trimmed === ')' || trimmed.startsWith(');');\n });\n\n if (createTableEnd === -1) {\n throw new DatabaseError('Invalid schema DDL - no closing parenthesis', {\n tableName,\n ddl: schema.ddl,\n });\n }\n\n // Get CREATE TABLE statement\n let createTableSQL = ddlLines.slice(0, createTableEnd + 1).join('\\n');\n\n // Fix DEFAULT values for DuckDB type inference\n // DuckDB infers ANY type when DEFAULT is an empty string without explicit cast\n // Replace patterns like: DEFAULT '' with DEFAULT CAST('' AS TEXT)\n createTableSQL = createTableSQL.replace(\n /\\b(\\w+)\\s+(TEXT|VARCHAR)\\s+DEFAULT\\s+''/g,\n \"$1 $2 DEFAULT CAST('' AS $2)\",\n );\n\n // Also handle DEFAULT NULL cases to ensure proper typing\n createTableSQL = createTableSQL.replace(\n /\\b(\\w+)\\s+(TEXT|VARCHAR)\\s+DEFAULT\\s+NULL/g,\n '$1 $2 DEFAULT CAST(NULL AS $2)',\n );\n\n // Convert UNIQUE indexes to inline UNIQUE constraints for DuckDB compatibility\n // DuckDB's ON CONFLICT requires inline constraints, not separate indexes\n const transformed = convertUniqueIndexesToInlineConstraints(\n createTableSQL,\n schema.indexes,\n );\n createTableSQL = transformed.ddl;\n const indexesToCreate = transformed.indexes;\n\n try {\n await connection.run(createTableSQL);\n\n // Get actual columns after table creation\n let existingColumns: Set<string> = new Set();\n try {\n const schemaInfo = await connection.runAndReadAll(\n `DESCRIBE ${tableName}`,\n );\n const columns = schemaInfo.getRowObjects();\n existingColumns = new Set(\n columns.map((col: any) => col.column_name.toLowerCase()),\n );\n\n console.log(`[json-adapter] Created ${tableName} with schema:`, {\n columns: columns.map((col: any) => ({\n name: col.column_name,\n type: col.column_type,\n null: col.null,\n })),\n });\n } catch (error) {\n // Schema verification failed, but table was created - log warning and continue\n console.warn(\n `[json-adapter] Could not verify schema for ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n // Add columns from fields that aren't in the DDL (important for STI subclass fields)\n if (schema.fields && existingColumns.size > 0) {\n // Handle both Map and Record formats\n const fieldEntries =\n schema.fields instanceof Map\n ? Array.from(schema.fields.entries())\n : Object.entries(schema.fields);\n\n for (const [fieldName, fieldDef] of fieldEntries) {\n const columnName = fieldName.toLowerCase();\n if (!existingColumns.has(columnName)) {\n // Determine SQL type from field definition\n const sqlType = fieldDef?.type || 'TEXT';\n try {\n await connection.run(\n `ALTER TABLE ${tableName} ADD COLUMN \"${fieldName}\" ${sqlType}`,\n );\n console.log(\n `[json-adapter] Added missing column '${fieldName}' (${sqlType}) to ${tableName}`,\n );\n } catch (alterError) {\n console.warn(\n `[json-adapter] Could not add column '${fieldName}' to ${tableName}: ${alterError instanceof Error ? alterError.message : String(alterError)}`,\n );\n }\n }\n }\n }\n\n // Create remaining indexes (non-UNIQUE indexes only)\n // UNIQUE indexes have been converted to inline constraints\n if (indexesToCreate && indexesToCreate.length > 0) {\n for (const indexSQL of indexesToCreate) {\n try {\n await connection.run(indexSQL);\n } catch (error) {\n // Index creation might fail if column doesn't exist or syntax incompatibility\n console.warn(\n `[json-adapter] Failed to create index: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n } catch (error) {\n throw new DatabaseError('Failed to create table from schema', {\n tableName,\n sql: createTableSQL,\n originalError: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\n/**\n * Inserts records with proper CAST handling for empty strings\n *\n * This helper avoids using read_json() with auto_detect, which causes DuckDB\n * to re-infer column types from data (causing ANY type for empty strings).\n * Instead, it uses parameterized INSERT with CAST to maintain table schema.\n *\n * @param connection - DuckDB connection\n * @param tableName - Name of the table to insert into\n * @param records - Array of records to insert\n */\nasync function insertRecordsWithCast(\n connection: any,\n tableName: string,\n records: Record<string, any>[],\n): Promise<void> {\n if (records.length === 0) return;\n\n const keys = Object.keys(records[0]);\n\n // Build placeholders - schema has NOT NULL DEFAULT '' to prevent ANY type\n const values: any[] = [];\n let paramIdx = 1;\n\n const placeholders = records\n .map((record) => {\n const rowPlaceholders = keys.map((key) => {\n const value = record[key];\n\n if (value === null) {\n return 'NULL';\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference on parameters\n values.push(value);\n return `CAST($${paramIdx++} AS TEXT)`;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n values.push(value.toISOString());\n return `CAST($${paramIdx++} AS TIMESTAMP)`;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else {\n // Direct parameter binding for other values\n values.push(value);\n return `$${paramIdx++}`;\n }\n });\n return `(${rowPlaceholders.join(', ')})`;\n })\n .join(', ');\n\n const sql = `INSERT INTO ${tableName} (${keys.join(', ')}) VALUES ${placeholders}`;\n\n await connection.run(sql, values);\n}\n\n/**\n * Validates that a table name is valid (alphanumeric + underscores only)\n *\n * @param table - Table name to validate\n * @throws DatabaseError if table name is invalid\n */\nfunction validateTableName(table: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(table)) {\n throw new DatabaseError(`Invalid table name: ${table}`, { table });\n }\n}\n\n/**\n * Creates a JSON database adapter using DuckDB in-memory engine\n *\n * This adapter provides SQL query capabilities over JSON files without creating\n * persistent database files or WAL files. All data is stored in-memory during\n * runtime and written back to JSON files based on the write strategy.\n *\n * @param options - JSON database options\n * @returns Database interface for JSON files\n */\nexport async function getDatabase(\n options: JSONOptions,\n): Promise<DatabaseInterface> {\n // Generate cache key from URL and options that affect database behavior\n // FIX for issues #533/#534: Auto-generate dbid from URL when schemas provided\n // This ensures connection caching ALWAYS happens for the same URL, preventing\n // the lost update bug where multiple connections overwrite each other's data.\n //\n // Priority:\n // 1. Explicit dbid from caller\n // 2. Auto-generated from URL + writeStrategy (ensures caching)\n const cacheKey =\n options.dbid ||\n `json:${options.url}:${options.writeStrategy || 'immediate'}:${options.autoRegister !== false}`;\n\n // If clearCache option is true, clear any cached connection for this key\n if (options.clearCache) {\n memoryConnectionCache.delete(cacheKey);\n pendingConnections.delete(cacheKey);\n }\n\n // Check if we have a cached connection for this cache key\n const cached = memoryConnectionCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // Check if there's a pending connection for this cache key\n const pending = pendingConnections.get(cacheKey);\n if (pending) {\n return pending;\n }\n\n // Create a new connection promise\n const connectionPromise = (async () => {\n const { connection, pendingJSONFiles, inferredSchemaTables } =\n await createJSONConnection(options);\n const writeStrategy = options.writeStrategy || 'immediate';\n const { url } = options;\n\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n * @throws Error if the insert operation fails\n */\n const insert = async (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot insert: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n const records = Array.isArray(data) ? data : [data];\n\n if (records.length === 0) {\n return { operation: 'insert', affected: 0 };\n }\n\n const keys = Object.keys(records[0]);\n\n // Build placeholders with CAST for empty strings\n const values: any[] = [];\n let paramIdx = 1;\n\n const placeholders = records\n .map((record) => {\n const rowPlaceholders = keys.map((key) => {\n const value = record[key];\n\n if (value === null) {\n return 'NULL';\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference\n values.push(value);\n return `CAST($${paramIdx++} AS TEXT)`;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB (issue #319)\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n values.push(value.toISOString());\n return `CAST($${paramIdx++} AS TIMESTAMP)`;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n // DuckDB cannot infer array element types from empty arrays or mixed types\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n // Only applies to plain objects (not class instances)\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx++} AS JSON)`;\n } else {\n // Direct parameter binding for other values\n values.push(value);\n return `$${paramIdx++}`;\n }\n });\n return `(${rowPlaceholders.join(', ')})`;\n })\n .join(', ');\n\n const sql = `INSERT INTO \"${table}\" (${keys.join(', ')}) VALUES ${placeholders}`;\n\n try {\n await connection.run(sql, values);\n const affected = records.length;\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'insert', affected };\n } catch (e) {\n throw new DatabaseError('Failed to insert records into table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to matching record or null if not found\n * @throws Error if the query fails\n */\n const get = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any> | null> => {\n validateTableName(table);\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `SELECT * FROM \"${table}\" ${whereClause} LIMIT 1`;\n\n try {\n const reader = await connection.runAndReadAll(sql, values);\n const rows = reader.getRowObjects();\n return rows.length > 0 ? convertBigInts(rows[0]) : null;\n } catch (e) {\n throw new DatabaseError('Failed to retrieve record from table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to array of matching records\n * @throws Error if the query fails\n */\n const list = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any>[]> => {\n validateTableName(table);\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `SELECT * FROM \"${table}\" ${whereClause}`;\n\n try {\n const reader = await connection.runAndReadAll(sql, values);\n return convertBigInts(reader.getRowObjects());\n } catch (e) {\n throw new DatabaseError('Failed to list records from table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update\n * @param data - New data to set\n * @returns Promise resolving to operation result\n * @throws Error if the update operation fails\n */\n const update = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot update: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n const keys = Object.keys(data);\n const setClause = keys\n .map((key, idx) => `${key} = $${idx + 1}`)\n .join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n keys.length + 1,\n 'json',\n );\n\n // Convert Date objects to ISO strings for DuckDB (issue #319)\n const dataValues = Object.values(data).map((value) =>\n value instanceof Date ? value.toISOString() : value,\n );\n\n const sql = `UPDATE \"${table}\" SET ${setClause} ${whereClause}`;\n const values = [...dataValues, ...whereValues];\n\n try {\n await connection.run(sql, values);\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n // DuckDB doesn't return rowsAffected in the same way, estimate from where clause\n return { operation: 'update', affected: 1 };\n } catch (e) {\n throw new DatabaseError('Failed to update records in table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n const buildJSONValueExpression = (\n value: any,\n values: any[],\n paramIdx: { value: number },\n ): string => {\n if (value === null) {\n return 'NULL';\n }\n if (value === '' && typeof value === 'string') {\n values.push(value);\n return `CAST($${paramIdx.value++} AS TEXT)`;\n }\n if (value instanceof Date) {\n values.push(value.toISOString());\n return `CAST($${paramIdx.value++} AS TIMESTAMP)`;\n }\n if (Array.isArray(value)) {\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx.value++} AS JSON)`;\n }\n if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n values.push(JSON.stringify(value));\n return `CAST($${paramIdx.value++} AS JSON)`;\n }\n\n values.push(value);\n return `$${paramIdx.value++}`;\n };\n\n const executeNullAwareJSONUpsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n ): Promise<QueryResult> => {\n const conflictWhere = Object.fromEntries(\n conflictColumns.map((col) => [col, data[col]]),\n );\n const existing = await get(table, conflictWhere);\n\n if (!existing) {\n return insert(table, data);\n }\n\n const keys = Object.keys(data);\n const values: any[] = [];\n const paramIdx = { value: 1 };\n const assignments = keys.map((key) => {\n const valueExpr = buildJSONValueExpression(data[key], values, paramIdx);\n return `\"${key}\" = ${valueExpr}`;\n });\n const { sql: whereClause, values: whereValues } = buildWhere(\n conflictWhere,\n paramIdx.value,\n 'json',\n );\n const sql = `UPDATE \"${table}\" SET ${assignments.join(', ')} ${whereClause}`;\n\n try {\n await connection.run(sql, [...values, ...whereValues]);\n\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'upsert', affected: 1 };\n } catch (e) {\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n sql,\n values: [...values, ...whereValues],\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n * @throws Error if the upsert operation fails\n */\n const upsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot upsert: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n // Validate that all conflict columns are present in the data\n const missingColumns = conflictColumns.filter((col) => !(col in data));\n\n if (missingColumns.length > 0) {\n throw new DatabaseError('Conflict columns missing from data', {\n table,\n conflictColumns,\n missingColumns,\n availableColumns: Object.keys(data),\n hint: 'All columns specified in ON CONFLICT must be present in the data being inserted. Undefined values should be replaced with null or an appropriate default.',\n });\n }\n\n if (\n !options?.nullsDistinct &&\n conflictColumns.some((col) => data[col] === null)\n ) {\n return executeNullAwareJSONUpsert(table, conflictColumns, data);\n }\n\n const keys = Object.keys(data);\n const dataValues = Object.values(data);\n\n // Build placeholders - schema has NOT NULL DEFAULT '' to prevent ANY type\n const placeholders: string[] = [];\n const values: any[] = [];\n let paramIdx = 1;\n\n for (const value of dataValues) {\n if (value === null) {\n placeholders.push('NULL');\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference on parameters\n placeholders.push(`CAST($${paramIdx} AS TEXT)`);\n values.push(value);\n paramIdx++;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n placeholders.push(`CAST($${paramIdx} AS TIMESTAMP)`);\n values.push(value.toISOString());\n paramIdx++;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n // DuckDB cannot infer array element types from empty arrays or mixed types\n placeholders.push(`CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n // Only applies to plain objects (not class instances)\n placeholders.push(`CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else {\n // Direct parameter binding for other values\n placeholders.push(`$${paramIdx}`);\n values.push(value);\n paramIdx++;\n }\n }\n\n // Build UPDATE SET clause with same approach\n // DO NOT reset paramIdx - parameters must be unique across entire query\n const updateSetParts: string[] = [];\n\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n const value = dataValues[i];\n\n if (value === null) {\n updateSetParts.push(`${key} = NULL`);\n } else if (value === '' && typeof value === 'string') {\n // CAST empty strings to TEXT to prevent DuckDB ANY type inference on parameters\n updateSetParts.push(`${key} = CAST($${paramIdx} AS TEXT)`);\n values.push(value);\n paramIdx++;\n } else if (value instanceof Date) {\n // Convert Date objects to ISO strings for DuckDB\n // CAST to TIMESTAMP to prevent DuckDB ANY type inference (issue #540)\n updateSetParts.push(`${key} = CAST($${paramIdx} AS TIMESTAMP)`);\n values.push(value.toISOString());\n paramIdx++;\n } else if (Array.isArray(value)) {\n // CAST arrays to JSON to prevent DuckDB ANY type inference\n updateSetParts.push(`${key} = CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else if (\n typeof value === 'object' &&\n value !== null &&\n Object.getPrototypeOf(value) === Object.prototype\n ) {\n // CAST plain objects to JSON to prevent DuckDB ANY type inference\n updateSetParts.push(`${key} = CAST($${paramIdx} AS JSON)`);\n values.push(JSON.stringify(value));\n paramIdx++;\n } else {\n // Direct parameter binding for other values\n updateSetParts.push(`${key} = $${paramIdx}`);\n values.push(value);\n paramIdx++;\n }\n }\n\n // Quote ALL column names to match DuckDB's schema generation\n // SchemaGenerator always quotes column names, so UPSERT must match\n const conflict = conflictColumns.map((col) => `\"${col}\"`).join(', ');\n const quotedKeys = keys.map((key) => `\"${key}\"`).join(', ');\n\n // Quote column names in UPDATE SET clause to match schema and ON CONFLICT\n // Extract the value expression from each updateSetPart (everything after '=')\n const quotedUpdateSetParts = keys.map((key, i) => {\n const part = updateSetParts[i];\n const valueExpr = part.substring(part.indexOf('=') + 1).trim();\n return `\"${key}\" = ${valueExpr}`;\n });\n\n const sql = `INSERT INTO \"${table}\" (${quotedKeys}) VALUES (${placeholders.join(', ')}) ON CONFLICT(${conflict}) DO UPDATE SET ${quotedUpdateSetParts.join(', ')}`;\n\n try {\n await connection.run(sql, values);\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'upsert', affected: 1 };\n } catch (e) {\n // Log detailed error information for debugging\n console.error('UPSERT failed:', {\n table,\n sql,\n values,\n valueTypes: values.map((v) => `${typeof v} (${v})`),\n conflictColumns,\n error: formatDbError(e),\n });\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n sql,\n values,\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record\n * @param data - Data to insert if no record found\n * @returns Promise resolving to the record (either retrieved or newly inserted)\n * @throws Error if the operation fails\n */\n const getOrInsert = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<Record<string, any>> => {\n const result = await get(table, where);\n if (result) return result;\n\n await insert(table, data);\n const inserted = await get(table, where);\n\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n\n return inserted;\n };\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion\n * @returns Promise resolving to operation result with count of deleted rows\n * @throws Error if the delete operation fails\n */\n const deleteRecords = async (\n table: string,\n where: Record<string, any>,\n ): Promise<QueryResult> => {\n validateTableName(table);\n\n // Enforce read-only mode\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot delete: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `DELETE FROM \"${table}\" ${whereClause}`;\n\n try {\n await connection.run(sql, values);\n\n // Handle write-back strategy\n if (writeStrategy === 'immediate') {\n await exportTableToJSON(connection, table, url);\n }\n\n return { operation: 'delete', affected: 1 };\n } catch (e) {\n throw new DatabaseError('Failed to delete records from table', {\n table,\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted)\n * @returns Promise resolving to count of matching records\n * @throws Error if the count operation fails\n */\n const count = async (\n table: string,\n where?: Record<string, any>,\n ): Promise<number> => {\n validateTableName(table);\n\n try {\n if (!where || Object.keys(where).length === 0) {\n // Count all records\n const result = await connection.runAndReadAll(\n `SELECT COUNT(*) as count FROM \"${table}\"`,\n );\n const rows = result.getRowObjects();\n return Number(rows[0]?.count) || 0;\n }\n\n // Count with conditions\n const { sql: whereClause, values } = buildWhere(where, 1, 'json');\n const sql = `SELECT COUNT(*) as count FROM \"${table}\" ${whereClause}`;\n\n const result = await connection.runAndReadAll(sql, values);\n const rows = result.getRowObjects();\n\n return Number(rows[0]?.count) || 0;\n } catch (e) {\n throw new DatabaseError('Failed to count records in table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Checks if a table exists in the database\n *\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\n const tableExists = async (tableName: string): Promise<boolean> => {\n try {\n // Try to query the table\n await connection.runAndReadAll(`SELECT * FROM ${tableName} LIMIT 1`);\n return true;\n } catch {\n return false;\n }\n };\n\n /**\n * Exports a table to JSON and schema files\n *\n * Exports two files:\n * 1. {table}.json - Table data with columns cast appropriately\n * 2. {table}.schema.sql - CREATE TABLE statement to preserve constraints\n *\n * Note: JSON columns are NOT cast to TEXT to preserve object structure.\n * Other columns are cast to TEXT to prevent DuckDB from converting UUIDs\n * and other TEXT values to hugeint representation in JSON output.\n *\n * @param connection - DuckDB connection\n * @param table - Table name\n * @param dataDir - Directory to write files\n */\n const exportTableToJSON = async (\n connection: any,\n table: string,\n dataDir: string,\n ): Promise<void> => {\n const filePath = join(dataDir, `${table}.json`);\n const schemaPath = join(dataDir, `${table}.schema.sql`);\n\n // Export schema first using SHOW CREATE TABLE\n try {\n const schemaResult = await connection.runAndReadAll(\n `SELECT sql FROM sqlite_master WHERE type='table' AND name='${table}'`,\n );\n const rows = schemaResult.getRowObjects();\n if (rows.length > 0 && rows[0].sql) {\n const { writeFile } = await import('node:fs/promises');\n await writeFile(schemaPath, rows[0].sql, 'utf-8');\n }\n } catch (error) {\n console.warn(\n `[json-adapter] Could not export schema for ${table}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n // Get column names and types to handle JSON columns specially\n // JSON columns should NOT be cast to TEXT to preserve object structure (fixes #542)\n const columnsResult = await connection.runAndReadAll(\n `SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '${table}' ORDER BY ordinal_position`,\n );\n const columnInfo = columnsResult.getRowObjects() as {\n column_name: string;\n data_type: string;\n }[];\n\n if (columnInfo.length === 0) {\n // Fallback to SELECT * if we can't get column names\n await connection.run(\n `COPY (SELECT * FROM \"${table}\") TO '${filePath}' (FORMAT JSON, ARRAY true)`,\n );\n return;\n }\n\n // Preserve type-appropriate columns, only cast text-based columns to TEXT\n // - JSON/STRUCT: preserve as-is for object structure (fixes #542)\n // - Numeric types: preserve as-is so numbers export as numbers (fixes #694)\n // - Boolean: preserve as-is\n // - Text-based: cast to TEXT to prevent DuckDB hugeint conversion for UUIDs\n const selectList = columnInfo\n .map(({ column_name, data_type }) => {\n const upperType = data_type.toUpperCase();\n // Preserve JSON/STRUCT as-is for object structure\n if (upperType === 'JSON' || upperType.startsWith('STRUCT')) {\n return `\"${column_name}\"`;\n }\n // Preserve numeric types as-is so they export as numbers, not strings\n if (\n [\n 'DOUBLE',\n 'REAL',\n 'FLOAT',\n 'INTEGER',\n 'BIGINT',\n 'SMALLINT',\n 'TINYINT',\n 'DECIMAL',\n 'NUMERIC',\n 'HUGEINT',\n 'UBIGINT',\n 'UINTEGER',\n 'USMALLINT',\n 'UTINYINT',\n ].some((t) => upperType.includes(t))\n ) {\n return `\"${column_name}\"`;\n }\n // Preserve boolean types as-is\n if (upperType === 'BOOLEAN' || upperType === 'BOOL') {\n return `\"${column_name}\"`;\n }\n // Cast text-based columns to TEXT to prevent hugeint conversion for UUIDs\n return `CAST(\"${column_name}\" AS TEXT) AS \"${column_name}\"`;\n })\n .join(', ');\n const sql = `COPY (SELECT ${selectList} FROM \"${table}\") TO '${filePath}' (FORMAT JSON, ARRAY true)`;\n\n await connection.run(sql);\n };\n\n /**\n * Manual export method for 'manual' write strategy\n *\n * Allows explicit control over when tables are written back to JSON files.\n *\n * @param table - Table name to export\n * @returns Promise that resolves when export completes\n */\n const exportTable = async (table: string): Promise<void> => {\n if (writeStrategy === 'none') {\n throw new DatabaseError(\n 'Cannot export table: write strategy is set to none (read-only mode)',\n { table, writeStrategy },\n );\n }\n await exportTableToJSON(connection, table, url);\n };\n\n /**\n * Creates a table by inferring schema from a JSON file\n *\n * This utility is for users who want automatic schema inference from JSON.\n * Note: Inferred schemas do NOT include UNIQUE constraints, so UPSERT\n * operations will fail. Use syncSchema() with explicit DDL for UPSERT support.\n *\n * @param tableName - Name of the table to create\n * @param jsonPath - Optional path to JSON file (defaults to {dataDir}/{tableName}.json)\n * @returns Promise that resolves when table is created\n * @throws Error if JSON file doesn't exist or table creation fails\n */\n const inferSchemaFromJSON = async (\n tableName: string,\n jsonPath?: string,\n ): Promise<void> => {\n validateTableName(tableName);\n\n const filePath = jsonPath || join(url, `${tableName}.json`);\n\n try {\n // Check if file exists\n const { access } = await import('node:fs/promises');\n const { constants } = await import('node:fs');\n await access(filePath, constants.F_OK);\n\n // Use DuckDB's read_json_auto to infer types and create table\n console.log(\n `[json-adapter] Inferring schema for ${tableName} from JSON file`,\n );\n await connection.run(\n `CREATE TABLE \"${tableName}\" AS SELECT * FROM read_json_auto('${filePath}')`,\n );\n\n // Remove from pending files if it was deferred\n pendingJSONFiles.delete(tableName);\n\n console.log(\n `[json-adapter] Created ${tableName} with inferred schema (no UNIQUE constraints)`,\n );\n } catch (error) {\n throw new DatabaseError(\n `Failed to infer schema from JSON for table ${tableName}`,\n {\n tableName,\n jsonPath: filePath,\n originalError:\n error instanceof Error ? error.message : String(error),\n },\n );\n }\n };\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param tableName - Table name\n * @returns TableInterface for the specified table\n */\n const table = (tableName: string): TableInterface => ({\n insert: (data) => insert(tableName, data),\n get: (where) => get(tableName, where),\n list: (where) => list(tableName, where),\n });\n\n /**\n * Parses a tagged template literal into a SQL query and values\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Object with SQL query and values array\n */\n const parseTemplate = (strings: TemplateStringsArray, ...vars: any[]) => {\n let sql = strings[0];\n const values = [];\n for (let i = 0; i < vars.length; i++) {\n values.push(vars[i]);\n sql += `$${i + 1}${strings[i + 1]}`;\n }\n return { sql, values };\n };\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n * @throws Error if the query fails\n */\n const many = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any>[]> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const reader = await connection.runAndReadAll(sql, values);\n return convertBigInts(reader.getRowObjects());\n } catch (e) {\n throw new DatabaseError('Failed to execute many query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n * @throws Error if the query fails\n */\n const single = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any> | null> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const reader = await connection.runAndReadAll(sql, values);\n const rows = reader.getRowObjects();\n return rows[0] ? convertBigInts(rows[0]) : null;\n } catch (e) {\n throw new DatabaseError('Failed to execute single query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n * @throws Error if the query fails\n */\n const pluck = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<any> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const reader = await connection.runAndReadAll(sql, values);\n const rows = reader.getRowObjects();\n if (rows.length === 0) return null;\n const firstRow = rows[0];\n const firstKey = Object.keys(firstRow)[0];\n return convertBigInts(firstRow[firstKey]);\n } catch (e) {\n throw new DatabaseError('Failed to execute pluck query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n * @throws Error if the query fails\n */\n const execute = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<void> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n await connection.run(sql, values);\n\n // Detect CREATE TABLE statements\n const createTableMatch = sql.match(\n /CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?[\"']?(\\w+)[\"']?/i,\n );\n if (createTableMatch) {\n const tableName = createTableMatch[1];\n\n // Check if there's pending JSON data for this table (deferred loading)\n const pendingFile = pendingJSONFiles.get(tableName);\n if (pendingFile) {\n // Table was just created by DDL - now load the JSON data\n await loadJSONData(connection, tableName, pendingFile);\n pendingJSONFiles.delete(tableName);\n } else if (writeStrategy !== 'none') {\n // No pending data - export empty table (preserves SMRT system tables)\n try {\n const { access } = await import('node:fs/promises');\n const jsonFilePath = join(url, `${tableName}.json`);\n try {\n await access(jsonFilePath);\n // File exists, don't overwrite\n } catch {\n // File doesn't exist, export empty table\n await exportTableToJSON(connection, tableName, url);\n }\n } catch (error) {\n console.warn(\n `[json-adapter] Could not export newly created table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n } catch (e) {\n throw new DatabaseError('Failed to execute query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * @param str - SQL query string\n * @param values - Variables to use as parameters\n * @returns Promise resolving to query result with rows and metadata\n * @throws Error if the query fails\n */\n const query = async (str: string, ...values: any[]) => {\n const sql = str;\n const args = Array.isArray(values[0]) ? values[0] : values;\n\n try {\n const reader = await connection.runAndReadAll(sql, args);\n const rows = convertBigInts(reader.getRowObjects());\n\n return {\n command: sql.split(' ')[0].toUpperCase(),\n rowCount: rows.length,\n oid: null,\n fields:\n rows.length > 0\n ? Object.keys(rows[0]).map((name) => ({\n name,\n tableID: 0,\n columnID: 0,\n dataTypeID: 0,\n dataTypeSize: -1,\n dataTypeModifier: -1,\n format: 'text',\n }))\n : [],\n rows,\n };\n } catch (e) {\n throw new DatabaseError('Failed to execute raw query', {\n sql,\n args,\n originalError: formatDbError(e),\n });\n }\n };\n\n // Shorthand aliases for query methods\n const oo = many; // (o)bjective-(o)bjects: returns multiple rows\n const oO = single; // (o)bjective-(O)bject: returns a single row\n const ox = pluck; // (o)bjective-(x): returns a single value\n const xx = execute; // e(x)ecute-e(x)ecute: executes without returning\n\n /**\n * Synchronizes database schema with provided SQL DDL\n *\n * Filters out CREATE TRIGGER statements since triggers are not supported\n * in the JSON adapter (timestamps managed at application level).\n *\n * @param schema - SQL schema definition with CREATE TABLE statements\n * @returns Promise that resolves when schema is synchronized\n */\n const syncSchema = async (schema: string): Promise<void> => {\n const statements = schema\n .trim()\n .split(';')\n .filter((stmt) => stmt.trim() !== '');\n\n const createTableStatements: string[] = [];\n const indexStatements: string[] = [];\n const otherStatements: string[] = [];\n\n // Separate CREATE TABLE, CREATE INDEX, and other statements\n for (const stmt of statements) {\n const trimmed = stmt.trim();\n if (!trimmed) continue;\n\n const upperTrimmed = trimmed.toUpperCase();\n\n // Skip trigger creation - not supported in JSON adapter\n if (upperTrimmed.startsWith('CREATE TRIGGER')) {\n console.warn(\n '[json-adapter] Skipping trigger creation - timestamps managed at application level',\n );\n continue;\n }\n\n if (\n upperTrimmed.startsWith('CREATE INDEX') ||\n upperTrimmed.startsWith('CREATE UNIQUE INDEX')\n ) {\n indexStatements.push(trimmed);\n } else if (upperTrimmed.startsWith('CREATE TABLE')) {\n createTableStatements.push(trimmed);\n } else {\n otherStatements.push(trimmed);\n }\n }\n\n // Process each CREATE TABLE statement\n for (const ddl of createTableStatements) {\n // Transform UNIQUE indexes to inline constraints for DuckDB compatibility\n const { ddl: transformedDDL, indexes: remainingIndexes } =\n convertUniqueIndexesToInlineConstraints(ddl, indexStatements);\n\n // Extract table name from DDL before executing\n const createTableMatch = transformedDDL.match(\n /CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?[\"']?(\\w+)[\"']?/i,\n );\n const tableName = createTableMatch ? createTableMatch[1] : null;\n\n // If table was created with inferred schema, drop it first\n // (proper schema with UNIQUE constraints takes precedence)\n if (tableName && inferredSchemaTables.has(tableName)) {\n try {\n await connection.run(`DROP TABLE IF EXISTS \"${tableName}\"`);\n inferredSchemaTables.delete(tableName);\n console.log(\n `[json-adapter] Dropped inferred-schema table ${tableName} for schema upgrade`,\n );\n } catch (error) {\n console.warn(\n `[json-adapter] Could not drop inferred-schema table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Execute transformed DDL\n try {\n await connection.run(transformedDDL);\n\n if (tableName) {\n // Check if there's pending JSON data for this table (deferred loading)\n const pendingFile = pendingJSONFiles.get(tableName);\n if (pendingFile) {\n // Table was just created by DDL - now load the JSON data\n await loadJSONData(connection, tableName, pendingFile);\n pendingJSONFiles.delete(tableName);\n } else if (writeStrategy !== 'none') {\n // No pending data - export empty table (preserves SMRT system tables)\n try {\n // Only export if JSON file doesn't already exist\n // This prevents overwriting existing data when tables are manually created\n const { access } = await import('node:fs/promises');\n const jsonFilePath = join(url, `${tableName}.json`);\n try {\n await access(jsonFilePath);\n // File exists, don't overwrite\n } catch {\n // File doesn't exist, export empty table\n await exportTableToJSON(connection, tableName, url);\n }\n } catch (error) {\n console.warn(\n `[json-adapter] Could not export newly created table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n } catch (e) {\n console.error('Schema sync error (CREATE TABLE):', e);\n }\n\n // Execute remaining (non-UNIQUE) indexes for this table\n for (const indexSQL of remainingIndexes) {\n try {\n await connection.run(indexSQL);\n } catch (e) {\n console.error('Schema sync error (CREATE INDEX):', e);\n }\n }\n }\n\n // Execute other statements\n for (const stmt of otherStatements) {\n try {\n await connection.run(stmt);\n } catch (e) {\n console.error('Schema sync error:', e);\n }\n }\n };\n\n /**\n * Initialize database schemas from JSON manifest\n * Supports dependency resolution and schema overrides\n *\n * @param options - Schema initialization options\n * @returns Promise that resolves when schemas are initialized\n */\n const initializeSchemas = async (\n options: SchemaInitializationOptions,\n ): Promise<void> => {\n const schemaManager = new DatabaseSchemaManager();\n const currentDb: DatabaseInterface = {\n url,\n client: connection,\n query,\n insert,\n update,\n upsert,\n get,\n list,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n tableExists,\n many,\n single,\n pluck,\n execute,\n oo,\n oO,\n ox,\n xx,\n syncSchema,\n };\n\n await schemaManager.initializeSchemas(currentDb, options);\n };\n\n /**\n * Executes a callback within a database transaction\n * Automatically commits on success or rolls back on error\n *\n * @param callback - Function to execute within transaction\n * @returns Promise resolving to callback result\n */\n const transaction = async <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ): Promise<T> => {\n try {\n await connection.run('BEGIN TRANSACTION');\n\n // Create a transaction-scoped database interface\n const txDb: DatabaseInterface = {\n url,\n client: connection,\n insert,\n get,\n list,\n update,\n upsert,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n transaction,\n };\n\n const result = await callback(txDb);\n await connection.run('COMMIT');\n return result;\n } catch (error) {\n await connection.run('ROLLBACK');\n throw error;\n }\n };\n\n /**\n * Begins a new transaction and returns a handle for manual control\n *\n * Unlike transaction(), this gives you explicit control over commit/rollback.\n * Ideal for test isolation where you want to rollback after each test.\n *\n * @returns Promise resolving to a TransactionHandle\n */\n const beginTransaction = async (): Promise<TransactionHandle> => {\n await connection.run('BEGIN TRANSACTION');\n\n let active = true;\n\n const commit = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await connection.run('COMMIT');\n active = false;\n };\n\n const rollback = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await connection.run('ROLLBACK');\n active = false;\n };\n\n const isActive = (): boolean => active;\n\n // Create a transaction-scoped database interface with commit/rollback\n const txHandle: TransactionHandle = {\n url,\n client: connection,\n insert,\n get,\n list,\n update,\n upsert,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n transaction,\n commit,\n rollback,\n isActive,\n };\n\n return txHandle;\n };\n\n return {\n url,\n requiresSchemaCheck: true,\n client: connection,\n query,\n insert,\n update,\n upsert,\n get,\n list,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n tableExists,\n many,\n single,\n pluck,\n execute,\n oo,\n oO,\n ox,\n xx,\n syncSchema,\n initializeSchemas,\n transaction,\n beginTransaction,\n // JSON-specific methods\n exportTable,\n inferSchemaFromJSON,\n } as DatabaseInterface & {\n exportTable: (table: string) => Promise<void>;\n inferSchemaFromJSON: (\n tableName: string,\n jsonPath?: string,\n ) => Promise<void>;\n };\n })();\n\n // Store the pending connection promise for concurrent requests\n pendingConnections.set(cacheKey, connectionPromise);\n\n try {\n // Wait for the connection to be established\n const db = await connectionPromise;\n\n // Cache the connection for reuse\n memoryConnectionCache.set(cacheKey, db);\n\n return db;\n } finally {\n // Clean up pending connection promise\n pendingConnections.delete(cacheKey);\n }\n}\n","/**\n * Shared utilities for ALTER TABLE operations\n *\n * Provides database-agnostic utilities for generating ALTER TABLE statements,\n * handling column definitions, and creating indexes.\n */\n\nimport type { ColumnDefinitionWithName, IndexDefinition } from './types.js';\n\n/**\n * Database dialect type for SQL generation\n */\nexport type DatabaseDialect = 'sqlite' | 'postgres' | 'duckdb';\n\n/**\n * Generates an ALTER TABLE ADD COLUMN statement\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @param dialect - Database dialect\n * @returns SQL statement string\n *\n * @example\n * ```typescript\n * const sql = generateAddColumnStatement('users', {\n * name: 'email',\n * type: 'TEXT',\n * unique: true,\n * notNull: false\n * }, 'sqlite');\n * // Returns: \"ALTER TABLE users ADD COLUMN email TEXT UNIQUE\"\n * ```\n */\nexport function generateAddColumnStatement(\n table: string,\n column: ColumnDefinitionWithName,\n _dialect: DatabaseDialect,\n): string {\n const parts: string[] = [column.name, column.type];\n\n // Primary key\n if (column.primaryKey) {\n parts.push('PRIMARY KEY');\n }\n\n // NOT NULL constraint\n if (column.notNull) {\n parts.push('NOT NULL');\n }\n\n // UNIQUE constraint\n if (column.unique) {\n parts.push('UNIQUE');\n }\n\n // DEFAULT clause\n if (column.defaultValue !== undefined) {\n const defaultClause = generateDefaultClause(\n column.type,\n column.defaultValue,\n );\n parts.push(`DEFAULT ${defaultClause}`);\n }\n\n // CHECK constraint\n if (column.check) {\n parts.push(`CHECK (${column.check})`);\n }\n\n // Foreign key (inline for some databases)\n if (column.foreignKey) {\n const fk = column.foreignKey;\n const fkParts = [`REFERENCES ${fk.table}(${fk.column})`];\n\n if (fk.onDelete) {\n fkParts.push(`ON DELETE ${fk.onDelete}`);\n }\n\n if (fk.onUpdate) {\n fkParts.push(`ON UPDATE ${fk.onUpdate}`);\n }\n\n parts.push(fkParts.join(' '));\n }\n\n const columnDef = parts.join(' ');\n return `ALTER TABLE ${table} ADD COLUMN ${columnDef}`;\n}\n\n/**\n * Generates a DEFAULT clause for a column definition\n *\n * Handles proper formatting and escaping of default values based on column type.\n *\n * @param columnType - SQL column type (TEXT, INTEGER, BOOLEAN, etc.)\n * @param defaultValue - Default value to format\n * @returns Formatted default value string\n *\n * @example\n * ```typescript\n * generateDefaultClause('TEXT', 'hello'); // Returns: \"'hello'\"\n * generateDefaultClause('INTEGER', 42); // Returns: \"42\"\n * generateDefaultClause('BOOLEAN', true); // Returns: \"true\"\n * generateDefaultClause('TEXT', null); // Returns: \"NULL\"\n * ```\n */\nexport function generateDefaultClause(\n columnType: string,\n defaultValue: any,\n): string {\n if (defaultValue === null) {\n return 'NULL';\n }\n\n const typeUpper = columnType.toUpperCase();\n\n // String types - need quotes\n if (\n typeUpper.includes('TEXT') ||\n typeUpper.includes('CHAR') ||\n typeUpper.includes('VARCHAR') ||\n typeUpper.includes('STRING')\n ) {\n // Handle empty strings\n if (defaultValue === '') {\n return \"''\";\n }\n // Escape single quotes\n const escaped = String(defaultValue).replace(/'/g, \"''\");\n return `'${escaped}'`;\n }\n\n // Boolean types\n if (typeUpper.includes('BOOL')) {\n return defaultValue ? 'true' : 'false';\n }\n\n // Numeric types - no quotes\n if (\n typeUpper.includes('INT') ||\n typeUpper.includes('REAL') ||\n typeUpper.includes('FLOAT') ||\n typeUpper.includes('DOUBLE') ||\n typeUpper.includes('NUMERIC') ||\n typeUpper.includes('DECIMAL')\n ) {\n return String(defaultValue);\n }\n\n // JSON types\n if (typeUpper.includes('JSON')) {\n if (typeof defaultValue === 'string') {\n return `'${defaultValue.replace(/'/g, \"''\")}'`;\n }\n return `'${JSON.stringify(defaultValue).replace(/'/g, \"''\")}'`;\n }\n\n // Date/timestamp types\n if (\n typeUpper.includes('DATE') ||\n typeUpper.includes('TIME') ||\n typeUpper.includes('TIMESTAMP')\n ) {\n if (defaultValue instanceof Date) {\n return `'${defaultValue.toISOString()}'`;\n }\n return `'${String(defaultValue).replace(/'/g, \"''\")}'`;\n }\n\n // Default: treat as string\n if (typeof defaultValue === 'string') {\n return `'${defaultValue.replace(/'/g, \"''\")}'`;\n }\n\n return String(defaultValue);\n}\n\n/**\n * Generates a CREATE INDEX statement\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns SQL CREATE INDEX statement\n *\n * @example\n * ```typescript\n * const sql = generateCreateIndexStatement('users', {\n * name: 'idx_users_email',\n * columns: ['email'],\n * unique: true\n * });\n * // Returns: \"CREATE UNIQUE INDEX idx_users_email ON users (email)\"\n * ```\n */\nexport function generateCreateIndexStatement(\n table: string,\n index: IndexDefinition,\n): string {\n const parts: string[] = ['CREATE'];\n\n // UNIQUE modifier\n if (index.unique) {\n parts.push('UNIQUE');\n }\n\n parts.push('INDEX');\n\n // Index name\n parts.push(index.name);\n\n // ON table\n parts.push(`ON ${table}`);\n\n // Column list\n const columns = index.columns.join(', ');\n parts.push(`(${columns})`);\n\n // WHERE clause (partial index)\n if (index.where) {\n parts.push(`WHERE ${index.where}`);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Validates a table name to prevent SQL injection\n *\n * @param tableName - Table name to validate\n * @throws Error if table name contains invalid characters\n */\nexport function validateTableName(tableName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {\n throw new Error(\n `Invalid table name: ${tableName}. Table names must start with a letter or underscore and contain only alphanumeric characters and underscores.`,\n );\n }\n}\n\n/**\n * Validates a column name to prevent SQL injection\n *\n * @param columnName - Column name to validate\n * @throws Error if column name contains invalid characters\n */\nexport function validateColumnName(columnName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(columnName)) {\n throw new Error(\n `Invalid column name: ${columnName}. Column names must start with a letter or underscore and contain only alphanumeric characters and underscores.`,\n );\n }\n}\n\n/**\n * Validates an index name to prevent SQL injection\n *\n * @param indexName - Index name to validate\n * @throws Error if index name contains invalid characters\n */\nexport function validateIndexName(indexName: string): void {\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(indexName)) {\n throw new Error(\n `Invalid index name: ${indexName}. Index names must start with a letter or underscore and contain only alphanumeric characters and underscores.`,\n );\n }\n}\n","import { DatabaseError, loadEnvConfig } from '@happyvertical/utils';\nimport { Pool } from 'pg';\nimport { DatabaseSchemaManager } from './schema-manager';\nimport {\n generateAddColumnStatement,\n generateCreateIndexStatement,\n validateColumnName,\n validateIndexName,\n validateTableName,\n} from './shared/alter-utils';\nimport type {\n QueryResult as BaseQueryResult,\n ColumnDefinition,\n ColumnDefinitionWithName,\n DatabaseInterface,\n IndexDefinition,\n SchemaInitializationOptions,\n SessionHandle,\n TableInterface,\n TableSchemaInfo,\n TransactionHandle,\n UpsertOptions,\n VectorCapabilities,\n VectorIndexOptions,\n VectorSearchOptions,\n VectorSearchResult,\n} from './shared/types';\nimport { buildWhere, formatDbError } from './shared/utils';\n\n/**\n * Configuration options for PostgreSQL database connections\n */\nexport interface PostgresOptions {\n /**\n * Connection URL for PostgreSQL\n */\n url?: string;\n\n /**\n * Database name\n */\n database?: string;\n\n /**\n * Database server hostname\n */\n host?: string;\n\n /**\n * Username for authentication\n */\n user?: string;\n\n /**\n * Password for authentication\n */\n password?: string;\n\n /**\n * Port number for the PostgreSQL server\n */\n port?: number;\n\n /**\n * Cache key for connection pooling.\n * If provided, the same dbid returns the same cached connection.\n * When omitted, a key is derived from the connection URL.\n */\n dbid?: string;\n\n /**\n * Maximum number of connections in the pool.\n * Defaults to 20. The pg library defaults to 10, which is too low\n * for applications with many SMRT collections.\n */\n max?: number;\n\n /**\n * Schema definitions for tables.\n * Accepts a record or a lazy function (see SchemasOption).\n *\n * **Postgres ignores this option** — tables are managed by migrations.\n * The option exists so callers can pass schemas uniformly to all adapters\n * without knowing the adapter type. Only JSON/DuckDB adapters resolve it.\n */\n schemas?: import('./shared/types').SchemasOption;\n}\n\n/**\n * Module-level cache for PostgreSQL connections.\n * Keyed by dbid (or derived from connection URL).\n * Prevents creating multiple pg.Pool instances for the same database.\n */\nconst connectionCache = new Map<string, DatabaseInterface>();\nconst pendingConnections = new Map<string, Promise<DatabaseInterface>>();\n\ntype PostgresQueryExecutor = {\n query: (\n sql: string,\n values?: any[],\n ) => Promise<{ rows: any[]; rowCount: number | null }>;\n};\n\n/**\n * Clears the PostgreSQL connection cache.\n * Useful for test isolation and reconnection scenarios.\n */\nexport function clearPostgresConnectionCache(): void {\n connectionCache.clear();\n pendingConnections.clear();\n}\n\n/**\n * Operator for the given distance metric in pgvector\n */\nfunction vectorOperator(metric: 'cosine' | 'l2' | 'ip'): string {\n switch (metric) {\n case 'cosine':\n return '<=>';\n case 'l2':\n return '<->';\n case 'ip':\n return '<#>';\n default:\n return '<=>';\n }\n}\n\nfunction getMaxPostgresParameterIndex(sql: string): number {\n let maxIndex = 0;\n for (const match of sql.matchAll(/\\$(\\d+)/g)) {\n const index = Number(match[1]);\n if (Number.isSafeInteger(index) && index > maxIndex) {\n maxIndex = index;\n }\n }\n return maxIndex;\n}\n\nfunction usesSingleArrayParameter(sql: string): boolean {\n const identifier = String.raw`(?:\"[^\"]+\"|[a-z_][\\w$]*)`;\n const qualifiedIdentifier = String.raw`${identifier}(?:\\s*\\.\\s*${identifier})?`;\n const arrayType = String.raw`${qualifiedIdentifier}(?:\\s*\\([^)]*\\))?\\s*\\[\\]`;\n\n return (\n new RegExp(String.raw`\\$1\\s*::\\s*${arrayType}`, 'i').test(sql) ||\n new RegExp(\n String.raw`\\bCAST\\s*\\(\\s*\\$1\\s+AS\\s+${arrayType}\\s*\\)`,\n 'i',\n ).test(sql) ||\n /\\b(?:ANY|ALL|SOME)\\s*\\(\\s*\\$1\\s*\\)/i.test(sql)\n );\n}\n\nfunction normalizeRawQueryValues(sql: string, values: any[]): any[] {\n if (values.length !== 1 || !Array.isArray(values[0])) {\n return values;\n }\n\n const valuesArray = values[0];\n const maxParameterIndex = getMaxPostgresParameterIndex(sql);\n\n if (maxParameterIndex === 1 && usesSingleArrayParameter(sql)) {\n return values;\n }\n\n if (maxParameterIndex === 0 || maxParameterIndex === valuesArray.length) {\n return valuesArray;\n }\n\n return values;\n}\n\nfunction rewriteQuestionMarkPlaceholders(sql: string): {\n sql: string;\n count: number;\n} {\n let output = '';\n let count = 0;\n let index = 0;\n\n const copyQuoted = (quote: \"'\" | '\"', escaped = false) => {\n output += quote;\n index += 1;\n\n while (index < sql.length) {\n const char = sql[index];\n output += char;\n index += 1;\n\n if (escaped && char === '\\\\' && index < sql.length) {\n output += sql[index];\n index += 1;\n continue;\n }\n\n if (char === quote) {\n if (sql[index] === quote) {\n output += sql[index];\n index += 1;\n continue;\n }\n break;\n }\n }\n };\n\n const copyUntil = (end: string) => {\n const endIndex = sql.indexOf(end, index + end.length);\n if (endIndex === -1) {\n output += sql.slice(index);\n index = sql.length;\n return;\n }\n\n output += sql.slice(index, endIndex + end.length);\n index = endIndex + end.length;\n };\n\n while (index < sql.length) {\n const char = sql[index];\n const next = sql[index + 1];\n\n if ((char === 'E' || char === 'e') && next === \"'\") {\n output += char;\n index += 1;\n copyQuoted(\"'\", true);\n continue;\n }\n\n if (char === \"'\") {\n copyQuoted(\"'\");\n continue;\n }\n\n if (char === '\"') {\n copyQuoted('\"');\n continue;\n }\n\n if (char === '-' && next === '-') {\n const endIndex = sql.indexOf('\\n', index + 2);\n if (endIndex === -1) {\n output += sql.slice(index);\n index = sql.length;\n } else {\n output += sql.slice(index, endIndex + 1);\n index = endIndex + 1;\n }\n continue;\n }\n\n if (char === '/' && next === '*') {\n copyUntil('*/');\n continue;\n }\n\n if (char === '$') {\n const tag = sql.slice(index).match(/^\\$[A-Za-z_][\\w$]*\\$|^\\$\\$/);\n if (tag) {\n copyUntil(tag[0]);\n continue;\n }\n }\n\n if (char === '?' && next !== '|' && next !== '&') {\n count += 1;\n output += `$${count}`;\n index += 1;\n continue;\n }\n\n output += char;\n index += 1;\n }\n\n return { sql: output, count };\n}\n\nfunction usesSingleQuestionArrayParameter(sql: string): boolean {\n const identifier = String.raw`(?:\"[^\"]+\"|[a-z_][\\w$]*)`;\n const qualifiedIdentifier = String.raw`${identifier}(?:\\s*\\.\\s*${identifier})?`;\n const arrayType = String.raw`${qualifiedIdentifier}(?:\\s*\\([^)]*\\))?\\s*\\[\\]`;\n\n return (\n new RegExp(String.raw`\\?\\s*::\\s*${arrayType}`, 'i').test(sql) ||\n new RegExp(String.raw`\\bCAST\\s*\\(\\s*\\?\\s+AS\\s+${arrayType}\\s*\\)`, 'i').test(\n sql,\n ) ||\n /\\b(?:ANY|ALL|SOME)\\s*\\(\\s*\\?\\s*\\)/i.test(sql)\n );\n}\n\nfunction normalizeQuestionMarkQueryValues(\n sql: string,\n values: any[],\n placeholderCount: number,\n): any[] {\n if (values.length !== 1 || !Array.isArray(values[0])) {\n return values;\n }\n\n if (placeholderCount === 1 && usesSingleQuestionArrayParameter(sql)) {\n return values;\n }\n\n if (placeholderCount === values[0].length) {\n return values[0];\n }\n\n return values;\n}\n\nfunction normalizePostgresRawQuery(\n sql: string,\n values: any[],\n): { sql: string; values: any[] } {\n if (getMaxPostgresParameterIndex(sql) > 0) {\n return { sql, values: normalizeRawQueryValues(sql, values) };\n }\n\n const rewritten = rewriteQuestionMarkPlaceholders(sql);\n const placeholderCount = rewritten.count;\n const queryValues = normalizeQuestionMarkQueryValues(\n sql,\n values,\n placeholderCount,\n );\n\n if (placeholderCount > 0 && placeholderCount === queryValues.length) {\n return {\n sql: rewritten.sql,\n values: queryValues,\n };\n }\n\n return { sql, values: normalizeRawQueryValues(sql, values) };\n}\n\n/**\n * pgvector index operator class for CREATE INDEX\n */\nfunction vectorOpsClass(metric: 'cosine' | 'l2' | 'ip'): string {\n switch (metric) {\n case 'cosine':\n return 'vector_cosine_ops';\n case 'l2':\n return 'vector_l2_ops';\n case 'ip':\n return 'vector_ip_ops';\n default:\n return 'vector_cosine_ops';\n }\n}\n\n/**\n * Convert a number[] to a pgvector literal string: '[0.1,0.2,0.3]'\n */\nfunction toVectorLiteral(embedding: number[]): string {\n if (embedding.length === 0) {\n throw new DatabaseError('Vector embedding must not be empty', {});\n }\n for (let i = 0; i < embedding.length; i++) {\n if (!Number.isFinite(embedding[i])) {\n throw new DatabaseError(\n 'Vector embedding contains invalid value (NaN or Infinity)',\n { index: i, value: embedding[i] },\n );\n }\n }\n return `[${embedding.join(',')}]`;\n}\n\n/**\n * Creates vector capabilities backed by pgvector for a PostgreSQL pool.\n *\n * @param pool - PostgreSQL connection pool\n * @returns VectorCapabilities implementation\n */\nfunction createVectorCapabilities(pool: Pool): VectorCapabilities {\n return {\n async ensureColumn(\n table: string,\n column: string,\n dimensions: number,\n ): Promise<void> {\n if (!Number.isInteger(dimensions) || dimensions <= 0) {\n throw new DatabaseError(\n 'Vector dimensions must be a positive integer',\n { dimensions },\n );\n }\n try {\n await pool.query('CREATE EXTENSION IF NOT EXISTS vector');\n await pool.query(\n `ALTER TABLE \"${table}\" ADD COLUMN IF NOT EXISTS \"${column}\" vector(${dimensions})`,\n );\n } catch (e) {\n throw new DatabaseError('Failed to ensure vector column', {\n table,\n column,\n dimensions,\n originalError: formatDbError(e),\n });\n }\n },\n\n async ensureIndex(\n table: string,\n column: string,\n options?: VectorIndexOptions,\n ): Promise<void> {\n const metric = options?.metric || 'cosine';\n const indexType = options?.type || 'hnsw';\n const opsClass = vectorOpsClass(metric);\n const indexName = `idx_${table}_${column}_${metric}_${indexType}`;\n\n try {\n await pool.query(\n `CREATE INDEX IF NOT EXISTS \"${indexName}\" ON \"${table}\" USING ${indexType} (\"${column}\" ${opsClass})`,\n );\n } catch (e) {\n throw new DatabaseError('Failed to ensure vector index', {\n table,\n column,\n indexName,\n originalError: formatDbError(e),\n });\n }\n },\n\n async upsertVector(\n table: string,\n where: Record<string, any>,\n column: string,\n embedding: number[],\n ): Promise<void> {\n const keys = Object.keys(where);\n const values = Object.values(where);\n const conditions = keys\n .map((key, i) => `\"${key}\" IS NOT DISTINCT FROM $${i + 1}`)\n .join(' AND ');\n const vectorParam = `$${values.length + 1}`;\n\n try {\n await pool.query(\n `UPDATE \"${table}\" SET \"${column}\" = ${vectorParam}::vector WHERE ${conditions}`,\n [...values, toVectorLiteral(embedding)],\n );\n } catch (e) {\n throw new DatabaseError('Failed to upsert vector', {\n table,\n column,\n where,\n originalError: formatDbError(e),\n });\n }\n },\n\n async search(\n table: string,\n column: string,\n embedding: number[],\n options?: VectorSearchOptions,\n ): Promise<VectorSearchResult[]> {\n const metric = options?.metric || 'cosine';\n const limit = options?.limit || 10;\n const op = vectorOperator(metric);\n\n // $1 is the query vector; user-provided WHERE params use $2, $3, etc.\n const queryParams: any[] = [toVectorLiteral(embedding)];\n\n let whereClause = `\"${column}\" IS NOT NULL`;\n if (options?.where) {\n whereClause += ` AND (${options.where})`;\n if (options.params) {\n queryParams.push(...options.params);\n }\n }\n\n const limitParam = `$${queryParams.length + 1}`;\n queryParams.push(limit);\n\n const sql = `SELECT *, (\"${column}\" ${op} $1::vector) AS distance FROM \"${table}\" WHERE ${whereClause} ORDER BY \"${column}\" ${op} $1::vector LIMIT ${limitParam}`;\n\n try {\n const result = await pool.query(sql, queryParams);\n\n return result.rows.map((row: Record<string, any>) => ({\n ...row,\n id: row.id as string,\n distance: Number.parseFloat(row.distance),\n }));\n } catch (e) {\n throw new DatabaseError('Failed to execute vector search', {\n table,\n column,\n metric,\n limit,\n originalError: formatDbError(e),\n });\n }\n },\n };\n}\n\n/**\n * Creates a PostgreSQL database adapter\n *\n * Loads configuration from environment variables with backward compatibility:\n * - First checks HAVE_SQL_* environment variables (new standard)\n * - Falls back to SQLOO_* environment variables (legacy)\n * - User-provided options always take precedence\n *\n * Environment variables:\n * - HAVE_SQL_URL / SQLOO_URL → Connection string (takes precedence)\n * - HAVE_SQL_DATABASE / SQLOO_DATABASE → Database name\n * - HAVE_SQL_HOST / SQLOO_HOST → Host (default: 'localhost')\n * - HAVE_SQL_USER / SQLOO_USER → Username\n * - HAVE_SQL_PASSWORD / SQLOO_PASSWORD → Password\n * - HAVE_SQL_PORT / SQLOO_PORT → Port (default: 5432)\n *\n * @param options - PostgreSQL connection options\n * @returns Database interface for PostgreSQL\n */\nexport async function getDatabase(\n options: PostgresOptions = {},\n): Promise<DatabaseInterface> {\n // --- Connection cache: return existing pool for same dbid/URL ---\n // Derive cache key from explicit dbid, options, or env vars so that\n // env-only callers also benefit from caching/deduplication.\n const envUrl = process.env.HAVE_SQL_URL || process.env.SQLOO_URL || null;\n const envDatabase =\n process.env.HAVE_SQL_DATABASE || process.env.SQLOO_DATABASE || null;\n const envHost =\n process.env.HAVE_SQL_HOST || process.env.SQLOO_HOST || 'localhost';\n const envUser = process.env.HAVE_SQL_USER || process.env.SQLOO_USER || '';\n const envPortRaw = process.env.HAVE_SQL_PORT || process.env.SQLOO_PORT;\n const envPort = envPortRaw ? Number(envPortRaw) || 5432 : 5432;\n\n const derivedHost = options.host || envHost;\n const derivedPort = options.port || envPort;\n const derivedDatabase = options.database || envDatabase;\n const derivedUser = options.user || envUser;\n\n const cacheKey =\n options.dbid ||\n options.url ||\n (derivedDatabase\n ? `pg:${derivedUser ? `${derivedUser}@` : ''}${derivedHost}:${derivedPort}/${derivedDatabase}`\n : envUrl || null);\n\n if (cacheKey) {\n const cached = connectionCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // Deduplicate concurrent calls for the same key\n const pending = pendingConnections.get(cacheKey);\n if (pending) return pending;\n }\n\n const connectionPromise = createDatabase(options, cacheKey);\n\n if (cacheKey) {\n pendingConnections.set(cacheKey, connectionPromise);\n connectionPromise.finally(() => {\n if (cacheKey) pendingConnections.delete(cacheKey);\n });\n }\n\n return connectionPromise;\n}\n\n/**\n * Internal: creates the actual database connection and caches it.\n */\nasync function createDatabase(\n options: PostgresOptions,\n cacheKey: string | null,\n): Promise<DatabaseInterface> {\n // Load HAVE_SQL_* environment variables first\n const config = loadEnvConfig(options, {\n packageName: 'sql',\n schema: {\n url: 'string',\n database: 'string',\n host: 'string',\n port: 'number',\n user: 'string',\n password: 'string',\n },\n });\n\n // For backward compatibility, fall back to SQLOO_* if HAVE_SQL_* not set\n // Only check legacy vars if the new ones aren't present\n if (!config.url && !config.host && !config.database && !config.user) {\n const legacyConfig = loadEnvConfig(\n {},\n {\n prefix: 'SQLOO',\n schema: {\n url: 'string',\n database: 'string',\n host: 'string',\n port: 'number',\n user: 'string',\n password: 'string',\n },\n },\n );\n\n // Merge legacy config, but don't override user options or HAVE_SQL_* vars\n for (const [key, value] of Object.entries(legacyConfig)) {\n if ((config as any)[key] === undefined && value !== undefined) {\n (config as any)[key] = value;\n }\n }\n }\n\n // Apply defaults\n const { database, host = 'localhost', user, password, port = 5432 } = config;\n\n // Construct url if not provided (for DatabaseInterface requirement)\n const url: string =\n (config.url as string) ||\n `postgresql://${user}${password ? `:${password}` : ''}@${host}:${port}/${database || 'postgres'}`;\n\n // Create a connection pool with explicit max to prevent exhaustion.\n // pg defaults to 10 which is too low for SMRT apps that sync 30+ table\n // schemas on startup. Default to 20 but allow callers to override.\n const poolMax = options.max ?? 20;\n const pool = new Pool(\n config.url\n ? { connectionString: config.url as string, max: poolMax }\n : {\n host: host as string,\n user: user as string,\n password: password as string,\n port: port as number,\n database: database as string,\n max: poolMax,\n },\n );\n\n // Wrap pool.end() to evict from cache so stale pools are never returned.\n // This fixes the \"Cannot use a pool after calling end on the pool\" error\n // when tests or shutdown code calls db.client.end() and subsequent calls\n // to getDatabase() would otherwise return the ended pool.\n const originalEnd = pool.end.bind(pool);\n const evictFromCache = () => {\n for (const [key, cached] of connectionCache.entries()) {\n if (cached.client === pool) {\n connectionCache.delete(key);\n }\n }\n };\n (pool as any).end = (callback?: () => void) => {\n evictFromCache();\n if (callback) {\n return originalEnd(callback);\n }\n return originalEnd();\n };\n\n const client = pool;\n\n /**\n * Serializes a value for database storage\n * Converts objects and arrays to JSON strings\n * Converts Dates to ISO strings\n * Passes through primitives unchanged\n */\n const serializeValue = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return value;\n };\n\n /**\n * Serializes all values in an object for database storage\n */\n const serializeRecord = (\n record: Record<string, any>,\n ): Record<string, any> => {\n const serialized: Record<string, any> = {};\n for (const [key, value] of Object.entries(record)) {\n // Skip undefined values - they cannot be passed to the database\n if (value === undefined) {\n continue;\n }\n serialized[key] = serializeValue(value);\n }\n return serialized;\n };\n\n let serverVersionNumPromise: Promise<number> | undefined;\n const nullsNotDistinctIndexCache = new Map<string, Promise<boolean>>();\n\n const hasNullConflictValue = (\n conflictColumns: string[],\n data: Record<string, any>,\n ): boolean => conflictColumns.some((col) => data[col] === null);\n\n const validateUpsertConflictColumns = (\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): void => {\n const missingColumns = conflictColumns.filter(\n (col) => !(col in serializedData),\n );\n\n if (missingColumns.length > 0) {\n throw new DatabaseError('Conflict columns missing from data', {\n table,\n conflictColumns,\n missingColumns,\n availableColumns: Object.keys(serializedData),\n hint: 'All columns specified in ON CONFLICT must be present in the data being inserted. Undefined values should be replaced with null or an appropriate default.',\n });\n }\n };\n\n const getServerVersionNum = async (): Promise<number> => {\n serverVersionNumPromise ??= client\n .query('SHOW server_version_num')\n .then((result) => Number(result.rows[0]?.server_version_num) || 0);\n return serverVersionNumPromise;\n };\n\n const hasNativeNullsNotDistinctIndex = async (\n table: string,\n conflictColumns: string[],\n ): Promise<boolean> => {\n const versionNum = await getServerVersionNum();\n if (versionNum < 150000) return false;\n\n const cacheKey = `${table}:${conflictColumns.join(',')}`;\n let cached = nullsNotDistinctIndexCache.get(cacheKey);\n if (!cached) {\n cached = client\n .query(\n `\n SELECT 1\n FROM pg_index i\n WHERE i.indrelid = to_regclass($1)\n AND i.indisunique\n AND i.indnullsnotdistinct\n AND ARRAY(\n SELECT a.attname::text\n FROM unnest(i.indkey) WITH ORDINALITY AS cols(attnum, ord)\n JOIN pg_attribute a\n ON a.attrelid = i.indrelid\n AND a.attnum = cols.attnum\n ORDER BY cols.ord\n ) = $2::text[]\n LIMIT 1\n `,\n [table, conflictColumns],\n )\n .then((result) => result.rows.length > 0)\n .catch(() => false);\n nullsNotDistinctIndexCache.set(cacheKey, cached);\n }\n\n return cached;\n };\n\n const buildPostgresUpsertParts = (\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ) => {\n const keys = Object.keys(serializedData);\n const values = Object.values(serializedData);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const updateSet = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const conflict = conflictColumns.join(', ');\n\n return { keys, values, placeholders, updateSet, conflict };\n };\n\n const executeStandardPostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const { keys, values, placeholders, updateSet, conflict } =\n buildPostgresUpsertParts(conflictColumns, serializedData);\n const sql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders}) ON CONFLICT(${conflict}) DO UPDATE SET ${updateSet}`;\n const result = await executor.query(sql, values);\n return { operation: 'upsert', affected: result.rowCount ?? 0 };\n };\n\n const executeNullAwarePostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const { keys, values, placeholders } = buildPostgresUpsertParts(\n conflictColumns,\n serializedData,\n );\n const lockKey = conflictColumns\n .map((col) => `${col}:${JSON.stringify(serializedData[col])}`)\n .join('|');\n\n await executor.query(\n 'SELECT pg_advisory_xact_lock(hashtext($1), hashtext($2))',\n [`@happyvertical/sql.upsert:${table}`, lockKey],\n );\n\n const updateSet = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const whereStart = values.length + 1;\n const whereClause = conflictColumns\n .map((col, i) => `${col} IS NOT DISTINCT FROM $${whereStart + i}`)\n .join(' AND ');\n const whereValues = conflictColumns.map((col) => serializedData[col]);\n const updateSql = `UPDATE ${table} SET ${updateSet} WHERE ${whereClause}`;\n const updateResult = await executor.query(updateSql, [\n ...values,\n ...whereValues,\n ]);\n\n if ((updateResult.rowCount ?? 0) > 0) {\n return { operation: 'upsert', affected: updateResult.rowCount ?? 0 };\n }\n\n const insertSql = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;\n const insertResult = await executor.query(insertSql, values);\n return { operation: 'upsert', affected: insertResult.rowCount ?? 0 };\n };\n\n const executeNullAwarePostgresUpsertInTransaction = async (\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const txClient = await client.connect();\n\n try {\n await txClient.query('BEGIN');\n const result = await executeNullAwarePostgresUpsert(\n txClient,\n table,\n conflictColumns,\n serializedData,\n );\n await txClient.query('COMMIT');\n return result;\n } catch (error) {\n await txClient.query('ROLLBACK');\n throw error;\n } finally {\n txClient.release();\n }\n };\n\n const executePostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options: UpsertOptions | undefined,\n acquireTransaction: boolean,\n ): Promise<BaseQueryResult> => {\n const serializedData = serializeRecord(data);\n validateUpsertConflictColumns(table, conflictColumns, serializedData);\n\n if (\n options?.nullsDistinct ||\n !hasNullConflictValue(conflictColumns, serializedData)\n ) {\n return executeStandardPostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n if (await hasNativeNullsNotDistinctIndex(table, conflictColumns)) {\n return executeStandardPostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n if (!acquireTransaction) {\n return executeNullAwarePostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n return executeNullAwarePostgresUpsertInTransaction(\n table,\n conflictColumns,\n serializedData,\n );\n };\n\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n * @throws Error if the insert operation fails\n *\n * @example Single record insert:\n * ```typescript\n * await db.insert('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * ```\n *\n * @example Multiple record insert:\n * ```typescript\n * await db.insert('users', [\n * { name: 'John', email: 'john@example.com' },\n * { name: 'Jane', email: 'jane@example.com' }\n * ]);\n * ```\n */\n const insert = async (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ): Promise<BaseQueryResult> => {\n // If data is an array, we need to handle multiple rows\n if (Array.isArray(data)) {\n // Serialize all records in the array\n const serializedRecords = data.map((record) => serializeRecord(record));\n const keys = Object.keys(serializedRecords[0]);\n const placeholders = serializedRecords\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(\n ', ',\n )}) VALUES ${placeholders}`;\n const values = serializedRecords.reduce<any[]>(\n (acc, row) => acc.concat(Object.values(row)),\n [],\n );\n const result = await client.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n // If data is an object, we handle a single row\n const serializedData = serializeRecord(data);\n const keys = Object.keys(serializedData);\n const values = Object.values(serializedData);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(\n ', ',\n )}) VALUES (${placeholders})`;\n const result = await client.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n };\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to query result\n */\n const get = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any> | null> => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n try {\n const result = await client.query(query, values);\n return result.rows[0] || null;\n } catch (e) {\n throw new DatabaseError('Failed to retrieve record from table', {\n table,\n sql: query,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to array of records\n */\n const list = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any>[]> => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n try {\n const result = await client.query(query, values);\n return result.rows;\n } catch (e) {\n throw new DatabaseError('Failed to list records from table', {\n table,\n sql: query,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update\n * @param data - New data to set\n * @returns Promise resolving to operation result\n */\n const update = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n // Serialize the data to update\n const serializedData = serializeRecord(data);\n const keys = Object.keys(serializedData);\n const values = Object.values(serializedData);\n const setClause = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n try {\n const result = await client.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n } catch (e) {\n throw new DatabaseError('Failed to update records in table', {\n table,\n sql,\n values: [...values, ...whereValues],\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n * @throws Error if the upsert operation fails\n */\n const upsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ): Promise<BaseQueryResult> => {\n try {\n return await executePostgresUpsert(\n client,\n table,\n conflictColumns,\n data,\n options,\n true,\n );\n } catch (e) {\n if (\n e instanceof DatabaseError &&\n e.message === 'Conflict columns missing from data'\n ) {\n throw e;\n }\n\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n values: data,\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record\n * @returns Promise resolving to the query result or insert result\n */\n const getOrInsert = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<Record<string, any>> => {\n const result = await get(table, where);\n if (result) return result;\n await insert(table, data);\n\n const inserted = await get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n };\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion\n * @returns Promise resolving to operation result with count of deleted rows\n * @throws Error if the delete operation fails\n */\n const deleteRecords = async (\n table: string,\n where: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n validateTableName(table);\n\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n\n try {\n const result = await client.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n } catch (e) {\n throw new DatabaseError('Failed to delete records from table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted)\n * @returns Promise resolving to count of matching records\n * @throws Error if the count operation fails\n */\n const count = async (\n table: string,\n where?: Record<string, any>,\n ): Promise<number> => {\n validateTableName(table);\n\n try {\n if (!where || Object.keys(where).length === 0) {\n // Count all records\n const result = await client.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n\n // Count with conditions\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n\n const result = await client.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n\n return Number(result.rows[0]?.count) || 0;\n } catch (e) {\n throw new DatabaseError('Failed to count records in table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param tableName - Table name\n * @returns TableMethods interface for the specified table\n */\n const table = (tableName: string): TableInterface => {\n return {\n insert: (data) => insert(tableName, data),\n get: (data) => get(tableName, data),\n list: (data) => list(tableName, data),\n };\n };\n\n /**\n * Template and values extracted from a tagged template literal\n */\n interface SqlTemplate {\n /**\n * SQL query with parameter placeholders\n */\n sql: string;\n\n /**\n * Values to use as parameters\n */\n values: any[];\n }\n\n /**\n * Parses a tagged template literal into a SQL query and values\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Object with SQL query and values array\n */\n const parseTemplate = (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): SqlTemplate => {\n let sql = strings[0];\n const values = [];\n for (let i = 0; i < vars.length; i++) {\n values.push(vars[i]);\n sql += `$${i + 1}${strings[i + 1]}`;\n }\n return { sql, values };\n };\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n */\n const pluck = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<any> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await client.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n // Return the first column value from the first row\n return Object.values(firstRow)[0];\n } catch (e) {\n throw new DatabaseError('Failed to execute pluck query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n */\n const single = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any> | null> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await client.query(sql, values);\n return result.rows[0] || null;\n } catch (e) {\n throw new DatabaseError('Failed to execute single query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n */\n const many = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any>[]> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await client.query(sql, values);\n return result.rows;\n } catch (e) {\n throw new DatabaseError('Failed to execute many query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n */\n const execute = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<void> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n await client.query(sql, values);\n } catch (e) {\n throw new DatabaseError('Failed to execute query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * Uses PostgreSQL-native placeholders ($1, $2, ...). Legacy ? placeholders\n * are converted only when the placeholder count matches the supplied values,\n * so Postgres operators such as JSONB ? remain intact.\n *\n * @param sql - SQL query string\n * @param values - Variables to use as parameters\n * @returns Promise resolving to query result with rows and count\n */\n const query = async (\n sql: string,\n ...values: any[]\n ): Promise<{ rows: Record<string, any>[]; rowCount: number }> => {\n const query = normalizePostgresRawQuery(sql, values);\n try {\n const result = await client.query(query.sql, query.values);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } catch (e) {\n throw new DatabaseError('Failed to execute raw query', {\n sql: query.sql,\n values: query.values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Acquire a pinned connection from the pool for session-scoped state such as\n * `pg_advisory_lock`. Every query on the returned handle runs on the same\n * client until {@link SessionHandle.release} drops the connection (which\n * frees any session locks it held). The connection is held for the handle's\n * lifetime, so hold one session per process, not per operation.\n */\n const acquireSession = async (): Promise<SessionHandle> => {\n const sessionClient = await pool.connect();\n let released = false;\n let lost = false;\n\n // pg-pool removes its idle 'error' listener when a client is checked out.\n // A session is pinned for the process lifetime and mostly idle between\n // queries, so a backend disconnect/failover would emit 'error' on a\n // listener-less client and crash the process. Absorb it and mark the\n // session dead instead; the next query()/isActive() surfaces it.\n sessionClient.on('error', () => {\n lost = true;\n });\n\n return {\n query: async (sql: string, ...values: any[]) => {\n if (released) {\n throw new DatabaseError('Session has been released', {});\n }\n if (lost) {\n throw new DatabaseError('Session connection was lost', {});\n }\n const normalized = normalizePostgresRawQuery(sql, values);\n try {\n const result = await sessionClient.query(\n normalized.sql,\n normalized.values,\n );\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } catch (e) {\n throw new DatabaseError('Failed to execute session query', {\n sql: normalized.sql,\n values: normalized.values,\n originalError: formatDbError(e),\n });\n }\n },\n isActive: () => !released && !lost,\n release: async () => {\n if (released) return;\n released = true;\n // Free session advisory locks before tearing down so the contract\n // \"after release() the locks are gone\" holds deterministically — the\n // destroy below is async (TCP teardown) and resolves later. Skip on a\n // lost connection (nothing to talk to; backend exit frees them anyway).\n if (!lost) {\n try {\n // A caller that left the connection in an aborted transaction\n // (BEGIN, a failed statement, then release) would make\n // pg_advisory_unlock_all() error with \"current transaction is\n // aborted\". Roll back first (a no-op when no transaction is open)\n // so the unlock runs and the deterministic-release contract holds.\n await sessionClient.query('ROLLBACK');\n } catch {\n // No open transaction, or already gone — proceed to unlock.\n }\n try {\n await sessionClient.query('SELECT pg_advisory_unlock_all()');\n } catch {\n // Best-effort; the destroy below frees locks at backend exit.\n }\n }\n // Destroy the physical connection rather than returning it to the pool.\n // Returning it would NOT clear residual session state, which could then\n // leak onto a connection later handed to unrelated code.\n sessionClient.release(true);\n },\n };\n };\n\n /**\n * Checks if a table exists in the database\n *\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\n const tableExists = async (tableName: string): Promise<boolean> => {\n const result = await client.query(\n `SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1 AND table_schema = 'public')`,\n [tableName],\n );\n return result.rows[0].exists;\n };\n\n /**\n * Synchronizes database schema with provided SQL DDL\n * Creates tables if they don't exist and adds missing columns\n * Also executes CREATE INDEX statements\n *\n * @param schema - SQL schema definition with CREATE TABLE and CREATE INDEX statements\n * @returns Promise that resolves when schema is synchronized\n */\n const syncSchema = async (schema: string): Promise<void> => {\n const commands = schema\n .trim()\n .split(';')\n .filter((command) => command.trim() !== '');\n\n // Match CREATE INDEX statements (Issue #867)\n // Supports: CREATE INDEX, CREATE UNIQUE INDEX, with IF NOT EXISTS\n const createIndexRegex =\n /CREATE (UNIQUE )?INDEX (IF NOT EXISTS )?\"?(\\w+)\"? ON \"?(\\w+)\"?\\s*\\(([^)]+)\\)/i;\n\n // Pre-scan commands to collect all index names for batch existence check (Issue #798)\n const indexNames: string[] = [];\n for (const command of commands) {\n const indexMatch = command.trim().match(createIndexRegex);\n if (indexMatch) {\n indexNames.push(indexMatch[3]);\n }\n }\n\n // Batch query to check which indexes already exist\n const existingIndexes = new Set<string>();\n if (indexNames.length > 0) {\n const result = await client.query(\n `SELECT indexname FROM pg_indexes\n WHERE schemaname = 'public' AND indexname = ANY($1::text[])`,\n [indexNames],\n );\n for (const row of result.rows) {\n existingIndexes.add(row.indexname);\n }\n }\n\n for (const command of commands) {\n const trimmedCommand = command.trim();\n\n // Match CREATE TABLE with optional quotes around table name\n // Supports: CREATE TABLE foo, CREATE TABLE \"foo\", CREATE TABLE IF NOT EXISTS \"foo\"\n const createTableRegex =\n /CREATE TABLE (IF NOT EXISTS )?\"?(\\w+)\"? \\(([\\s\\S]+)\\)/i;\n const tableMatch = trimmedCommand.match(createTableRegex);\n\n if (tableMatch) {\n const tableName = tableMatch[2];\n const columns = tableMatch[3].trim().split(',\\n');\n\n // Check if table exists\n const exists = await tableExists(tableName);\n\n if (!exists) {\n // Table doesn't exist, create it\n await client.query(trimmedCommand);\n } else {\n // Table exists, check for missing columns\n for (const column of columns) {\n const columnDef = column.trim();\n // Match column name with optional quotes: \"id\" or id\n const columnMatch = columnDef.match(/\"?(\\w+)\"?\\s+(\\w+[^,]*)/);\n\n if (columnMatch) {\n const columnName = columnMatch[1];\n\n // Skip constraint definitions\n if (\n columnName.toUpperCase() === 'PRIMARY' ||\n columnName.toUpperCase() === 'FOREIGN' ||\n columnName.toUpperCase() === 'UNIQUE' ||\n columnName.toUpperCase() === 'CHECK' ||\n columnName.toUpperCase() === 'CONSTRAINT'\n ) {\n continue;\n }\n\n try {\n // Check if column exists\n const columnExists = await client.query(\n `SELECT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = $1\n AND column_name = $2\n AND table_schema = 'public'\n )`,\n [tableName, columnName],\n );\n\n if (!columnExists.rows[0].exists) {\n // Column doesn't exist, add it\n // Quote the table name for safety\n const alterCommand = `ALTER TABLE \"${tableName}\" ADD COLUMN ${columnDef}`;\n await client.query(alterCommand);\n }\n } catch (error) {\n // If there's an error checking/adding the column, log it but continue\n console.error(\n `Error adding column ${columnName} to ${tableName}:`,\n error,\n );\n }\n }\n }\n }\n continue;\n }\n\n const indexMatch = trimmedCommand.match(createIndexRegex);\n\n if (indexMatch) {\n const indexName = indexMatch[3];\n const indexTableName = indexMatch[4];\n\n // Use pre-fetched batch result instead of per-index query\n if (!existingIndexes.has(indexName)) {\n try {\n await client.query(trimmedCommand);\n // Track newly created index for idempotency within this call\n existingIndexes.add(indexName);\n } catch (error) {\n // Log error but continue - index creation failures shouldn't block schema sync\n console.warn(\n `Warning: Failed to create index ${indexName} on ${indexTableName}:`,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n continue;\n }\n\n // For any other DDL statements (like other CREATE commands), try to execute them\n // This provides forward compatibility for future DDL types\n if (\n trimmedCommand.toUpperCase().startsWith('CREATE ') &&\n !trimmedCommand.toUpperCase().includes('CREATE TABLE')\n ) {\n try {\n await client.query(trimmedCommand);\n } catch (error) {\n // Log but don't fail - the statement may have already been executed\n console.warn(\n `Warning: DDL statement may have failed:`,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n }\n };\n\n /**\n * Executes a callback within a database transaction\n * Automatically commits on success or rolls back on error\n *\n * @param callback - Function to execute within transaction\n * @returns Promise resolving to callback result\n */\n const transaction = async <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ): Promise<T> => {\n // Get a client from the pool for the transaction\n const txClient = await client.connect();\n\n try {\n await txClient.query('BEGIN');\n\n // Create a transaction-scoped database interface\n const txDb: DatabaseInterface = {\n url,\n client: txClient,\n insert: async (table, data) => {\n // Reuse insert logic but with transaction client\n if (Array.isArray(data)) {\n const keys = Object.keys(data[0]);\n const placeholders = data\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES ${placeholders}`;\n const values = data.reduce(\n (acc, row) => acc.concat(Object.values(row)),\n [] as any[],\n );\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n const keys = Object.keys(data);\n const values = Object.values(data);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n },\n get: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows[0] || null;\n },\n list: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows;\n },\n update: async (table, where, data) => {\n const keys = Object.keys(data);\n const values = Object.values(data);\n const setClause = keys\n .map((key, i) => `${key} = $${i + 1}`)\n .join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n const result = await txClient.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n },\n upsert: async (table, conflictColumns, data, options) =>\n executePostgresUpsert(\n txClient,\n table,\n conflictColumns,\n data,\n options,\n false,\n ),\n getOrInsert: async (table, where, data) => {\n const result = await txDb.get(table, where);\n if (result) return result;\n await txDb.insert(table, data);\n const inserted = await txDb.get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n },\n delete: async (table, where) => {\n validateTableName(table);\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n },\n count: async (table, where) => {\n validateTableName(table);\n if (!where || Object.keys(where).length === 0) {\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n return Number(result.rows[0]?.count) || 0;\n },\n table: (tableName) => ({\n insert: (data) => txDb.insert(tableName, data),\n get: (data) => txDb.get(tableName, data),\n list: (data) => txDb.list(tableName, data),\n }),\n many: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n single: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n pluck: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n execute: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n query: async (sql, ...values) => {\n const query = normalizePostgresRawQuery(sql, values);\n const result = await txClient.query(query.sql, query.values);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n },\n oo: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n oO: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n ox: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n xx: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n tableExists,\n syncSchema,\n transaction,\n };\n\n const result = await callback(txDb);\n await txClient.query('COMMIT');\n return result;\n } catch (error) {\n await txClient.query('ROLLBACK');\n throw error;\n } finally {\n txClient.release();\n }\n };\n\n /**\n * Begins a new transaction and returns a handle for manual control\n *\n * Unlike transaction(), this gives you explicit control over commit/rollback.\n * Ideal for test isolation where you want to rollback after each test.\n *\n * @returns Promise resolving to a TransactionHandle\n */\n const beginTransaction = async (): Promise<TransactionHandle> => {\n // Get a client from the pool for the transaction\n const txClient = await client.connect();\n await txClient.query('BEGIN');\n\n let active = true;\n\n const commit = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await txClient.query('COMMIT');\n active = false;\n txClient.release();\n };\n\n const rollback = async (): Promise<void> => {\n if (!active) {\n throw new DatabaseError('Transaction already ended', {});\n }\n await txClient.query('ROLLBACK');\n active = false;\n txClient.release();\n };\n\n const isActive = (): boolean => active;\n\n // Create a transaction-scoped database interface with commit/rollback\n const txHandle: TransactionHandle = {\n url,\n client: txClient,\n insert: async (table, data) => {\n if (Array.isArray(data)) {\n const keys = Object.keys(data[0]);\n const placeholders = data\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES ${placeholders}`;\n const values = data.reduce(\n (acc, row) => acc.concat(Object.values(row)),\n [] as any[],\n );\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n const keys = Object.keys(data);\n const values = Object.values(data);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(', ')}) VALUES (${placeholders})`;\n const result = await txClient.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n },\n get: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows[0] || null;\n },\n list: async (table, where) => {\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n const result = await txClient.query(query, values);\n return result.rows;\n },\n update: async (table, where, data) => {\n const keys = Object.keys(data);\n const values = Object.values(data);\n const setClause = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n const result = await txClient.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n },\n upsert: async (table, conflictColumns, data, options) =>\n executePostgresUpsert(\n txClient,\n table,\n conflictColumns,\n data,\n options,\n false,\n ),\n getOrInsert: async (table, where, data) => {\n const result = await txHandle.get(table, where);\n if (result) return result;\n await txHandle.insert(table, data);\n const inserted = await txHandle.get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n },\n delete: async (table, where) => {\n validateTableName(table);\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n },\n count: async (table, where) => {\n validateTableName(table);\n if (!where || Object.keys(where).length === 0) {\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const result = await txClient.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n return Number(result.rows[0]?.count) || 0;\n },\n table: (tableName) => ({\n insert: (data) => txHandle.insert(tableName, data),\n get: (data) => txHandle.get(tableName, data),\n list: (data) => txHandle.list(tableName, data),\n }),\n many: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n single: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n pluck: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n execute: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n query: async (sql, ...values) => {\n const query = normalizePostgresRawQuery(sql, values);\n const result = await txClient.query(query.sql, query.values);\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n },\n oo: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows;\n },\n oO: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n return result.rows[0] || null;\n },\n ox: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n const result = await txClient.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n return Object.values(firstRow)[0];\n },\n xx: async (strings, ...vars) => {\n const { sql, values } = parseTemplate(strings, ...vars);\n await txClient.query(sql, values);\n },\n tableExists,\n syncSchema,\n transaction,\n commit,\n rollback,\n isActive,\n };\n\n return txHandle;\n };\n\n // Shorthand aliases for query methods\n const oo = many; // (o)bjective-(o)bjects: returns multiple rows\n const oO = single; // (o)bjective-(O)bject: returns a single row\n const ox = pluck; // (o)bjective-(x): returns a single value\n const xx = execute; // (x)ecute-(x)ecute: executes without returning\n\n /**\n * Initialize database schemas from JSON manifest\n * Supports dependency resolution and schema overrides\n *\n * @param options - Schema initialization options\n * @returns Promise that resolves when schemas are initialized\n */\n const initializeSchemas = async (\n options: SchemaInitializationOptions,\n ): Promise<void> => {\n const schemaManager = new DatabaseSchemaManager();\n const currentDb: DatabaseInterface = {\n url,\n client,\n insert,\n update,\n upsert,\n get,\n getOrInsert,\n delete: deleteRecords,\n count,\n list,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n transaction,\n };\n\n await schemaManager.initializeSchemas(currentDb, options);\n };\n\n /**\n * Retrieves the schema information for a table\n *\n * @param table - Table name\n * @returns Promise resolving to table schema info or null if table doesn't exist\n * @throws Error if the query fails\n */\n const getTableSchema = async (\n table: string,\n ): Promise<TableSchemaInfo | null> => {\n validateTableName(table);\n\n try {\n // Check if table exists\n const exists = await tableExists(table);\n if (!exists) {\n return null;\n }\n\n // Get column information from information_schema\n const columnRows = await many`\n SELECT\n column_name,\n data_type,\n is_nullable,\n column_default\n FROM information_schema.columns\n WHERE table_name = ${table}\n AND table_schema = 'public'\n ORDER BY ordinal_position\n `;\n\n // Get primary key columns\n const pkRows = await many`\n SELECT kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.table_name = ${table}\n AND tc.table_schema = 'public'\n AND tc.constraint_type = 'PRIMARY KEY'\n `;\n\n const pkColumns = new Set(pkRows.map((row) => row.column_name));\n\n const columns: Record<string, ColumnDefinition> = {};\n for (const row of columnRows) {\n const colName = row.column_name as string;\n columns[colName] = {\n type: row.data_type as string,\n primaryKey: pkColumns.has(colName),\n notNull: row.is_nullable === 'NO',\n defaultValue: row.column_default,\n };\n }\n\n // Get index information from pg_indexes\n const indexRows = await many`\n SELECT\n indexname,\n indexdef\n FROM pg_indexes\n WHERE tablename = ${table}\n AND schemaname = 'public'\n AND indexname NOT LIKE '%_pkey'\n `;\n\n const indexes: IndexDefinition[] = [];\n for (const row of indexRows) {\n const indexName = row.indexname as string;\n const indexDef = row.indexdef as string;\n\n // Parse column names from index definition\n // Example: CREATE INDEX idx_name ON table (col1, col2)\n const colMatch = indexDef.match(/\\(([^)]+)\\)/);\n const indexColumns = colMatch\n ? colMatch[1].split(',').map((col) => col.trim())\n : [];\n\n const isUnique = indexDef.toUpperCase().includes('UNIQUE');\n\n indexes.push({\n name: indexName,\n columns: indexColumns,\n unique: isUnique,\n });\n }\n\n // Get foreign key information\n const fkRows = await many`\n SELECT\n kcu.column_name,\n ccu.table_name AS foreign_table_name,\n ccu.column_name AS foreign_column_name,\n rc.delete_rule,\n rc.update_rule\n FROM information_schema.table_constraints AS tc\n JOIN information_schema.key_column_usage AS kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n JOIN information_schema.constraint_column_usage AS ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n JOIN information_schema.referential_constraints AS rc\n ON rc.constraint_name = tc.constraint_name\n AND rc.constraint_schema = tc.table_schema\n WHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_name = ${table}\n AND tc.table_schema = 'public'\n `;\n\n const foreignKeys: Array<{\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete?: string;\n onUpdate?: string;\n }> = [];\n\n for (const fkRow of fkRows) {\n foreignKeys.push({\n column: fkRow.column_name as string,\n referencesTable: fkRow.foreign_table_name as string,\n referencesColumn: fkRow.foreign_column_name as string,\n onDelete: fkRow.delete_rule as string | undefined,\n onUpdate: fkRow.update_rule as string | undefined,\n });\n }\n\n return {\n tableName: table,\n columns,\n indexes,\n foreignKeys,\n };\n } catch (e) {\n throw new DatabaseError('Failed to retrieve table schema', {\n table,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * ALTER TABLE operations for schema evolution\n */\n const alterTable = {\n /**\n * Adds a new column to an existing table\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @returns Promise that resolves when column is added\n * @throws Error if the alter operation fails\n */\n addColumn: async (\n table: string,\n column: ColumnDefinitionWithName,\n ): Promise<void> => {\n validateTableName(table);\n validateColumnName(column.name);\n\n try {\n const sql = generateAddColumnStatement(table, column, 'postgres');\n await client.query(sql);\n } catch (e) {\n throw new DatabaseError('Failed to add column to table', {\n table,\n column: column.name,\n originalError: formatDbError(e),\n });\n }\n },\n\n /**\n * Adds a new index to an existing table\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns Promise that resolves when index is created\n * @throws Error if the create index operation fails\n */\n addIndex: async (table: string, index: IndexDefinition): Promise<void> => {\n validateTableName(table);\n validateIndexName(index.name);\n\n for (const col of index.columns) {\n validateColumnName(col);\n }\n\n try {\n const sql = generateCreateIndexStatement(table, index);\n await client.query(sql);\n } catch (e) {\n throw new DatabaseError('Failed to create index on table', {\n table,\n index: index.name,\n originalError: formatDbError(e),\n });\n }\n },\n };\n\n const db: DatabaseInterface = {\n url,\n client,\n insert,\n update,\n upsert,\n get,\n getOrInsert,\n delete: deleteRecords,\n count,\n list,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n initializeSchemas,\n transaction,\n beginTransaction,\n acquireSession,\n getTableSchema,\n alterTable,\n vector: createVectorCapabilities(pool),\n };\n\n // Cache the connection for reuse by subsequent calls with the same dbid/URL\n const finalCacheKey = cacheKey || url;\n connectionCache.set(finalCacheKey, db);\n\n return db;\n}\n","import { loadEnvConfig } from '@happyvertical/utils';\nimport type { PostgresOptions } from './postgres';\nimport type {\n DatabaseInterface,\n DuckDBOptions,\n JSONOptions,\n} from './shared/types';\nimport type { SqliteOptions } from './sqlite';\n\n/**\n * Union type of options for creating different database types\n */\ntype GetDatabaseOptions =\n | (PostgresOptions & { type?: 'postgres' })\n | (SqliteOptions & { type?: 'sqlite' })\n | (DuckDBOptions & { type?: 'duckdb' })\n | JSONOptions;\n\n/**\n * Checks if the provided value is a database instance rather than configuration options\n *\n * @param value - Value to check\n * @returns True if the value appears to be a DatabaseInterface instance\n */\nfunction isDatabaseInstance(value: any): value is DatabaseInterface {\n return (\n value &&\n typeof value === 'object' &&\n typeof value.client !== 'undefined' &&\n typeof value.insert === 'function' &&\n typeof value.get === 'function' &&\n typeof value.query === 'function'\n );\n}\n\n/**\n * Creates a database connection based on the provided options, or returns an existing database instance\n *\n * Loads configuration from environment variables using the HAVE_SQL_* pattern:\n * - HAVE_SQL_TYPE → type ('sqlite' | 'postgres' | 'duckdb' | 'json')\n * - HAVE_SQL_URL → url (connection string)\n * - HAVE_SQL_HOST → host (database server hostname)\n * - HAVE_SQL_PORT → port (database server port number)\n * - HAVE_SQL_DATABASE → database (database name)\n * - HAVE_SQL_USER → user (authentication username)\n * - HAVE_SQL_PASSWORD → password (authentication password)\n *\n * User-provided options always take precedence over environment variables.\n *\n * ## Lazy schemas\n *\n * The `schemas` option accepts either an eagerly-built record or a lazy\n * function (`() => Record<string, SchemaProvider>`). Adapters that manage\n * tables via migrations (Postgres, SQLite) never resolve the function, so\n * there is zero cost for callers that pass schemas uniformly regardless of\n * adapter type. Only JSON and DuckDB adapters call the function.\n *\n * ```typescript\n * // Caller doesn't need to know the adapter type:\n * await getDatabase({\n * ...config,\n * schemas: () => ObjectRegistry.getAllSchemas(),\n * });\n * ```\n *\n * @param options - Configuration options for the database connection or an existing database instance\n * @returns Promise resolving to a DatabaseInterface implementation\n * @throws Error if the database type is invalid\n */\nexport async function getDatabase(\n options: GetDatabaseOptions | DatabaseInterface = {},\n): Promise<DatabaseInterface> {\n // If a database instance is passed, return it directly\n if (isDatabaseInstance(options)) {\n return options;\n }\n\n // Load HAVE_SQL_* environment variables and merge into options\n // This ensures options object is mutated (needed for dbid propagation)\n Object.assign(\n options,\n loadEnvConfig(options as any, {\n packageName: 'sql',\n schema: {\n type: 'string',\n url: 'string',\n host: 'string',\n port: 'number',\n database: 'string',\n user: 'string',\n password: 'string',\n },\n }) as Partial<GetDatabaseOptions>,\n );\n\n // if no type but url starts with file:, set to sqlite\n if (\n !options.type &&\n (options.url?.startsWith('file:') || options.url === ':memory:')\n ) {\n options.type = 'sqlite';\n }\n\n if (options.type === 'postgres') {\n const postgres = await import('./postgres.js');\n return postgres.getDatabase(options as PostgresOptions);\n }\n if (options.type === 'sqlite') {\n const sqlite = await import('./sqlite.js');\n return sqlite.getDatabase(options as SqliteOptions);\n }\n if (options.type === 'duckdb') {\n const duckdb = await import('./duckdb.js');\n return duckdb.getDatabase(options as DuckDBOptions);\n }\n if (options.type === 'json') {\n const json = await import('./json.js');\n return json.getDatabase(options as JSONOptions);\n }\n throw new Error('Invalid database type');\n}\n\n/**\n * Validates if a table name consists only of alphanumeric characters and underscores\n *\n * @param name - Table name to validate\n * @returns Boolean indicating if the name is valid\n */\nfunction _isValidTableName(name: string): boolean {\n // Simple regex to allow only alphanumeric characters and underscores\n return /^[a-zA-Z0-9_]+$/.test(name);\n}\n\n/**\n * Synchronizes a SQL schema definition with a database\n * Creates tables if they don't exist and adds missing columns to existing tables\n *\n * @param options - Object containing database and schema\n * @param options.db - Database interface to use\n * @param options.schema - SQL schema definition\n * @throws Error if db or schema are missing or if the database doesn't support syncSchema\n */\nexport async function syncSchema(options: {\n db: DatabaseInterface;\n schema: string;\n}) {\n const { db, schema } = options;\n if (!db || !schema) {\n throw new Error('db and schema are required');\n }\n\n // Delegate to the database adapter's syncSchema implementation\n if (db.syncSchema) {\n await db.syncSchema(schema);\n } else {\n throw new Error('Database adapter does not support schema synchronization');\n }\n}\n\n/**\n * Checks if a table exists in the database\n *\n * @param db - Database interface to use\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\nexport async function tableExists(db: DatabaseInterface, tableName: string) {\n return db.tableExists(tableName);\n}\n\n/**\n * Escapes and formats a value for use in SQL queries\n *\n * @param value - Value to escape\n * @returns String representation of the value safe for SQL use\n */\nexport function escapeSqlValue(value: any): string {\n if (value === null) {\n return 'NULL';\n }\n if (value instanceof Date) {\n return `'${value.toISOString()}'`;\n }\n if (typeof value === 'number') {\n return value.toString();\n }\n if (typeof value === 'boolean') {\n return value ? '1' : '0';\n }\n // Escape single quotes and wrap in quotes\n return `'${String(value).replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Validates a column name for use in SQL queries\n *\n * @param column - Column name to validate\n * @returns The validated column name\n * @throws Error if the column name contains invalid characters\n */\nexport function validateColumnName(column: string): string {\n // Only allow alphanumeric characters, underscores, and dots (for table.column notation)\n if (!/^[a-zA-Z0-9_.]+$/.test(column)) {\n throw new Error(`Invalid column name: ${column}`);\n }\n return column;\n}\n\n// Import utilities from shared utils\nimport { buildWhere, formatDbError } from './shared/utils';\n\nexport {\n type AggregateBuildResult,\n type AggregateFunction,\n type AggregateSelectExpr,\n type AggregateSpec,\n type AggregateTimeBucketUnit,\n bucketExpr,\n buildAggregate,\n} from './aggregate.js';\nexport type { SqlAdapterType } from './shared/utils';\nexport { buildWhere, formatDbError };\n\n// Import DuckDB schema transformation utilities\nimport { convertUniqueIndexesToInlineConstraints } from './shared/duckdb-schema-utils';\n\n// Generic database integrity-check framework\nexport {\n checkExpectedTables,\n checkRelationship,\n checkUniqueColumn,\n type DoctorCheck,\n type DoctorContext,\n type DoctorIssue,\n type DoctorLevel,\n type DoctorResult,\n type RelationshipSpec,\n type RunDoctorOptions,\n runDoctor,\n type UniqueColumnSpec,\n} from './doctor';\n\n// Export adapter cache utilities (for testing)\nexport { clearConnectionCache } from './json.js';\nexport { clearPostgresConnectionCache } from './postgres.js';\n// Postgres CLI shell-outs and URL helpers\nexport {\n assertCanExportDatabase,\n assertCanImportDatabase,\n type CreateDropOptions,\n createPostgresDatabase,\n type DumpOptions,\n databaseNameFromUrl,\n dropPostgresDatabase,\n dumpPostgresDatabase,\n isLocalDatabaseUrl,\n type PostgresImportLocalityOptions,\n type PostgresLocalityOptions,\n postgresEnvFromUrl,\n type RestoreOptions,\n redactDatabaseUrl,\n restorePostgresDatabase,\n} from './postgres-cli';\nexport type { SchemaInitializationResult } from './schema-manager';\n// Export schema management\nexport { DatabaseSchemaManager } from './schema-manager';\nexport * from './shared/types';\nexport { convertUniqueIndexesToInlineConstraints };\n\nexport default {\n getDatabase,\n syncSchema,\n tableExists,\n buildWhere,\n};\n\n/** @internal */\nexport const PACKAGE_VERSION_INITIALIZED = true;\n"],"names":["index","alias","expression","tableExists","pendingConnections","validateTableName","getDatabase","table","options","result","rows","connection","syncSchema","validateColumnName","cacheKey","keys","placeholders","_","query","values","postgres","json"],"mappings":"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"}
|