@toiroakr/lines-db 0.4.0 → 0.5.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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["columns: ColumnDefinition[]","sqlType: ColumnDefinition['type']","readFile","writeFile","foreignKeys: BiDirectionalSchema['foreignKeys']","pathToFileURL","schemaMetadata: {\n primaryKey?: string;\n foreignKeys?: BiDirectionalSchema['foreignKeys'];\n indexes?: BiDirectionalSchema['indexes'];\n }","validationErrors: Array<{\n rowIndex: number;\n rowData: JsonObject;\n error: ValidationError;\n }>","validatedData: JsonObject[]","schema: TableSchema","foreignKeyDefs: string[]","rows: Tables[K][]","normalizedValue: JsonObject","pkValues: unknown[]","validationErrors: Array<{\n rowIndex: number;\n rowData: unknown;\n pkValue: unknown;\n error: ValidationError;\n }>","values: Array<string | number | bigint | null | Uint8Array>","functionFilters: Array<{ key: string; fn: (value: unknown) => boolean }>","conditions: string[]","tables: TableInfo[]","imports: string[]","tableEntries: string[]","allErrors: ValidationErrorDetail[]","allWarnings: string[]","filesWithSchema: string[]","errors: ValidationErrorDetail[]","warnMessages: string[]","capturedError: Error | null","warnMessages: string[]"],"sources":["../src/runtime.ts","../src/sqlite-adapter.ts","../src/jsonl-reader.ts","../src/jsonl-writer.ts","../src/schema-loader.ts","../src/directory-scanner.ts","../src/schema.ts","../src/database.ts","../src/type-generator.ts","../src/validator.ts","../src/jsonl-migration.ts"],"sourcesContent":["/**\n * Runtime detection utilities\n */\n\nexport type RuntimeEnvironment = 'node' | 'unknown';\n\nexport function detectRuntime(): RuntimeEnvironment {\n // Check for Node.js\n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'unknown';\n}\n\nexport const RUNTIME = detectRuntime();\n","/**\n * SQLite adapter for Node.js\n */\n\nimport { RUNTIME } from './runtime.js';\n\n/**\n * Common interface for SQLite database\n */\nexport interface SQLiteDatabase {\n prepare(sql: string): SQLiteStatement;\n exec(sql: string): void;\n close(): void;\n}\n\nexport interface SQLiteStatement {\n run(...params: any[]): { changes: number; lastInsertRowid: number | bigint };\n get(...params: any[]): any;\n all(...params: any[]): any[];\n}\n\n/**\n * Create a SQLite database instance for Node.js\n */\nexport function createDatabase(path: string = ':memory:'): SQLiteDatabase {\n if (RUNTIME === 'node') {\n return createNodeDatabase(path);\n } else {\n throw new Error(`Unsupported runtime: ${RUNTIME}`);\n }\n}\n\n/**\n * Create a Node.js SQLite database\n */\nfunction createNodeDatabase(path: string): SQLiteDatabase {\n // Dynamic import for Node.js\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite');\n const db = new DatabaseSync(path);\n\n // CRITICAL: Enable foreign key constraints\n // SQLite disables foreign keys by default, which is a major data integrity issue\n db.exec('PRAGMA foreign_keys = ON');\n\n return {\n prepare(sql: string): SQLiteStatement {\n const stmt = db.prepare(sql);\n return {\n run(...params: any[]) {\n return stmt.run(...params);\n },\n get(...params: any[]) {\n return stmt.get(...params);\n },\n all(...params: any[]) {\n return stmt.all(...params);\n },\n };\n },\n exec(sql: string): void {\n db.exec(sql);\n },\n close(): void {\n db.close();\n },\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { normalize } from 'node:path';\nimport type { JsonObject, ColumnDefinition, TableSchema } from './types.js';\n\nexport class JsonlReader {\n private static overrides: Map<string, JsonObject[]> | null = null;\n\n /**\n * Temporarily override the data returned for specific JSONL files.\n * Useful for scenarios like migration validation where in-memory data should be used.\n */\n static async withOverrides<T>(\n overrides: Map<string, JsonObject[]>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const normalized = new Map<string, JsonObject[]>();\n for (const [filePath, rows] of overrides) {\n normalized.set(normalize(filePath), rows);\n }\n\n const previousOverrides = this.overrides;\n this.overrides = normalized;\n\n try {\n return await fn();\n } finally {\n this.overrides = previousOverrides;\n }\n }\n\n /**\n * Read JSONL file and parse each line as JSON\n */\n static async read(filePath: string): Promise<JsonObject[]> {\n const overrideRows = this.overrides?.get(normalize(filePath));\n if (overrideRows) {\n // Return clones to avoid accidental mutations from consumers\n return overrideRows.map((row) => JSON.parse(JSON.stringify(row)) as JsonObject);\n }\n\n const content = await readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n');\n\n return lines\n .filter((line) => line.trim().length > 0)\n .map((line) => {\n try {\n return JSON.parse(line) as JsonObject;\n } catch (error) {\n throw new Error(`Failed to parse JSON line: ${line}`, { cause: error });\n }\n });\n }\n\n /**\n * Infer schema from JSONL data\n */\n static inferSchema(tableName: string, data: JsonObject[]): TableSchema {\n if (data.length === 0) {\n throw new Error('Cannot infer schema from empty data');\n }\n\n const columnTypes = new Map<string, Set<string>>();\n const booleanColumns = new Set<string>();\n const nonBooleanColumns = new Set<string>();\n\n // Collect all column names and their types\n for (const row of data) {\n for (const [key, value] of Object.entries(row)) {\n if (!columnTypes.has(key)) {\n columnTypes.set(key, new Set());\n }\n columnTypes.get(key)!.add(this.inferType(value));\n\n if (typeof value === 'boolean') {\n booleanColumns.add(key);\n } else if (value !== null) {\n nonBooleanColumns.add(key);\n }\n }\n }\n\n // Convert to column definitions\n const columns: ColumnDefinition[] = [];\n for (const [columnName, types] of columnTypes.entries()) {\n const typeArray = Array.from(types);\n\n // If multiple types exist, prefer TEXT as a safe fallback\n let sqlType: ColumnDefinition['type'] = 'TEXT';\n\n if (typeArray.length === 1) {\n sqlType = typeArray[0] as ColumnDefinition['type'];\n } else if (typeArray.every((t) => t === 'INTEGER' || t === 'REAL')) {\n sqlType = 'REAL'; // Use REAL if we have mixed numeric types\n } else if (!typeArray.includes('NULL')) {\n // If there are multiple non-null types, use TEXT\n sqlType = 'TEXT';\n } else if (typeArray.length === 2 && typeArray.includes('NULL')) {\n // If one type + NULL, use the non-null type\n sqlType = typeArray.find((t) => t !== 'NULL') as ColumnDefinition['type'];\n }\n\n const isBooleanColumn = booleanColumns.has(columnName) && !nonBooleanColumns.has(columnName);\n\n columns.push({\n name: columnName,\n type: sqlType,\n notNull: !typeArray.includes('NULL'),\n valueType: isBooleanColumn ? 'boolean' : undefined,\n });\n }\n\n // If there's an 'id' column, make it primary key\n const idColumn = columns.find((col) => col.name === 'id');\n if (idColumn) {\n idColumn.primaryKey = true;\n }\n\n return {\n name: tableName,\n columns,\n };\n }\n\n private static inferType(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number') {\n return Number.isInteger(value) ? 'INTEGER' : 'REAL';\n }\n if (typeof value === 'string') return 'TEXT';\n if (typeof value === 'boolean') return 'INTEGER'; // SQLite stores booleans as integers\n if (typeof value === 'object') return 'JSON'; // Store objects/arrays as JSON\n return 'TEXT';\n }\n}\n","import { writeFile } from 'node:fs/promises';\nimport type { JsonObject } from './types.js';\n\nexport class JsonlWriter {\n /**\n * Write data to JSONL file\n */\n static async write(filePath: string, data: JsonObject[]): Promise<void> {\n const lines = data.map((obj) => JSON.stringify(obj)).join('\\n');\n await writeFile(filePath, lines + '\\n', 'utf-8');\n }\n\n /**\n * Append data to JSONL file\n */\n static async append(filePath: string, data: JsonObject[]): Promise<void> {\n const { readFile, writeFile } = await import('node:fs/promises');\n\n try {\n const existing = await readFile(filePath, 'utf-8');\n const lines = data.map((obj) => JSON.stringify(obj)).join('\\n');\n const newContent = existing.trim() + '\\n' + lines + '\\n';\n await writeFile(filePath, newContent, 'utf-8');\n } catch (error) {\n // If file doesn't exist, just write the data\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n await this.write(filePath, data);\n } else {\n throw error;\n }\n }\n }\n}\n","import { pathToFileURL } from 'node:url';\nimport { access } from 'node:fs/promises';\nimport { dirname, join, basename } from 'node:path';\nimport type { StandardSchema } from './types.js';\n\nexport class SchemaLoader {\n /**\n * Check if a schema file exists for a table\n */\n static async hasSchema(jsonlPath: string): Promise<boolean> {\n const dir = dirname(jsonlPath);\n const tableName = basename(jsonlPath, '.jsonl');\n const schemaPath = join(dir, `${tableName}.schema.ts`);\n\n try {\n await access(schemaPath);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Load a validation schema file for a table\n * Requires ${tableName}.schema.ts to exist alongside the JSONL file\n */\n static async loadSchema(jsonlPath: string): Promise<StandardSchema> {\n const dir = dirname(jsonlPath);\n const tableName = basename(jsonlPath, '.jsonl');\n const schemaPath = join(dir, `${tableName}.schema.ts`);\n\n try {\n await access(schemaPath);\n } catch (error) {\n throw new Error(`Schema file not found for table '${tableName}'. Expected: ${schemaPath}`, {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n try {\n const schemaUrl = pathToFileURL(schemaPath).href;\n // Add cache busting query parameter to force reload on each import\n // This ensures schema changes are picked up immediately\n const cacheBustedUrl = `${schemaUrl}?t=${Date.now()}`;\n const module = await import(cacheBustedUrl);\n const schema = module.default || module.schema;\n\n if (schema && this.isStandardSchema(schema)) {\n return schema;\n }\n\n throw new Error(`Schema file ${schemaPath} does not export a valid StandardSchema`);\n } catch (error) {\n throw new Error(\n `Failed to load schema for table '${tableName}' from ${schemaPath}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error instanceof Error ? error : undefined },\n );\n }\n }\n\n /**\n * Check if an object implements the StandardSchema interface\n */\n private static isStandardSchema(obj: unknown): obj is StandardSchema {\n if (!obj || typeof obj !== 'object') return false;\n\n const schema = obj as Record<string, unknown>;\n const standard = schema['~standard'];\n\n if (!standard || typeof standard !== 'object') return false;\n\n const standardObj = standard as Record<string, unknown>;\n\n return (\n standardObj.version === 1 &&\n typeof standardObj.vendor === 'string' &&\n typeof standardObj.validate === 'function'\n );\n }\n}\n","import { readdir } from 'node:fs/promises';\nimport { join, basename, extname } from 'node:path';\nimport type { TableConfig } from './types.js';\n\nexport class DirectoryScanner {\n /**\n * Scan directory for JSONL files and create table configurations\n */\n static async scanDirectory(dataDir: string): Promise<Map<string, TableConfig>> {\n const tables = new Map<string, TableConfig>();\n\n try {\n const files = await readdir(dataDir);\n\n for (const file of files) {\n if (extname(file) === '.jsonl') {\n const tableName = basename(file, '.jsonl');\n const jsonlPath = join(dataDir, file);\n\n tables.set(tableName, {\n jsonlPath,\n autoInferSchema: true,\n });\n }\n }\n\n if (tables.size === 0) {\n console.warn(`Warning: No JSONL files found in directory: ${dataDir}`);\n }\n\n return tables;\n } catch (error) {\n throw new Error(\n `Failed to scan directory ${dataDir}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n","import type { StandardSchema, Table, ForeignKeyDefinition, IndexDefinition } from './types.js';\n\n/**\n * Schema options for defining constraints and indexes\n */\nexport interface SchemaOptions {\n /**\n * Primary key column\n */\n primaryKey?: string;\n\n /**\n * Foreign key constraints\n */\n foreignKeys?: ForeignKeyDefinition[];\n\n /**\n * Indexes to create\n */\n indexes?: IndexDefinition[];\n\n /**\n * Backward transformation from Output to Input\n * Required when Input and Output types differ (e.g., with transformations)\n */\n backward?: (output: Table) => Table;\n}\n\n/**\n * BiDirectional Schema interface\n * Extends StandardSchema with optional backward transformation and schema metadata\n */\nexport interface BiDirectionalSchema<Input extends Table = Table, Output extends Table = Input>\n extends StandardSchema<Input, Output> {\n /**\n * Backward transformation from Output to Input\n * Required when Input and Output types differ (e.g., with transformations)\n */\n backward?: (output: Output) => Input;\n\n /**\n * Primary key column\n */\n primaryKey?: string;\n\n /**\n * Foreign key constraints\n */\n foreignKeys?: ForeignKeyDefinition[];\n\n /**\n * Indexes to create\n */\n indexes?: IndexDefinition[];\n}\n\n/**\n * Define a bidirectional schema with optional backward transformation\n *\n * @param schema - Standard Schema for validation\n * @param optionsOrBackward - Optional SchemaOptions object or backward transformation function (Output → Input)\n * Required when schema performs transformations\n *\n * @example\n * // No transformation - backward not needed\n * const schema = defineSchema(\n * v.object({ id: v.number(), name: v.string() })\n * );\n *\n * @example\n * // With transformation - backward recommended (legacy)\n * const schema = defineSchema(\n * v.pipe(v.string(), v.transform(Number)),\n * (num) => String(num) // backward: number → string\n * );\n *\n * @example\n * // With primary key and foreign key\n * const schema = defineSchema(\n * v.object({ id: v.number(), customerId: v.number() }),\n * {\n * primaryKey: 'id',\n * foreignKeys: [\n * { column: 'customerId', references: { table: 'users', column: 'id' } }\n * ]\n * }\n * );\n */\nexport function defineSchema<Input extends Table, Output extends Table>(\n schema: StandardSchema<Input, Output>,\n optionsOrBackward?: SchemaOptions | ((output: Output) => Input),\n): BiDirectionalSchema<Input, Output> {\n // Create a new object that extends the schema\n const bidirectionalSchema = Object.create(schema) as BiDirectionalSchema<Input, Output>;\n\n // Handle options or backward function\n if (optionsOrBackward) {\n if (typeof optionsOrBackward === 'function') {\n // Legacy: backward function only\n bidirectionalSchema.backward = optionsOrBackward;\n } else {\n // New: options object\n if (optionsOrBackward.backward) {\n bidirectionalSchema.backward = optionsOrBackward.backward as (output: Output) => Input;\n }\n if (optionsOrBackward.primaryKey) {\n bidirectionalSchema.primaryKey = optionsOrBackward.primaryKey;\n }\n if (optionsOrBackward.foreignKeys) {\n bidirectionalSchema.foreignKeys = optionsOrBackward.foreignKeys;\n }\n if (optionsOrBackward.indexes) {\n bidirectionalSchema.indexes = optionsOrBackward.indexes;\n }\n }\n }\n\n // Copy '~standard' property\n Object.defineProperty(bidirectionalSchema, '~standard', {\n value: schema['~standard'],\n enumerable: true,\n configurable: true,\n });\n\n return bidirectionalSchema;\n}\n\n/**\n * Check if a schema has backward transformation\n */\nexport function hasBackward<Input extends Table, Output extends Table>(\n schema: StandardSchema<Input, Output>,\n): schema is BiDirectionalSchema<Input, Output> {\n return 'backward' in schema && typeof (schema as { backward?: unknown }).backward === 'function';\n}\n","import { createDatabase, type SQLiteDatabase } from './sqlite-adapter.js';\nimport { JsonlReader } from './jsonl-reader.js';\nimport { JsonlWriter } from './jsonl-writer.js';\nimport { SchemaLoader } from './schema-loader.js';\nimport { DirectoryScanner } from './directory-scanner.js';\nimport { hasBackward } from './schema.js';\nimport type {\n DatabaseConfig,\n TableSchema,\n JsonObject,\n TableConfig,\n StandardSchema,\n StandardSchemaIssue,\n ValidationError,\n Table,\n TableDefs,\n WhereCondition,\n} from './types.js';\nimport type { BiDirectionalSchema } from './schema.js';\n\nexport class LinesDB<Tables extends TableDefs> {\n private db: SQLiteDatabase;\n private config: DatabaseConfig<Tables>;\n private schemas: Map<string, TableSchema> = new Map();\n private validationSchemas: Map<string, StandardSchema | undefined> = new Map();\n private tables: Map<string, TableConfig> = new Map();\n private inTransaction: boolean = false;\n\n private constructor(config: DatabaseConfig<Tables>, dbPath?: string) {\n this.config = config;\n this.db = createDatabase(dbPath ?? ':memory:');\n }\n\n static create<Tables extends TableDefs>(\n config: DatabaseConfig<Tables>,\n dbPath?: string,\n ): LinesDB<Tables> {\n return new LinesDB<Tables>(config, dbPath);\n }\n\n /**\n * Initialize database by loading all JSONL files\n * Uses dependency resolution to ensure foreign key references are loaded in correct order\n */\n async initialize(): Promise<void> {\n // Scan directory for JSONL files\n this.tables = await DirectoryScanner.scanDirectory(this.config.dataDir);\n\n // Track loaded tables and tables currently being loaded (for circular dependency detection)\n const loadedTables = new Set<string>();\n const loadingTables = new Set<string>();\n\n // Load all tables with dependency resolution\n for (const [tableName] of this.tables) {\n if (!loadedTables.has(tableName)) {\n try {\n await this.loadTableWithDependencies(tableName, loadedTables, loadingTables);\n } catch (error) {\n // Log error but continue loading other tables\n console.warn(\n `Warning: Failed to load table '${tableName}':`,\n error instanceof Error ? error.message : String(error),\n );\n // Remove the failed table from the tables map\n this.tables.delete(tableName);\n this.schemas.delete(tableName);\n this.validationSchemas.delete(tableName);\n }\n }\n }\n }\n\n /**\n * Load a table and its dependencies recursively\n */\n private async loadTableWithDependencies(\n tableName: string,\n loadedTables: Set<string>,\n loadingTables: Set<string>,\n ): Promise<void> {\n // Skip if already loaded\n if (loadedTables.has(tableName)) {\n return;\n }\n\n // Check for circular dependencies\n if (loadingTables.has(tableName)) {\n throw new Error(`Circular dependency detected for table '${tableName}'`);\n }\n\n // Get table config\n const tableConfig = this.tables.get(tableName);\n if (!tableConfig) {\n throw new Error(`Table configuration not found for '${tableName}'`);\n }\n\n // Mark as currently loading\n loadingTables.add(tableName);\n\n try {\n // Load schema module to check for foreign key dependencies\n // We need to load the entire module to access foreignKeys export\n let foreignKeys: BiDirectionalSchema['foreignKeys'];\n\n try {\n const { pathToFileURL } = await import('node:url');\n const schemaPath = tableConfig.jsonlPath.replace('.jsonl', '.schema.ts');\n const schemaUrl = pathToFileURL(schemaPath).href;\n const schemaModule = await import(`${schemaUrl}?t=${Date.now()}`);\n\n // Try to get foreign keys from exported 'schema' or directly from module\n const schemaExport = schemaModule.schema || schemaModule.default;\n foreignKeys = schemaExport?.foreignKeys || schemaModule.foreignKeys;\n } catch {\n // Schema file not found - will continue without validation\n }\n\n // If there are foreign key dependencies, load them first\n if (foreignKeys && foreignKeys.length > 0) {\n for (const fk of foreignKeys) {\n const referencedTable = fk.references.table;\n if (!loadedTables.has(referencedTable)) {\n // Check if referenced table exists in our tables map\n if (this.tables.has(referencedTable)) {\n await this.loadTableWithDependencies(referencedTable, loadedTables, loadingTables);\n } else {\n throw new Error(\n `Foreign key reference to non-existent table '${referencedTable}' in table '${tableName}'`,\n );\n }\n }\n }\n }\n\n // Now load this table\n const wasLoaded = await this.loadTable(tableName, tableConfig);\n if (wasLoaded) {\n loadedTables.add(tableName);\n } else {\n // Table was not loaded (e.g., empty data)\n this.tables.delete(tableName);\n }\n } finally {\n // Remove from loading set\n loadingTables.delete(tableName);\n }\n }\n\n /**\n * Load a single table from JSONL file\n * @returns true if table was loaded, false if skipped\n */\n private async loadTable(tableName: string, config: TableConfig): Promise<boolean> {\n // Read JSONL file\n const data = await JsonlReader.read(config.jsonlPath);\n\n // Load validation schema if provided or try to auto-load\n let validationSchema = config.validationSchema;\n const schemaMetadata: {\n primaryKey?: string;\n foreignKeys?: BiDirectionalSchema['foreignKeys'];\n indexes?: BiDirectionalSchema['indexes'];\n } = {};\n\n if (!validationSchema) {\n try {\n validationSchema = await SchemaLoader.loadSchema(config.jsonlPath);\n } catch (_error) {\n // Schema file not found or failed to load - this is OK, table can still be used without validation\n }\n }\n\n // Load schema metadata (foreignKeys, primaryKey, indexes) from schema module\n // SchemaLoader.loadSchema() only returns the validation schema object, not metadata\n if (!config.validationSchema) {\n // Only load if not already provided via config\n try {\n const { pathToFileURL } = await import('node:url');\n const schemaPath = config.jsonlPath.replace('.jsonl', '.schema.ts');\n const schemaUrl = pathToFileURL(schemaPath).href;\n const schemaModule = await import(`${schemaUrl}?t=${Date.now()}`);\n\n // Try to get metadata from exported 'schema' or directly from module\n const schemaExport = schemaModule.schema || schemaModule.default;\n\n if (schemaExport?.primaryKey) {\n schemaMetadata.primaryKey = schemaExport.primaryKey;\n } else if (schemaModule.primaryKey) {\n schemaMetadata.primaryKey = schemaModule.primaryKey;\n }\n\n if (schemaExport?.foreignKeys) {\n schemaMetadata.foreignKeys = schemaExport.foreignKeys;\n } else if (schemaModule.foreignKeys) {\n schemaMetadata.foreignKeys = schemaModule.foreignKeys;\n }\n\n if (schemaExport?.indexes) {\n schemaMetadata.indexes = schemaExport.indexes;\n } else if (schemaModule.indexes) {\n schemaMetadata.indexes = schemaModule.indexes;\n }\n } catch (_error) {\n // Schema file not found - this is OK\n }\n }\n\n this.validationSchemas.set(tableName, validationSchema);\n\n // Validate data first and collect validated (transformed) data\n const validationErrors: Array<{\n rowIndex: number;\n rowData: JsonObject;\n error: ValidationError;\n }> = [];\n const validatedData: JsonObject[] = [];\n\n for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {\n const row = data[rowIndex];\n try {\n const validatedRow = this.validateAndTransform(tableName, row);\n validatedData.push(validatedRow);\n } catch (error) {\n if (error instanceof Error && error.name === 'ValidationError') {\n validationErrors.push({\n rowIndex,\n rowData: row,\n error: error as ValidationError,\n });\n } else {\n throw error;\n }\n }\n }\n\n if (validationErrors.length > 0) {\n const enhancedError = new Error(\n `Validation failed for ${validationErrors.length} row(s) in table ${tableName}`,\n );\n enhancedError.name = 'ValidationError';\n (enhancedError as unknown as { validationErrors: typeof validationErrors }).validationErrors =\n validationErrors;\n (enhancedError as unknown as { issues: ReadonlyArray<StandardSchemaIssue> }).issues =\n validationErrors[0].error.issues;\n throw enhancedError;\n }\n\n // Determine schema - infer from validated data if auto-inference is enabled\n let schema: TableSchema;\n if (config.schema) {\n schema = config.schema;\n } else if (config.autoInferSchema !== false) {\n if (validatedData.length === 0) {\n return false;\n }\n // Infer schema from validated data (which may have additional fields added by validation)\n schema = JsonlReader.inferSchema(tableName, validatedData);\n } else {\n throw new Error(`No schema provided for table ${tableName} and autoInferSchema is disabled`);\n }\n\n // Enhance schema with constraints from validation schema and schema metadata\n // Priority: config.validationSchema (as BiDirectionalSchema) > schemaMetadata\n const biSchema = validationSchema as BiDirectionalSchema;\n const primaryKey = biSchema?.primaryKey || schemaMetadata.primaryKey;\n const foreignKeys = biSchema?.foreignKeys || schemaMetadata.foreignKeys;\n const indexes = biSchema?.indexes || schemaMetadata.indexes;\n\n if (primaryKey && !schema.columns.some((col) => col.primaryKey)) {\n // Add primary key constraint to column\n const col = schema.columns.find((c) => c.name === primaryKey);\n if (col) {\n col.primaryKey = true;\n }\n } else if (!primaryKey && !schema.columns.some((col) => col.primaryKey)) {\n // If no primary key is defined, use 'id' column as primary key if it exists\n // This matches the behavior of JsonlReader.inferSchema()\n const idColumn = schema.columns.find((c) => c.name === 'id');\n if (idColumn) {\n idColumn.primaryKey = true;\n }\n }\n if (foreignKeys) {\n schema.foreignKeys = foreignKeys;\n }\n if (indexes) {\n schema.indexes = indexes;\n }\n\n this.schemas.set(tableName, schema);\n\n // Create table\n this.createTable(schema);\n\n // Insert validated data\n this.insertData(tableName, schema, validatedData);\n\n return true;\n }\n\n /**\n * Create table in SQLite with constraints and indexes\n */\n private createTable(schema: TableSchema): void {\n // Note: Foreign key constraints are enabled at database connection level (see sqlite-adapter.ts)\n // No need to enable them here for each table\n\n // Quote table name to handle special characters\n const quotedTableName = this.quoteTableName(schema.name);\n\n const columnDefs = schema.columns.map((col) => {\n // JSON type is stored as TEXT in SQLite\n const sqlType = col.type === 'JSON' ? 'TEXT' : col.type;\n const parts = [this.quoteIdentifier(col.name), sqlType];\n if (col.primaryKey) parts.push('PRIMARY KEY');\n if (col.notNull) parts.push('NOT NULL');\n if (col.unique) parts.push('UNIQUE');\n return parts.join(' ');\n });\n\n // Add foreign key constraints\n const foreignKeyDefs: string[] = [];\n if (schema.foreignKeys && schema.foreignKeys.length > 0) {\n for (const fk of schema.foreignKeys) {\n const fkParts = [\n `FOREIGN KEY (${this.quoteIdentifier(fk.column)})`,\n `REFERENCES ${this.quoteTableName(fk.references.table)}(${this.quoteIdentifier(fk.references.column)})`,\n ];\n if (fk.onDelete) {\n fkParts.push(`ON DELETE ${fk.onDelete}`);\n }\n if (fk.onUpdate) {\n fkParts.push(`ON UPDATE ${fk.onUpdate}`);\n }\n foreignKeyDefs.push(fkParts.join(' '));\n }\n }\n\n const allDefs = [...columnDefs, ...foreignKeyDefs];\n const sql = `CREATE TABLE IF NOT EXISTS ${quotedTableName} (${allDefs.join(', ')})`;\n this.db.exec(sql);\n\n // Create indexes\n if (schema.indexes && schema.indexes.length > 0) {\n for (let i = 0; i < schema.indexes.length; i++) {\n const index = schema.indexes[i];\n // Create safe index name by replacing special characters\n const safeTableName = schema.name.replace(/[^a-zA-Z0-9]/g, '_');\n const resolvedIndexName =\n index.name || `idx_${safeTableName}_${index.columns.join('_')}_${i}`;\n const uniqueKeyword = index.unique ? 'UNIQUE ' : '';\n const indexSql = `CREATE ${uniqueKeyword}INDEX IF NOT EXISTS ${this.quoteIdentifier(resolvedIndexName)} ON ${quotedTableName} (${index.columns\n .map((col) => this.quoteIdentifier(col))\n .join(', ')})`;\n this.db.exec(indexSql);\n }\n }\n }\n\n /**\n * Quote table name to handle special characters in SQL\n */\n private quoteTableName(tableName: string): string {\n return this.quoteIdentifier(tableName);\n }\n\n /**\n * Quote identifier for SQL statements, escaping embedded quotes\n */\n private quoteIdentifier(identifier: string): string {\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\n }\n\n /**\n * Insert data into table\n */\n private insertData(tableName: string, schema: TableSchema, data: JsonObject[]): void {\n const columnNames = schema.columns.map((col) => col.name);\n const quotedColumns = columnNames.map((name) => this.quoteIdentifier(name));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteTableName(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const stmt = this.db.prepare(sql);\n\n for (const row of data) {\n const values = columnNames.map((col) => this.normalizeValue(row[col]));\n stmt.run(...values);\n }\n }\n\n /**\n * Execute a raw SQL query\n */\n query<T = unknown>(\n sql: string,\n params: (string | number | bigint | null | Uint8Array)[] = [],\n ): T[] {\n const stmt = this.db.prepare(sql);\n return stmt.all(...params) as T[];\n }\n\n /**\n * Execute a SQL query that returns a single row\n */\n queryOne<T = unknown>(\n sql: string,\n params: (string | number | bigint | null | Uint8Array)[] = [],\n ): T | null {\n const stmt = this.db.prepare(sql);\n const result = stmt.get(...params);\n return result === undefined ? null : (result as T);\n }\n\n /**\n * Execute a SQL statement (INSERT, UPDATE, DELETE)\n */\n execute(\n sql: string,\n params: (string | number | bigint | null | Uint8Array)[] = [],\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const stmt = this.db.prepare(sql);\n return stmt.run(...params);\n }\n\n /**\n * Find rows by condition (supports OR/AND with arrays and function filters)\n * If where is not provided, returns all rows\n */\n find<K extends keyof Tables & string>(tableName: K, where?: WhereCondition<Tables[K]>) {\n // If no where condition, return all rows\n if (where === undefined) {\n const rows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n return rows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n }\n\n // Handle empty array - should return no results\n if (Array.isArray(where) && where.length === 0) {\n return [];\n }\n\n const { sql, values, functionFilters, hasOrWithFunctionFilters } = this.buildWhereClause(where);\n\n let rows: Tables[K][];\n\n // If OR condition has function filters, get all rows and evaluate in JS\n if (hasOrWithFunctionFilters) {\n const rawRows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n return this.applyOrConditionWithFilters(rows, where as WhereCondition<Tables[K]>);\n }\n\n // Normal case: use SQL WHERE clause\n if (sql) {\n const rawRows = this.query(\n `SELECT * FROM ${this.quoteTableName(tableName)} WHERE ${sql}`,\n values,\n );\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n } else {\n // If only function filters (AND case), get all rows\n const rawRows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n }\n\n // Apply function filters for AND conditions\n return this.applyFunctionFilters(rows, functionFilters);\n }\n\n /**\n * Find a single row by condition (supports OR/AND with arrays and function filters)\n */\n findOne<K extends keyof Tables & string>(tableName: K, where: WhereCondition<Tables[K]>) {\n const { sql, values, functionFilters } = this.buildWhereClause(where);\n\n let rows: Tables[K][];\n if (sql) {\n const rawRows = this.query(\n `SELECT * FROM ${this.quoteTableName(tableName)} WHERE ${sql}`,\n values,\n );\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n } else {\n // If only function filters, get all rows\n const rawRows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n }\n\n // Apply function filters and return first match\n const filtered = this.applyFunctionFilters(rows, functionFilters);\n return filtered.length > 0 ? filtered[0] : null;\n }\n\n /**\n * Deserialize JSON columns in a row\n */\n private deserializeRow<T>(tableName: string, row: T): T {\n const schema = this.schemas.get(tableName);\n if (!schema) return row;\n\n const deserializedRow = { ...row } as Record<string, unknown>;\n\n for (const column of schema.columns) {\n const colName = column.name;\n if (!(colName in deserializedRow)) continue;\n\n const value = deserializedRow[colName];\n\n if (column.type === 'JSON' && typeof value === 'string') {\n try {\n deserializedRow[colName] = JSON.parse(value);\n } catch (error) {\n // If parsing fails, keep the original value\n console.warn(`Failed to parse JSON column ${colName}:`, error);\n }\n continue;\n }\n\n if (column.valueType === 'boolean') {\n if (typeof value === 'number') {\n deserializedRow[colName] = value === 0 ? false : true;\n } else if (typeof value === 'bigint') {\n deserializedRow[colName] = value === 0n ? false : true;\n }\n }\n }\n\n return deserializedRow as T;\n }\n\n /**\n * Validate data using StandardSchema and return the transformed value\n * Note: Only synchronous validation is supported\n */\n private validateAndTransform(tableName: string, data: unknown): JsonObject {\n const schema = this.validationSchemas.get(tableName);\n if (!schema) {\n return data as JsonObject;\n }\n\n const result = schema['~standard'].validate(data);\n\n // Only synchronous validation is supported\n if (result instanceof Promise) {\n throw new Error(\n 'Asynchronous validation is not supported. Please use synchronous validation schemas.',\n );\n }\n\n if (result.issues && result.issues.length > 0) {\n // Format detailed error message with all validation issues\n const issueMessages = result.issues\n .map((issue) => {\n // Handle path: can be array of PathSegment or undefined\n let pathStr = 'root';\n if (issue.path && issue.path.length > 0) {\n pathStr = issue.path\n .map((segment) => {\n // PathSegment can be { key: PropertyKey } or just PropertyKey\n if (typeof segment === 'object' && segment !== null && 'key' in segment) {\n return String(segment.key);\n }\n return String(segment);\n })\n .join('.');\n }\n return ` - ${pathStr}: ${issue.message}`;\n })\n .join('\\n');\n\n const errorMessage = `Validation failed for table '${tableName}':\\n${issueMessages}`;\n const error = new Error(errorMessage) as ValidationError;\n error.name = 'ValidationError';\n error.issues = result.issues;\n throw error;\n }\n\n // Return the transformed value from validation\n // When there are no issues, result.value should be present\n const transformedValue = ('value' in result ? result.value : data) as JsonObject;\n\n // Convert undefined values to null for JSON compatibility\n const normalizedValue: JsonObject = {};\n for (const [key, value] of Object.entries(transformedValue)) {\n normalizedValue[key] = value === undefined ? null : value;\n }\n\n return normalizedValue;\n }\n\n /**\n * Validate data using StandardSchema (without returning transformed value)\n * Note: Only synchronous validation is supported\n */\n private validateData(tableName: string, data: unknown): void {\n // Use validateAndTransform but discard the result\n this.validateAndTransform(tableName, data);\n }\n\n /**\n * Insert a row into a table with validation\n */\n insert<K extends keyof Tables & string>(\n tableName: K,\n data: Tables[K],\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n // Validate if schema exists\n this.validateData(tableName, data);\n\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n const columnNames = Object.keys(data);\n const quotedColumns = columnNames.map((col) => this.quoteIdentifier(col));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteTableName(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const values = Object.values(data).map((v) => this.normalizeValue(v));\n const result = this.execute(sql, values);\n\n // Auto-sync if not in transaction\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return result;\n }\n\n /**\n * Batch insert rows with validation per record.\n */\n batchInsert<K extends keyof Tables & string>(\n tableName: K,\n records: Tables[K][],\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n if (records.length === 0) {\n return { changes: 0, lastInsertRowid: 0 };\n }\n\n let totalChanges = 0n;\n let lastRowid = 0n;\n\n for (const record of records) {\n this.validateData(tableName, record);\n\n const columnNames = Object.keys(record);\n const quotedColumns = columnNames.map((col) => this.quoteIdentifier(col));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteTableName(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const values = columnNames.map((col) => this.normalizeValue(record[col as keyof Tables[K]]));\n\n const result = this.execute(sql, values);\n totalChanges += BigInt(result.changes);\n lastRowid = BigInt(result.lastInsertRowid);\n }\n\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return {\n changes: totalChanges,\n lastInsertRowid: lastRowid,\n };\n }\n\n /**\n * Update rows in a table with validation (supports OR/AND with arrays)\n * Note: Function filters are not supported for update operations\n * Note: By default, validation is enabled. For partial updates, existing data is fetched\n * and merged before validation. Set options.validate = false to disable validation.\n */\n update<K extends keyof Tables & string>(\n tableName: K,\n data: Partial<Tables[K]>,\n where: WhereCondition<Tables[K]>,\n options?: { validate?: boolean },\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n // Validate by default (can be disabled with validate: false)\n const shouldValidate = options?.validate !== false;\n const hasValidationSchema = this.validationSchemas.has(tableName);\n\n if (shouldValidate && hasValidationSchema) {\n // Get existing rows to merge with partial data\n const existingRows = this.find(tableName, where);\n\n // Validate each merged row\n for (const existingRow of existingRows) {\n const mergedData = { ...existingRow, ...data };\n this.validateData(tableName, mergedData);\n }\n }\n\n const { sql: whereSql, values: whereValues, functionFilters } = this.buildWhereClause(where);\n\n if (functionFilters.length > 0) {\n throw new Error('Function filters are not supported in update operations');\n }\n\n const setClauses = Object.keys(data)\n .map((key) => `${this.quoteIdentifier(key)} = ?`)\n .join(', ');\n const sql = `UPDATE ${this.quoteTableName(tableName)} SET ${setClauses} WHERE ${whereSql}`;\n\n const values = [...Object.values(data).map((v) => this.normalizeValue(v)), ...whereValues];\n\n const result = this.execute(sql, values);\n\n // Auto-sync if not in transaction\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return result;\n }\n\n /**\n * Batch update rows with record-specific values and validation.\n * Each record must include the primary key to identify the target row.\n * Validation runs once per merged record unless explicitly disabled.\n */\n batchUpdate<K extends keyof Tables & string>(\n tableName: K,\n records: Array<Partial<Tables[K]> & Record<string, unknown>>,\n options?: { validate?: boolean },\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n if (records.length === 0) {\n return { changes: 0, lastInsertRowid: 0 };\n }\n\n // Get primary key column\n const pkColumn = schema.columns.find((col) => col.primaryKey);\n if (!pkColumn) {\n throw new Error(`Table ${tableName} does not have a primary key`);\n }\n\n const pkName = pkColumn.name;\n\n // Extract primary key values from records\n const pkValues: unknown[] = [];\n for (const record of records) {\n const pkValue = record[pkName];\n if (pkValue === undefined) {\n throw new Error(\n `Record is missing primary key '${String(pkName)}': ${JSON.stringify(record)}`,\n );\n }\n pkValues.push(pkValue);\n }\n\n // Validate by default (can be disabled with validate: false)\n const shouldValidate = options?.validate !== false;\n const hasValidationSchema = this.validationSchemas.has(tableName);\n\n if (shouldValidate && hasValidationSchema) {\n // Build OR condition to fetch all existing rows at once\n const orCondition = pkValues.map((pkValue) => ({\n [pkName]: pkValue,\n })) as WhereCondition<Tables[K]>;\n\n // Fetch all existing rows in one query\n const existingRows = this.find(tableName, orCondition);\n\n // Create a map for fast lookup: pkValue -> existingRow\n const existingRowsMap = new Map<unknown, Tables[K]>();\n for (const row of existingRows) {\n const pkValue = (row as Record<string, unknown>)[pkName];\n existingRowsMap.set(pkValue, row);\n }\n\n // Validate each merged record and collect all errors\n const validationErrors: Array<{\n rowIndex: number;\n rowData: unknown;\n pkValue: unknown;\n error: ValidationError;\n }> = [];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i];\n const pkValue = record[pkName];\n const existingRow = existingRowsMap.get(pkValue);\n\n if (!existingRow) {\n throw new Error(\n `No existing row found with ${String(pkName)}=${JSON.stringify(pkValue)}`,\n );\n }\n\n const mergedData = { ...existingRow, ...record };\n\n try {\n this.validateData(tableName, mergedData);\n } catch (error) {\n // Collect validation errors instead of throwing immediately\n if (error instanceof Error && error.name === 'ValidationError') {\n validationErrors.push({\n rowIndex: i,\n rowData: mergedData,\n pkValue,\n error: error as ValidationError,\n });\n } else {\n throw error;\n }\n }\n }\n\n // If there are validation errors, throw with all error information\n if (validationErrors.length > 0) {\n const enhancedError = new Error(\n `Validation failed for ${validationErrors.length} row(s)`,\n ) as ValidationError & { validationErrors: typeof validationErrors };\n enhancedError.name = 'ValidationError';\n enhancedError.validationErrors = validationErrors;\n // For backward compatibility, include issues from first error\n enhancedError.issues = validationErrors[0].error.issues;\n throw enhancedError;\n }\n }\n\n // All validations passed - perform updates\n let totalChanges = 0n;\n let lastRowid = 0n;\n\n for (const record of records) {\n const pkValue = record[pkName];\n const where = { [pkName]: pkValue } as WhereCondition<Tables[K]>;\n\n // Call update without validation (already validated above)\n const result = this.update(tableName, record as Partial<Tables[K]>, where, {\n validate: false,\n });\n\n totalChanges += BigInt(result.changes);\n lastRowid = BigInt(result.lastInsertRowid);\n }\n\n return {\n changes: totalChanges,\n lastInsertRowid: lastRowid,\n };\n }\n\n /**\n * Delete rows from a table (supports OR/AND with arrays)\n * Note: Function filters are not supported for delete operations\n */\n delete<K extends keyof Tables & string>(\n tableName: K,\n where: WhereCondition<Tables[K]>,\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n const { sql: whereSql, values, functionFilters } = this.buildWhereClause(where);\n\n if (functionFilters.length > 0) {\n throw new Error('Function filters are not supported in delete operations');\n }\n\n const sql = `DELETE FROM ${this.quoteTableName(tableName)} WHERE ${whereSql}`;\n const result = this.execute(sql, values);\n\n // Auto-sync if not in transaction\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return result;\n }\n\n /**\n * Batch delete rows by primary key.\n */\n batchDelete<K extends keyof Tables & string>(\n tableName: K,\n records: Array<Partial<Tables[K]> & Record<string, unknown>>,\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n if (records.length === 0) {\n return { changes: 0, lastInsertRowid: 0 };\n }\n\n const pkColumn = schema.columns.find((col) => col.primaryKey);\n if (!pkColumn) {\n throw new Error(`Table ${tableName} does not have a primary key`);\n }\n const pkName = pkColumn.name;\n\n const pkValues = records.map((record, index) => {\n const pkValue = record[pkName as keyof Tables[K]];\n if (pkValue === undefined) {\n throw new Error(`Record at index ${index} is missing primary key '${String(pkName)}'`);\n }\n return pkValue;\n });\n\n const placeholders = pkValues.map(() => '?').join(', ');\n const sql = `DELETE FROM ${this.quoteTableName(tableName)} WHERE ${this.quoteIdentifier(pkName)} IN (${placeholders})`;\n const values = pkValues.map((value) => this.normalizeValue(value));\n\n const result = this.execute(sql, values);\n\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return {\n changes: BigInt(result.changes),\n lastInsertRowid: BigInt(result.lastInsertRowid),\n };\n }\n\n /**\n * Normalize value for SQLite\n */\n private normalizeValue(value: unknown): string | number | bigint | null | Uint8Array {\n if (value === null || value === undefined) return null;\n if (typeof value === 'boolean') return value ? 1 : 0;\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint')\n return value;\n if (value instanceof Uint8Array) return value;\n // For objects, convert to JSON string\n return JSON.stringify(value);\n }\n\n /**\n * Build WHERE clause from condition (supports OR/AND with arrays and functions)\n */\n private buildWhereClause<T extends Record<string, unknown>>(\n condition: WhereCondition<T>,\n ): {\n sql: string;\n values: Array<string | number | bigint | null | Uint8Array>;\n functionFilters: Array<{\n key: string;\n fn: (value: unknown) => boolean;\n }>;\n hasOrWithFunctionFilters: boolean;\n } {\n const values: Array<string | number | bigint | null | Uint8Array> = [];\n const functionFilters: Array<{ key: string; fn: (value: unknown) => boolean }> = [];\n let hasOrWithFunctionFilters = false;\n\n const buildCondition = (cond: WhereCondition<T>, isInOr = false): string => {\n // Handle array (OR conditions)\n if (Array.isArray(cond)) {\n const clauses = cond\n .map((item) => {\n const clause = Array.isArray(item)\n ? buildCondition(item, true)\n : buildCondition(item, true);\n return clause ? `(${clause})` : '';\n })\n .filter((clause) => clause !== ''); // Filter out empty clauses\n\n return clauses.join(' OR ');\n }\n\n // Handle object (AND conditions)\n const conditions: string[] = [];\n let hasFunctionFilter = false;\n for (const [key, value] of Object.entries(cond)) {\n if (typeof value === 'function') {\n // Function filter - will be applied later\n functionFilters.push({ key, fn: value as (value: unknown) => boolean });\n hasFunctionFilter = true;\n } else {\n // Regular value\n conditions.push(`${this.quoteIdentifier(key)} = ?`);\n values.push(this.normalizeValue(value));\n }\n }\n\n if (isInOr && hasFunctionFilter) {\n hasOrWithFunctionFilters = true;\n }\n\n return conditions.join(' AND ');\n };\n\n const sql = buildCondition(condition);\n return { sql, values, functionFilters, hasOrWithFunctionFilters };\n }\n\n /**\n * Apply OR condition with function filters by evaluating each row against the condition\n */\n private applyOrConditionWithFilters<T extends Record<string, unknown>>(\n rows: T[],\n condition: WhereCondition<T>,\n ): T[] {\n return rows.filter((row) => this.matchesOrCondition(row, condition));\n }\n\n /**\n * Check if a row matches an OR/AND condition (recursively)\n */\n private matchesOrCondition<T extends Record<string, unknown>>(\n row: T,\n condition: WhereCondition<T>,\n ): boolean {\n // Handle array (OR conditions)\n if (Array.isArray(condition)) {\n return condition.some((item) => this.matchesOrCondition(row, item));\n }\n\n // Handle object (AND conditions)\n return Object.entries(condition).every(([key, value]) => {\n const rowValue = row[key as keyof T];\n if (typeof value === 'function') {\n return (value as (value: unknown) => boolean)(rowValue);\n }\n return rowValue === value;\n });\n }\n\n /**\n * Apply function filters to rows\n */\n private applyFunctionFilters<T extends Record<string, unknown>>(\n rows: T[],\n functionFilters: Array<{ key: string; fn: (value: unknown) => boolean }>,\n ): T[] {\n if (functionFilters.length === 0) return rows;\n\n return rows.filter((row) => {\n return functionFilters.every(({ key, fn }) => {\n const value = row[key as keyof T];\n return fn(value);\n });\n });\n }\n\n /**\n * Get table schema\n */\n getSchema(tableName: string): TableSchema | undefined {\n return this.schemas.get(tableName);\n }\n\n /**\n * Get all table names\n */\n getTableNames(): string[] {\n return Array.from(this.schemas.keys());\n }\n\n /**\n * Sync a specific table back to its JSONL file\n * Uses backward transformation when available\n */\n private async syncTable(tableName: string): Promise<void> {\n const tableConfig = this.tables.get(tableName);\n if (!tableConfig) {\n throw new Error(`Table ${tableName} not found`);\n }\n\n // Get all rows from the table\n const rows = this.query<JsonObject>(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n\n // Deserialize JSON columns\n const deserializedRows = rows.map((row) => this.deserializeRow(tableName, row));\n\n // Apply backward transformation if available\n const validationSchema = this.validationSchemas.get(tableName);\n let finalRows = deserializedRows;\n\n if (validationSchema && hasBackward(validationSchema)) {\n const biSchema = validationSchema as BiDirectionalSchema<Table, Table>;\n finalRows = deserializedRows.map((row) => biSchema.backward!(row) as JsonObject);\n }\n\n // Write back to JSONL file\n await JsonlWriter.write(tableConfig.jsonlPath, finalRows);\n }\n\n /**\n * Sync database changes back to JSONL files\n * Uses backward transformation when available\n */\n async sync(): Promise<void> {\n for (const [tableName] of this.tables) {\n await this.syncTable(tableName);\n }\n }\n\n /**\n * Execute a function within a transaction\n * Automatically commits on success or rolls back on error\n */\n async transaction<T>(fn: (tx: LinesDB<Tables>) => Promise<T> | T): Promise<T> {\n if (this.inTransaction) {\n throw new Error('Nested transactions are not supported');\n }\n\n this.db.exec('BEGIN TRANSACTION');\n this.inTransaction = true;\n\n try {\n const result = await fn(this);\n this.db.exec('COMMIT');\n this.inTransaction = false;\n\n // Sync all tables after successful commit\n await this.sync();\n\n return result;\n } catch (error) {\n if (this.inTransaction) {\n this.db.exec('ROLLBACK');\n }\n this.inTransaction = false;\n throw error;\n }\n }\n\n /**\n * Close the database connection\n */\n async close(): Promise<void> {\n try {\n this.db.close();\n } catch (_error) {\n // Ignore errors if database is already closed\n }\n }\n\n /**\n * Get the underlying SQLite database instance\n */\n getDb(): SQLiteDatabase {\n return this.db;\n }\n}\n","import { readdir } from 'node:fs/promises';\nimport { join, relative, basename, dirname, isAbsolute } from 'node:path';\nimport { writeFile, mkdir } from 'node:fs/promises';\n\nexport interface TypeGeneratorOptions {\n dataDir: string;\n projectRoot?: string; // Default: current working directory\n}\n\ninterface TableInfo {\n tableName: string;\n schemaFile?: string;\n}\n\nexport class TypeGenerator {\n private dataDir: string;\n private projectRoot: string;\n private outputFile: string;\n private dataDirPath: string;\n\n constructor(options: TypeGeneratorOptions) {\n // For testing: allow overriding projectRoot via environment variable\n const envProjectRoot = process.env.LINES_DB_TEST_PROJECT_ROOT;\n this.projectRoot =\n envProjectRoot !== undefined ? envProjectRoot : options.projectRoot || process.cwd();\n this.dataDir = options.dataDir;\n this.dataDirPath = isAbsolute(this.dataDir)\n ? this.dataDir\n : join(this.projectRoot, this.dataDir);\n this.outputFile = join(this.dataDirPath, 'db.ts');\n }\n\n /**\n * Generate types file from JSONL files and their optional schema files.\n */\n async generate(): Promise<string> {\n // Find all JSONL files and their corresponding schema files\n const tables = await this.findTables();\n\n if (tables.length === 0) {\n throw new Error(\n `No JSONL files found in ${this.dataDirPath}. Place one or more *.jsonl files in the directory.`,\n );\n }\n\n // Generate type declarations\n const content = this.generateTypeDeclarations(tables);\n\n // Ensure output directory exists\n const outputDir = dirname(this.outputFile);\n await mkdir(outputDir, { recursive: true });\n\n // Write to file\n await writeFile(this.outputFile, content, 'utf-8');\n console.log(`Generated types at ${this.outputFile}`);\n return this.outputFile;\n }\n\n /**\n * Find all *.jsonl files and check if they have corresponding *.schema.ts files\n */\n private async findTables(): Promise<TableInfo[]> {\n try {\n const entries = await readdir(this.dataDirPath, { withFileTypes: true });\n const tables: TableInfo[] = [];\n\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n const tableName = basename(entry.name, '.jsonl');\n const schemaFileName = `${tableName}.schema.ts`;\n const schemaFilePath = join(this.dataDirPath, schemaFileName);\n\n // Check if schema file exists\n const hasSchema = entries.some((e) => e.isFile() && e.name === schemaFileName);\n\n tables.push({\n tableName,\n schemaFile: hasSchema ? schemaFilePath : undefined,\n });\n }\n }\n\n return tables;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(\n `Data directory not found: ${this.dataDirPath}. Set lines-db.dataDir to the correct location.`,\n );\n }\n throw error;\n }\n }\n\n /**\n * Generate type declaration content\n */\n private generateTypeDeclarations(tables: TableInfo[]): string {\n const imports: string[] = [];\n const tableEntries: string[] = [];\n const usedAliases = new Set<string>();\n\n for (const table of tables) {\n const tableKey = this.formatTableKey(table.tableName);\n\n if (table.schemaFile) {\n // Table has a schema file\n const schemaIdentifier = this.createSchemaIdentifier(table.tableName, usedAliases);\n usedAliases.add(schemaIdentifier);\n\n // Calculate relative path from output file to schema file\n let relativePath = relative(join(this.outputFile, '..'), table.schemaFile)\n .replace(/\\\\/g, '/') // Convert Windows paths to Unix-style\n .replace('.ts', '.js'); // Import from .js (TypeScript module resolution)\n\n // Ensure relative path starts with './' or '../'\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath;\n }\n\n // Add import statement for schema\n imports.push(`import { schema as ${schemaIdentifier} } from '${relativePath}';`);\n\n // Add table entry with InferOutput\n tableEntries.push(` ${tableKey}: InferOutput<typeof ${schemaIdentifier}>;`);\n } else {\n // Table has no schema file, use Record<string, unknown>\n tableEntries.push(` ${tableKey}: Record<string, unknown>;`);\n }\n }\n\n // Generate full content\n const importSection = imports.length > 0 ? `${imports.join('\\n')}\\n` : '';\n const inferOutputImport = imports.length > 0 ? ', InferOutput' : '';\n\n return `// Auto-generated by lines-db\n// Do not edit this file manually\n\n${importSection}import type { DatabaseConfig${inferOutputImport} } from '@toiroakr/lines-db';\nimport { fileURLToPath } from 'node:url';\nimport { dirname } from 'node:path';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport type Tables = {\n${tableEntries.join('\\n')}\n};\n\nexport const config: DatabaseConfig<Tables> = {\n dataDir: __dirname,\n};\n`;\n }\n\n private createSchemaIdentifier(tableName: string, usedAliases: Set<string>): string {\n const camel = toCamelCase(tableName);\n const sanitizedBase = sanitizeIdentifier(camel);\n let base = sanitizedBase || 'table';\n\n if (!/^[A-Za-z_$]/.test(base)) {\n base = `_${base}`;\n }\n\n let candidate = `${base}Schema`;\n let suffix = 1;\n while (usedAliases.has(candidate)) {\n candidate = `${base}${++suffix}Schema`;\n }\n\n return candidate;\n }\n\n private formatTableKey(tableName: string): string {\n const identifierPattern = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n if (identifierPattern.test(tableName)) {\n return tableName;\n }\n const escaped = tableName.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n return `'${escaped}'`;\n }\n}\n\nfunction toCamelCase(value: string): string {\n const parts = value\n .split(/[^A-Za-z0-9]+/)\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n\n if (parts.length === 0) {\n return value;\n }\n\n const [first, ...rest] = parts;\n return first + rest.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('');\n}\n\nfunction sanitizeIdentifier(value: string): string {\n return value.replace(/[^A-Za-z0-9_$]/g, '');\n}\n","import { readdir, stat } from 'node:fs/promises';\nimport { join, basename, dirname } from 'node:path';\nimport { JsonlReader } from './jsonl-reader.js';\nimport { SchemaLoader } from './schema-loader.js';\nimport { LinesDB } from './database.js';\nimport type { StandardSchemaIssue } from './types.js';\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationErrorDetail[];\n warnings: string[];\n}\n\nexport interface ValidationErrorDetail {\n file: string;\n tableName: string;\n rowIndex: number;\n issues: ReadonlyArray<StandardSchemaIssue>;\n type?: 'schema' | 'foreignKey';\n foreignKeyError?: {\n column: string;\n value: unknown;\n referencedTable: string;\n referencedColumn: string;\n };\n}\n\nexport interface ValidatorOptions {\n path: string; // File or directory path\n projectRoot?: string;\n}\n\nexport class Validator {\n private path: string;\n private projectRoot: string;\n\n constructor(options: ValidatorOptions) {\n this.path = options.path;\n this.projectRoot = options.projectRoot || process.cwd();\n }\n\n /**\n * Validate JSONL file(s)\n */\n async validate(): Promise<ValidationResult> {\n // Use absolute path if provided, otherwise resolve relative to projectRoot\n const fullPath = this.path.startsWith('/') ? this.path : join(this.projectRoot, this.path);\n const stats = await stat(fullPath);\n\n if (stats.isDirectory()) {\n return this.validateDirectory(fullPath);\n } else if (stats.isFile() && fullPath.endsWith('.jsonl')) {\n return this.validateFile(fullPath);\n } else {\n throw new Error(`Invalid path: ${this.path}. Must be a directory or .jsonl file.`);\n }\n }\n\n /**\n * Validate all JSONL files in a directory\n */\n private async validateDirectory(dirPath: string): Promise<ValidationResult> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const jsonlFiles = entries\n .filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl'))\n .map((entry) => join(dirPath, entry.name));\n\n if (jsonlFiles.length === 0) {\n throw new Error(`No JSONL files found in directory: ${dirPath}`);\n }\n\n const allErrors: ValidationErrorDetail[] = [];\n const allWarnings: string[] = [];\n const filesWithSchema: string[] = [];\n\n // Filter files with schema and collect warnings for files without schema\n for (const file of jsonlFiles) {\n const hasSchema = await SchemaLoader.hasSchema(file);\n if (hasSchema) {\n filesWithSchema.push(file);\n } else {\n const tableName = basename(file, '.jsonl');\n allWarnings.push(`Skipping validation for '${tableName}': schema file not found`);\n }\n }\n\n // Validate schema for each file with schema\n for (const file of filesWithSchema) {\n const result = await this.validateFile(file);\n allErrors.push(...result.errors);\n allWarnings.push(...result.warnings);\n }\n\n // Then, validate by actually loading into database\n if (filesWithSchema.length > 0 && allErrors.length === 0) {\n const dbErrors = await this.validateWithDatabase(dirPath, filesWithSchema);\n allErrors.push(...dbErrors);\n }\n\n return {\n valid: allErrors.length === 0,\n errors: allErrors,\n warnings: allWarnings,\n };\n }\n\n /**\n * Validate by loading data into an actual database\n * This catches constraint violations (unique, primary key, foreign key, etc.)\n */\n private async validateWithDatabase(\n dirPath: string,\n jsonlFiles: string[],\n ): Promise<ValidationErrorDetail[]> {\n const errors: ValidationErrorDetail[] = [];\n\n // Capture console.warn messages\n const warnMessages: string[] = [];\n const originalWarn = console.warn;\n console.warn = (...args: unknown[]) => {\n const message = args.map((arg) => String(arg)).join(' ');\n warnMessages.push(message);\n // Still output to console for debugging\n originalWarn(...args);\n };\n\n try {\n // Try to initialize database with the data directory\n const db = LinesDB.create({ dataDir: dirPath });\n await db.initialize();\n await db.close();\n\n // Check if there were any loading errors\n for (const message of warnMessages) {\n if (message.includes('Failed to load table')) {\n // Extract table name from message\n const tableNameMatch = message.match(/Failed to load table '([^']+)'/);\n const tableName = tableNameMatch ? tableNameMatch[1] : 'unknown';\n\n const file = jsonlFiles.find((f) => basename(f, '.jsonl') === tableName);\n\n errors.push({\n file: file || `${dirPath}/${tableName}.jsonl`,\n tableName,\n rowIndex: 0,\n issues: [\n {\n message: message.replace(/^Warning:\\s*/, ''),\n path: [],\n },\n ],\n type: 'schema',\n });\n }\n }\n } catch (error) {\n // If initialization itself fails, report it\n errors.push({\n file: dirPath,\n tableName: 'database',\n rowIndex: 0,\n issues: [\n {\n message: `Database initialization failed: ${error instanceof Error ? error.message : String(error)}`,\n path: [],\n },\n ],\n type: 'schema',\n });\n } finally {\n // Restore console.warn\n console.warn = originalWarn;\n }\n\n return errors;\n }\n\n /**\n * Validate a single JSONL file\n */\n private async validateFile(filePath: string): Promise<ValidationResult> {\n const tableName = basename(filePath, '.jsonl');\n const data = await JsonlReader.read(filePath);\n\n // Try to load schema\n const schema = await SchemaLoader.loadSchema(filePath);\n\n const errors: ValidationErrorDetail[] = [];\n\n // Validate each row with schema\n for (let i = 0; i < data.length; i++) {\n const row = data[i];\n const result = schema['~standard'].validate(row);\n\n // Only synchronous validation is supported\n if (result instanceof Promise) {\n throw new Error('Asynchronous validation is not supported.');\n }\n\n if (result.issues && result.issues.length > 0) {\n errors.push({\n file: filePath,\n tableName,\n rowIndex: i, // 0-indexed, will be converted to 1-indexed in formatter\n issues: result.issues,\n type: 'schema',\n });\n }\n }\n\n // If schema validation passed, validate with database\n if (errors.length === 0) {\n const dirPath = dirname(filePath);\n const dbErrors = await this.validateWithDatabase(dirPath, [filePath]);\n errors.push(...dbErrors);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings: [],\n };\n }\n}\n","import { join } from 'node:path';\nimport type { JsonObject } from './types.js';\nimport { JsonlReader } from './jsonl-reader.js';\nimport { LinesDB } from './database.js';\n\nexport interface TableValidationOptions {\n dataDir: string;\n tableName: string;\n rows: JsonObject[];\n}\n\n/**\n * Validate a table by temporarily supplying in-memory rows while reusing the existing LinesDB validation pipeline.\n * If validation fails, the underlying LinesDB error is rethrown so callers can inspect validation details.\n */\nexport async function ensureTableRowsValid(options: TableValidationOptions): Promise<void> {\n console.log('[ensureTableRowsValid] START');\n console.log('[ensureTableRowsValid] dataDir:', options.dataDir);\n console.log('[ensureTableRowsValid] tableName:', options.tableName);\n console.log('[ensureTableRowsValid] rows count:', options.rows.length);\n\n const tablePath = join(options.dataDir, `${options.tableName}.jsonl`);\n const overrides = new Map<string, JsonObject[]>([[tablePath, options.rows]]);\n console.log('[ensureTableRowsValid] tablePath:', tablePath);\n\n let capturedError: Error | null = null;\n\n // Intercept console.warn to capture validation errors\n const originalWarn = console.warn;\n const warnMessages: string[] = [];\n console.warn = (...args: any[]) => {\n const message = args.join(' ');\n console.log('[ensureTableRowsValid] Captured warn:', message);\n warnMessages.push(message);\n // Check if this is a validation error for our table\n if (\n message.includes(`Failed to load table '${options.tableName}'`) &&\n message.includes('Validation failed')\n ) {\n // Extract the original error from the warn message\n capturedError = new Error(message);\n console.log('[ensureTableRowsValid] Captured validation error!');\n }\n };\n\n try {\n console.log('[ensureTableRowsValid] Calling JsonlReader.withOverrides');\n await JsonlReader.withOverrides(overrides, async () => {\n console.log('[ensureTableRowsValid] Inside withOverrides callback');\n const db = LinesDB.create({ dataDir: options.dataDir });\n console.log('[ensureTableRowsValid] LinesDB created');\n try {\n console.log('[ensureTableRowsValid] Calling db.initialize()');\n await db.initialize();\n console.log('[ensureTableRowsValid] db.initialize() completed');\n } finally {\n console.log('[ensureTableRowsValid] Calling db.close()');\n await db.close();\n }\n });\n console.log('[ensureTableRowsValid] withOverrides completed');\n } finally {\n // Restore original console.warn\n console.warn = originalWarn;\n }\n\n console.log('[ensureTableRowsValid] Warnings captured:', warnMessages.length);\n console.log('[ensureTableRowsValid] capturedError:', capturedError ? 'YES' : 'NO');\n\n if (capturedError) {\n console.log('[ensureTableRowsValid] Throwing captured error');\n throw capturedError;\n }\n\n console.log('[ensureTableRowsValid] END (success)');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["columns: ColumnDefinition[]","sqlType: ColumnDefinition['type']","readFile","writeFile","foreignKeys: BiDirectionalSchema['foreignKeys']","pathToFileURL","schemaMetadata: {\n primaryKey?: string;\n foreignKeys?: BiDirectionalSchema['foreignKeys'];\n indexes?: BiDirectionalSchema['indexes'];\n }","validationErrors: Array<{\n rowIndex: number;\n rowData: JsonObject;\n error: ValidationError;\n }>","validatedData: JsonObject[]","schema: TableSchema","foreignKeyDefs: string[]","rows: Tables[K][]","normalizedValue: JsonObject","pkValues: unknown[]","validationErrors: Array<{\n rowIndex: number;\n rowData: unknown;\n pkValue: unknown;\n error: ValidationError;\n }>","values: Array<string | number | bigint | null | Uint8Array>","functionFilters: Array<{ key: string; fn: (value: unknown) => boolean }>","conditions: string[]","tables: TableInfo[]","imports: string[]","tableEntries: string[]","allErrors: ValidationErrorDetail[]","allWarnings: string[]","filesWithSchema: string[]","errors: ValidationErrorDetail[]","schema: any","foreignKeys: any[]","indexes: any[]","primaryKey: string | undefined","pathToFileURL","capturedError: Error | null","warnMessages: string[]"],"sources":["../src/runtime.ts","../src/sqlite-adapter.ts","../src/jsonl-reader.ts","../src/jsonl-writer.ts","../src/schema-loader.ts","../src/directory-scanner.ts","../src/schema.ts","../src/database.ts","../src/type-generator.ts","../src/validator.ts","../src/jsonl-migration.ts"],"sourcesContent":["/**\n * Runtime detection utilities\n */\n\nexport type RuntimeEnvironment = 'node' | 'unknown';\n\nexport function detectRuntime(): RuntimeEnvironment {\n // Check for Node.js\n if (typeof process !== 'undefined' && process.versions && process.versions.node) {\n return 'node';\n }\n\n return 'unknown';\n}\n\nexport const RUNTIME = detectRuntime();\n","/**\n * SQLite adapter for Node.js\n */\n\nimport { RUNTIME } from './runtime.js';\n\n/**\n * Common interface for SQLite database\n */\nexport interface SQLiteDatabase {\n prepare(sql: string): SQLiteStatement;\n exec(sql: string): void;\n close(): void;\n}\n\nexport interface SQLiteStatement {\n run(...params: any[]): { changes: number; lastInsertRowid: number | bigint };\n get(...params: any[]): any;\n all(...params: any[]): any[];\n}\n\n/**\n * Create a SQLite database instance for Node.js\n */\nexport function createDatabase(path: string = ':memory:'): SQLiteDatabase {\n if (RUNTIME === 'node') {\n return createNodeDatabase(path);\n } else {\n throw new Error(`Unsupported runtime: ${RUNTIME}`);\n }\n}\n\n/**\n * Create a Node.js SQLite database\n */\nfunction createNodeDatabase(path: string): SQLiteDatabase {\n // Dynamic import for Node.js\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite');\n const db = new DatabaseSync(path);\n\n // CRITICAL: Enable foreign key constraints\n // SQLite disables foreign keys by default, which is a major data integrity issue\n db.exec('PRAGMA foreign_keys = ON');\n\n return {\n prepare(sql: string): SQLiteStatement {\n const stmt = db.prepare(sql);\n return {\n run(...params: any[]) {\n return stmt.run(...params);\n },\n get(...params: any[]) {\n return stmt.get(...params);\n },\n all(...params: any[]) {\n return stmt.all(...params);\n },\n };\n },\n exec(sql: string): void {\n db.exec(sql);\n },\n close(): void {\n db.close();\n },\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { normalize } from 'node:path';\nimport type { JsonObject, ColumnDefinition, TableSchema } from './types.js';\n\nexport class JsonlReader {\n private static overrides: Map<string, JsonObject[]> | null = null;\n\n /**\n * Temporarily override the data returned for specific JSONL files.\n * Useful for scenarios like migration validation where in-memory data should be used.\n */\n static async withOverrides<T>(\n overrides: Map<string, JsonObject[]>,\n fn: () => Promise<T>,\n ): Promise<T> {\n const normalized = new Map<string, JsonObject[]>();\n for (const [filePath, rows] of overrides) {\n normalized.set(normalize(filePath), rows);\n }\n\n const previousOverrides = this.overrides;\n this.overrides = normalized;\n\n try {\n return await fn();\n } finally {\n this.overrides = previousOverrides;\n }\n }\n\n /**\n * Read JSONL file and parse each line as JSON\n */\n static async read(filePath: string): Promise<JsonObject[]> {\n const overrideRows = this.overrides?.get(normalize(filePath));\n if (overrideRows) {\n // Return clones to avoid accidental mutations from consumers\n return overrideRows.map((row) => JSON.parse(JSON.stringify(row)) as JsonObject);\n }\n\n const content = await readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n');\n\n return lines\n .filter((line) => line.trim().length > 0)\n .map((line) => {\n try {\n return JSON.parse(line) as JsonObject;\n } catch (error) {\n throw new Error(`Failed to parse JSON line: ${line}`, { cause: error });\n }\n });\n }\n\n /**\n * Infer schema from JSONL data\n */\n static inferSchema(tableName: string, data: JsonObject[]): TableSchema {\n if (data.length === 0) {\n throw new Error('Cannot infer schema from empty data');\n }\n\n const columnTypes = new Map<string, Set<string>>();\n const booleanColumns = new Set<string>();\n const nonBooleanColumns = new Set<string>();\n\n // Collect all column names and their types\n for (const row of data) {\n for (const [key, value] of Object.entries(row)) {\n if (!columnTypes.has(key)) {\n columnTypes.set(key, new Set());\n }\n columnTypes.get(key)!.add(this.inferType(value));\n\n if (typeof value === 'boolean') {\n booleanColumns.add(key);\n } else if (value !== null) {\n nonBooleanColumns.add(key);\n }\n }\n }\n\n // Convert to column definitions\n const columns: ColumnDefinition[] = [];\n for (const [columnName, types] of columnTypes.entries()) {\n const typeArray = Array.from(types);\n\n // If multiple types exist, prefer TEXT as a safe fallback\n let sqlType: ColumnDefinition['type'] = 'TEXT';\n\n if (typeArray.length === 1) {\n sqlType = typeArray[0] as ColumnDefinition['type'];\n } else if (typeArray.every((t) => t === 'INTEGER' || t === 'REAL')) {\n sqlType = 'REAL'; // Use REAL if we have mixed numeric types\n } else if (!typeArray.includes('NULL')) {\n // If there are multiple non-null types, use TEXT\n sqlType = 'TEXT';\n } else if (typeArray.length === 2 && typeArray.includes('NULL')) {\n // If one type + NULL, use the non-null type\n sqlType = typeArray.find((t) => t !== 'NULL') as ColumnDefinition['type'];\n }\n\n const isBooleanColumn = booleanColumns.has(columnName) && !nonBooleanColumns.has(columnName);\n\n columns.push({\n name: columnName,\n type: sqlType,\n notNull: !typeArray.includes('NULL'),\n valueType: isBooleanColumn ? 'boolean' : undefined,\n });\n }\n\n // If there's an 'id' column, make it primary key\n const idColumn = columns.find((col) => col.name === 'id');\n if (idColumn) {\n idColumn.primaryKey = true;\n }\n\n return {\n name: tableName,\n columns,\n };\n }\n\n private static inferType(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number') {\n return Number.isInteger(value) ? 'INTEGER' : 'REAL';\n }\n if (typeof value === 'string') return 'TEXT';\n if (typeof value === 'boolean') return 'INTEGER'; // SQLite stores booleans as integers\n if (typeof value === 'object') return 'JSON'; // Store objects/arrays as JSON\n return 'TEXT';\n }\n}\n","import { writeFile } from 'node:fs/promises';\nimport type { JsonObject } from './types.js';\n\nexport class JsonlWriter {\n /**\n * Write data to JSONL file\n */\n static async write(filePath: string, data: JsonObject[]): Promise<void> {\n const lines = data.map((obj) => JSON.stringify(obj)).join('\\n');\n await writeFile(filePath, lines + '\\n', 'utf-8');\n }\n\n /**\n * Append data to JSONL file\n */\n static async append(filePath: string, data: JsonObject[]): Promise<void> {\n const { readFile, writeFile } = await import('node:fs/promises');\n\n try {\n const existing = await readFile(filePath, 'utf-8');\n const lines = data.map((obj) => JSON.stringify(obj)).join('\\n');\n const newContent = existing.trim() + '\\n' + lines + '\\n';\n await writeFile(filePath, newContent, 'utf-8');\n } catch (error) {\n // If file doesn't exist, just write the data\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n await this.write(filePath, data);\n } else {\n throw error;\n }\n }\n }\n}\n","import { pathToFileURL } from 'node:url';\nimport { access } from 'node:fs/promises';\nimport { dirname, join, basename } from 'node:path';\nimport type { StandardSchema } from './types.js';\n\nexport class SchemaLoader {\n /**\n * Check if a schema file exists for a table\n */\n static async hasSchema(jsonlPath: string): Promise<boolean> {\n const dir = dirname(jsonlPath);\n const tableName = basename(jsonlPath, '.jsonl');\n const schemaPath = join(dir, `${tableName}.schema.ts`);\n\n try {\n await access(schemaPath);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Load a validation schema file for a table\n * Requires ${tableName}.schema.ts to exist alongside the JSONL file\n */\n static async loadSchema(jsonlPath: string): Promise<StandardSchema> {\n const dir = dirname(jsonlPath);\n const tableName = basename(jsonlPath, '.jsonl');\n const schemaPath = join(dir, `${tableName}.schema.ts`);\n\n try {\n await access(schemaPath);\n } catch (error) {\n throw new Error(`Schema file not found for table '${tableName}'. Expected: ${schemaPath}`, {\n cause: error instanceof Error ? error : undefined,\n });\n }\n\n try {\n const schemaUrl = pathToFileURL(schemaPath).href;\n // Add cache busting query parameter to force reload on each import\n // This ensures schema changes are picked up immediately\n const cacheBustedUrl = `${schemaUrl}?t=${Date.now()}`;\n const module = await import(cacheBustedUrl);\n const schema = module.default || module.schema;\n\n if (schema && this.isStandardSchema(schema)) {\n return schema;\n }\n\n throw new Error(`Schema file ${schemaPath} does not export a valid StandardSchema`);\n } catch (error) {\n throw new Error(\n `Failed to load schema for table '${tableName}' from ${schemaPath}: ${error instanceof Error ? error.message : String(error)}`,\n { cause: error instanceof Error ? error : undefined },\n );\n }\n }\n\n /**\n * Check if an object implements the StandardSchema interface\n */\n private static isStandardSchema(obj: unknown): obj is StandardSchema {\n if (!obj || typeof obj !== 'object') return false;\n\n const schema = obj as Record<string, unknown>;\n const standard = schema['~standard'];\n\n if (!standard || typeof standard !== 'object') return false;\n\n const standardObj = standard as Record<string, unknown>;\n\n return (\n standardObj.version === 1 &&\n typeof standardObj.vendor === 'string' &&\n typeof standardObj.validate === 'function'\n );\n }\n}\n","import { readdir } from 'node:fs/promises';\nimport { join, basename, extname } from 'node:path';\nimport type { TableConfig } from './types.js';\n\nexport class DirectoryScanner {\n /**\n * Scan directory for JSONL files and create table configurations\n */\n static async scanDirectory(dataDir: string): Promise<Map<string, TableConfig>> {\n const tables = new Map<string, TableConfig>();\n\n try {\n const files = await readdir(dataDir);\n\n for (const file of files) {\n if (extname(file) === '.jsonl') {\n const tableName = basename(file, '.jsonl');\n const jsonlPath = join(dataDir, file);\n\n tables.set(tableName, {\n jsonlPath,\n autoInferSchema: true,\n });\n }\n }\n\n if (tables.size === 0) {\n console.warn(`Warning: No JSONL files found in directory: ${dataDir}`);\n }\n\n return tables;\n } catch (error) {\n throw new Error(\n `Failed to scan directory ${dataDir}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n","import type { StandardSchema, Table, ForeignKeyDefinition, IndexDefinition } from './types.js';\n\n/**\n * Schema options for defining constraints and indexes\n */\nexport interface SchemaOptions {\n /**\n * Primary key column\n */\n primaryKey?: string;\n\n /**\n * Foreign key constraints\n */\n foreignKeys?: ForeignKeyDefinition[];\n\n /**\n * Indexes to create\n */\n indexes?: IndexDefinition[];\n\n /**\n * Backward transformation from Output to Input\n * Required when Input and Output types differ (e.g., with transformations)\n */\n backward?: (output: Table) => Table;\n}\n\n/**\n * BiDirectional Schema interface\n * Extends StandardSchema with optional backward transformation and schema metadata\n */\nexport interface BiDirectionalSchema<Input extends Table = Table, Output extends Table = Input>\n extends StandardSchema<Input, Output> {\n /**\n * Backward transformation from Output to Input\n * Required when Input and Output types differ (e.g., with transformations)\n */\n backward?: (output: Output) => Input;\n\n /**\n * Primary key column\n */\n primaryKey?: string;\n\n /**\n * Foreign key constraints\n */\n foreignKeys?: ForeignKeyDefinition[];\n\n /**\n * Indexes to create\n */\n indexes?: IndexDefinition[];\n}\n\n/**\n * Define a bidirectional schema with optional backward transformation\n *\n * @param schema - Standard Schema for validation\n * @param optionsOrBackward - Optional SchemaOptions object or backward transformation function (Output → Input)\n * Required when schema performs transformations\n *\n * @example\n * // No transformation - backward not needed\n * const schema = defineSchema(\n * v.object({ id: v.number(), name: v.string() })\n * );\n *\n * @example\n * // With transformation - backward recommended (legacy)\n * const schema = defineSchema(\n * v.pipe(v.string(), v.transform(Number)),\n * (num) => String(num) // backward: number → string\n * );\n *\n * @example\n * // With primary key and foreign key\n * const schema = defineSchema(\n * v.object({ id: v.number(), customerId: v.number() }),\n * {\n * primaryKey: 'id',\n * foreignKeys: [\n * { column: 'customerId', references: { table: 'users', column: 'id' } }\n * ]\n * }\n * );\n */\nexport function defineSchema<Input extends Table, Output extends Table>(\n schema: StandardSchema<Input, Output>,\n optionsOrBackward?: SchemaOptions | ((output: Output) => Input),\n): BiDirectionalSchema<Input, Output> {\n // Create a new object that extends the schema\n const bidirectionalSchema = Object.create(schema) as BiDirectionalSchema<Input, Output>;\n\n // Handle options or backward function\n if (optionsOrBackward) {\n if (typeof optionsOrBackward === 'function') {\n // Legacy: backward function only\n bidirectionalSchema.backward = optionsOrBackward;\n } else {\n // New: options object\n if (optionsOrBackward.backward) {\n bidirectionalSchema.backward = optionsOrBackward.backward as (output: Output) => Input;\n }\n if (optionsOrBackward.primaryKey) {\n bidirectionalSchema.primaryKey = optionsOrBackward.primaryKey;\n }\n if (optionsOrBackward.foreignKeys) {\n bidirectionalSchema.foreignKeys = optionsOrBackward.foreignKeys;\n }\n if (optionsOrBackward.indexes) {\n bidirectionalSchema.indexes = optionsOrBackward.indexes;\n }\n }\n }\n\n // Copy '~standard' property\n Object.defineProperty(bidirectionalSchema, '~standard', {\n value: schema['~standard'],\n enumerable: true,\n configurable: true,\n });\n\n return bidirectionalSchema;\n}\n\n/**\n * Check if a schema has backward transformation\n */\nexport function hasBackward<Input extends Table, Output extends Table>(\n schema: StandardSchema<Input, Output>,\n): schema is BiDirectionalSchema<Input, Output> {\n return 'backward' in schema && typeof (schema as { backward?: unknown }).backward === 'function';\n}\n","import { createDatabase, type SQLiteDatabase } from './sqlite-adapter.js';\nimport { JsonlReader } from './jsonl-reader.js';\nimport { JsonlWriter } from './jsonl-writer.js';\nimport { SchemaLoader } from './schema-loader.js';\nimport { DirectoryScanner } from './directory-scanner.js';\nimport { hasBackward } from './schema.js';\nimport type {\n DatabaseConfig,\n TableSchema,\n JsonObject,\n TableConfig,\n StandardSchema,\n StandardSchemaIssue,\n ValidationError,\n Table,\n TableDefs,\n WhereCondition,\n} from './types.js';\nimport type { BiDirectionalSchema } from './schema.js';\n\nexport class LinesDB<Tables extends TableDefs> {\n private db: SQLiteDatabase;\n private config: DatabaseConfig<Tables>;\n private schemas: Map<string, TableSchema> = new Map();\n private validationSchemas: Map<string, StandardSchema | undefined> = new Map();\n private tables: Map<string, TableConfig> = new Map();\n private inTransaction: boolean = false;\n\n private constructor(config: DatabaseConfig<Tables>, dbPath?: string) {\n this.config = config;\n this.db = createDatabase(dbPath ?? ':memory:');\n }\n\n static create<Tables extends TableDefs>(\n config: DatabaseConfig<Tables>,\n dbPath?: string,\n ): LinesDB<Tables> {\n return new LinesDB<Tables>(config, dbPath);\n }\n\n /**\n * Initialize database by loading all JSONL files\n * Uses dependency resolution to ensure foreign key references are loaded in correct order\n */\n async initialize(): Promise<void> {\n // Scan directory for JSONL files\n this.tables = await DirectoryScanner.scanDirectory(this.config.dataDir);\n\n // Track loaded tables and tables currently being loaded (for circular dependency detection)\n const loadedTables = new Set<string>();\n const loadingTables = new Set<string>();\n\n // Load all tables with dependency resolution\n for (const [tableName] of this.tables) {\n if (!loadedTables.has(tableName)) {\n try {\n await this.loadTableWithDependencies(tableName, loadedTables, loadingTables);\n } catch (error) {\n // Log error but continue loading other tables\n console.warn(\n `Warning: Failed to load table '${tableName}':`,\n error instanceof Error ? error.message : String(error),\n );\n // Remove the failed table from the tables map\n this.tables.delete(tableName);\n this.schemas.delete(tableName);\n this.validationSchemas.delete(tableName);\n }\n }\n }\n }\n\n /**\n * Load a table and its dependencies recursively\n */\n private async loadTableWithDependencies(\n tableName: string,\n loadedTables: Set<string>,\n loadingTables: Set<string>,\n ): Promise<void> {\n // Skip if already loaded\n if (loadedTables.has(tableName)) {\n return;\n }\n\n // Check for circular dependencies\n if (loadingTables.has(tableName)) {\n throw new Error(`Circular dependency detected for table '${tableName}'`);\n }\n\n // Get table config\n const tableConfig = this.tables.get(tableName);\n if (!tableConfig) {\n throw new Error(`Table configuration not found for '${tableName}'`);\n }\n\n // Mark as currently loading\n loadingTables.add(tableName);\n\n try {\n // Load schema module to check for foreign key dependencies\n // We need to load the entire module to access foreignKeys export\n let foreignKeys: BiDirectionalSchema['foreignKeys'];\n\n try {\n const { pathToFileURL } = await import('node:url');\n const schemaPath = tableConfig.jsonlPath.replace('.jsonl', '.schema.ts');\n const schemaUrl = pathToFileURL(schemaPath).href;\n const schemaModule = await import(`${schemaUrl}?t=${Date.now()}`);\n\n // Try to get foreign keys from exported 'schema' or directly from module\n const schemaExport = schemaModule.schema || schemaModule.default;\n foreignKeys = schemaExport?.foreignKeys || schemaModule.foreignKeys;\n } catch {\n // Schema file not found - will continue without validation\n }\n\n // If there are foreign key dependencies, load them first\n if (foreignKeys && foreignKeys.length > 0) {\n for (const fk of foreignKeys) {\n const referencedTable = fk.references.table;\n if (!loadedTables.has(referencedTable)) {\n // Check if referenced table exists in our tables map\n if (this.tables.has(referencedTable)) {\n await this.loadTableWithDependencies(referencedTable, loadedTables, loadingTables);\n } else {\n throw new Error(\n `Foreign key reference to non-existent table '${referencedTable}' in table '${tableName}'`,\n );\n }\n }\n }\n }\n\n // Now load this table\n const wasLoaded = await this.loadTable(tableName, tableConfig);\n if (wasLoaded) {\n loadedTables.add(tableName);\n } else {\n // Table was not loaded (e.g., empty data)\n this.tables.delete(tableName);\n }\n } finally {\n // Remove from loading set\n loadingTables.delete(tableName);\n }\n }\n\n /**\n * Load a single table from JSONL file\n * @returns true if table was loaded, false if skipped\n */\n private async loadTable(tableName: string, config: TableConfig): Promise<boolean> {\n // Read JSONL file\n const data = await JsonlReader.read(config.jsonlPath);\n\n // Load validation schema if provided or try to auto-load\n let validationSchema = config.validationSchema;\n const schemaMetadata: {\n primaryKey?: string;\n foreignKeys?: BiDirectionalSchema['foreignKeys'];\n indexes?: BiDirectionalSchema['indexes'];\n } = {};\n\n if (!validationSchema) {\n try {\n validationSchema = await SchemaLoader.loadSchema(config.jsonlPath);\n } catch (_error) {\n // Schema file not found or failed to load - this is OK, table can still be used without validation\n }\n }\n\n // Load schema metadata (foreignKeys, primaryKey, indexes) from schema module\n // SchemaLoader.loadSchema() only returns the validation schema object, not metadata\n if (!config.validationSchema) {\n // Only load if not already provided via config\n try {\n const { pathToFileURL } = await import('node:url');\n const schemaPath = config.jsonlPath.replace('.jsonl', '.schema.ts');\n const schemaUrl = pathToFileURL(schemaPath).href;\n const schemaModule = await import(`${schemaUrl}?t=${Date.now()}`);\n\n // Try to get metadata from exported 'schema' or directly from module\n const schemaExport = schemaModule.schema || schemaModule.default;\n\n if (schemaExport?.primaryKey) {\n schemaMetadata.primaryKey = schemaExport.primaryKey;\n } else if (schemaModule.primaryKey) {\n schemaMetadata.primaryKey = schemaModule.primaryKey;\n }\n\n if (schemaExport?.foreignKeys) {\n schemaMetadata.foreignKeys = schemaExport.foreignKeys;\n } else if (schemaModule.foreignKeys) {\n schemaMetadata.foreignKeys = schemaModule.foreignKeys;\n }\n\n if (schemaExport?.indexes) {\n schemaMetadata.indexes = schemaExport.indexes;\n } else if (schemaModule.indexes) {\n schemaMetadata.indexes = schemaModule.indexes;\n }\n } catch (_error) {\n // Schema file not found - this is OK\n }\n }\n\n this.validationSchemas.set(tableName, validationSchema);\n\n // Validate data first and collect validated (transformed) data\n const validationErrors: Array<{\n rowIndex: number;\n rowData: JsonObject;\n error: ValidationError;\n }> = [];\n const validatedData: JsonObject[] = [];\n\n for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {\n const row = data[rowIndex];\n try {\n const validatedRow = this.validateAndTransform(tableName, row);\n validatedData.push(validatedRow);\n } catch (error) {\n if (error instanceof Error && error.name === 'ValidationError') {\n validationErrors.push({\n rowIndex,\n rowData: row,\n error: error as ValidationError,\n });\n } else {\n throw error;\n }\n }\n }\n\n if (validationErrors.length > 0) {\n const enhancedError = new Error(\n `Validation failed for ${validationErrors.length} row(s) in table ${tableName}`,\n );\n enhancedError.name = 'ValidationError';\n (enhancedError as unknown as { validationErrors: typeof validationErrors }).validationErrors =\n validationErrors;\n (enhancedError as unknown as { issues: ReadonlyArray<StandardSchemaIssue> }).issues =\n validationErrors[0].error.issues;\n throw enhancedError;\n }\n\n // Determine schema - infer from validated data if auto-inference is enabled\n let schema: TableSchema;\n if (config.schema) {\n schema = config.schema;\n } else if (config.autoInferSchema !== false) {\n if (validatedData.length === 0) {\n return false;\n }\n // Infer schema from validated data (which may have additional fields added by validation)\n schema = JsonlReader.inferSchema(tableName, validatedData);\n } else {\n throw new Error(`No schema provided for table ${tableName} and autoInferSchema is disabled`);\n }\n\n // Enhance schema with constraints from validation schema and schema metadata\n // Priority: config.validationSchema (as BiDirectionalSchema) > schemaMetadata\n const biSchema = validationSchema as BiDirectionalSchema;\n const primaryKey = biSchema?.primaryKey || schemaMetadata.primaryKey;\n const foreignKeys = biSchema?.foreignKeys || schemaMetadata.foreignKeys;\n const indexes = biSchema?.indexes || schemaMetadata.indexes;\n\n if (primaryKey && !schema.columns.some((col) => col.primaryKey)) {\n // Add primary key constraint to column\n const col = schema.columns.find((c) => c.name === primaryKey);\n if (col) {\n col.primaryKey = true;\n }\n } else if (!primaryKey && !schema.columns.some((col) => col.primaryKey)) {\n // If no primary key is defined, use 'id' column as primary key if it exists\n // This matches the behavior of JsonlReader.inferSchema()\n const idColumn = schema.columns.find((c) => c.name === 'id');\n if (idColumn) {\n idColumn.primaryKey = true;\n }\n }\n if (foreignKeys) {\n schema.foreignKeys = foreignKeys;\n }\n if (indexes) {\n schema.indexes = indexes;\n }\n\n this.schemas.set(tableName, schema);\n\n // Create table\n this.createTable(schema);\n\n // Insert validated data\n this.insertData(tableName, schema, validatedData);\n\n return true;\n }\n\n /**\n * Create table in SQLite with constraints and indexes\n */\n private createTable(schema: TableSchema): void {\n // Note: Foreign key constraints are enabled at database connection level (see sqlite-adapter.ts)\n // No need to enable them here for each table\n\n // Quote table name to handle special characters\n const quotedTableName = this.quoteTableName(schema.name);\n\n const columnDefs = schema.columns.map((col) => {\n // JSON type is stored as TEXT in SQLite\n const sqlType = col.type === 'JSON' ? 'TEXT' : col.type;\n const parts = [this.quoteIdentifier(col.name), sqlType];\n if (col.primaryKey) parts.push('PRIMARY KEY');\n if (col.notNull) parts.push('NOT NULL');\n if (col.unique) parts.push('UNIQUE');\n return parts.join(' ');\n });\n\n // Add foreign key constraints\n const foreignKeyDefs: string[] = [];\n if (schema.foreignKeys && schema.foreignKeys.length > 0) {\n for (const fk of schema.foreignKeys) {\n const fkParts = [\n `FOREIGN KEY (${this.quoteIdentifier(fk.column)})`,\n `REFERENCES ${this.quoteTableName(fk.references.table)}(${this.quoteIdentifier(fk.references.column)})`,\n ];\n if (fk.onDelete) {\n fkParts.push(`ON DELETE ${fk.onDelete}`);\n }\n if (fk.onUpdate) {\n fkParts.push(`ON UPDATE ${fk.onUpdate}`);\n }\n foreignKeyDefs.push(fkParts.join(' '));\n }\n }\n\n const allDefs = [...columnDefs, ...foreignKeyDefs];\n const sql = `CREATE TABLE IF NOT EXISTS ${quotedTableName} (${allDefs.join(', ')})`;\n this.db.exec(sql);\n\n // Create indexes\n if (schema.indexes && schema.indexes.length > 0) {\n for (let i = 0; i < schema.indexes.length; i++) {\n const index = schema.indexes[i];\n // Create safe index name by replacing special characters\n const safeTableName = schema.name.replace(/[^a-zA-Z0-9]/g, '_');\n const resolvedIndexName =\n index.name || `idx_${safeTableName}_${index.columns.join('_')}_${i}`;\n const uniqueKeyword = index.unique ? 'UNIQUE ' : '';\n const indexSql = `CREATE ${uniqueKeyword}INDEX IF NOT EXISTS ${this.quoteIdentifier(resolvedIndexName)} ON ${quotedTableName} (${index.columns\n .map((col) => this.quoteIdentifier(col))\n .join(', ')})`;\n this.db.exec(indexSql);\n }\n }\n }\n\n /**\n * Quote table name to handle special characters in SQL\n */\n private quoteTableName(tableName: string): string {\n return this.quoteIdentifier(tableName);\n }\n\n /**\n * Quote identifier for SQL statements, escaping embedded quotes\n */\n private quoteIdentifier(identifier: string): string {\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\n }\n\n /**\n * Insert data into table\n */\n private insertData(tableName: string, schema: TableSchema, data: JsonObject[]): void {\n const columnNames = schema.columns.map((col) => col.name);\n const quotedColumns = columnNames.map((name) => this.quoteIdentifier(name));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteTableName(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const stmt = this.db.prepare(sql);\n\n for (const row of data) {\n const values = columnNames.map((col) => this.normalizeValue(row[col]));\n stmt.run(...values);\n }\n }\n\n /**\n * Execute a raw SQL query\n */\n query<T = unknown>(\n sql: string,\n params: (string | number | bigint | null | Uint8Array)[] = [],\n ): T[] {\n const stmt = this.db.prepare(sql);\n return stmt.all(...params) as T[];\n }\n\n /**\n * Execute a SQL query that returns a single row\n */\n queryOne<T = unknown>(\n sql: string,\n params: (string | number | bigint | null | Uint8Array)[] = [],\n ): T | null {\n const stmt = this.db.prepare(sql);\n const result = stmt.get(...params);\n return result === undefined ? null : (result as T);\n }\n\n /**\n * Execute a SQL statement (INSERT, UPDATE, DELETE)\n */\n execute(\n sql: string,\n params: (string | number | bigint | null | Uint8Array)[] = [],\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const stmt = this.db.prepare(sql);\n return stmt.run(...params);\n }\n\n /**\n * Find rows by condition (supports OR/AND with arrays and function filters)\n * If where is not provided, returns all rows\n */\n find<K extends keyof Tables & string>(tableName: K, where?: WhereCondition<Tables[K]>) {\n // If no where condition, return all rows\n if (where === undefined) {\n const rows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n return rows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n }\n\n // Handle empty array - should return no results\n if (Array.isArray(where) && where.length === 0) {\n return [];\n }\n\n const { sql, values, functionFilters, hasOrWithFunctionFilters } = this.buildWhereClause(where);\n\n let rows: Tables[K][];\n\n // If OR condition has function filters, get all rows and evaluate in JS\n if (hasOrWithFunctionFilters) {\n const rawRows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n return this.applyOrConditionWithFilters(rows, where as WhereCondition<Tables[K]>);\n }\n\n // Normal case: use SQL WHERE clause\n if (sql) {\n const rawRows = this.query(\n `SELECT * FROM ${this.quoteTableName(tableName)} WHERE ${sql}`,\n values,\n );\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n } else {\n // If only function filters (AND case), get all rows\n const rawRows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n }\n\n // Apply function filters for AND conditions\n return this.applyFunctionFilters(rows, functionFilters);\n }\n\n /**\n * Find a single row by condition (supports OR/AND with arrays and function filters)\n */\n findOne<K extends keyof Tables & string>(tableName: K, where: WhereCondition<Tables[K]>) {\n const { sql, values, functionFilters } = this.buildWhereClause(where);\n\n let rows: Tables[K][];\n if (sql) {\n const rawRows = this.query(\n `SELECT * FROM ${this.quoteTableName(tableName)} WHERE ${sql}`,\n values,\n );\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n } else {\n // If only function filters, get all rows\n const rawRows = this.query(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n rows = rawRows.map((row) => this.deserializeRow(tableName, row)) as Tables[K][];\n }\n\n // Apply function filters and return first match\n const filtered = this.applyFunctionFilters(rows, functionFilters);\n return filtered.length > 0 ? filtered[0] : null;\n }\n\n /**\n * Deserialize JSON columns in a row\n */\n private deserializeRow<T>(tableName: string, row: T): T {\n const schema = this.schemas.get(tableName);\n if (!schema) return row;\n\n const deserializedRow = { ...row } as Record<string, unknown>;\n\n for (const column of schema.columns) {\n const colName = column.name;\n if (!(colName in deserializedRow)) continue;\n\n const value = deserializedRow[colName];\n\n if (column.type === 'JSON' && typeof value === 'string') {\n try {\n deserializedRow[colName] = JSON.parse(value);\n } catch (error) {\n // If parsing fails, keep the original value\n console.warn(`Failed to parse JSON column ${colName}:`, error);\n }\n continue;\n }\n\n if (column.valueType === 'boolean') {\n if (typeof value === 'number') {\n deserializedRow[colName] = value === 0 ? false : true;\n } else if (typeof value === 'bigint') {\n deserializedRow[colName] = value === 0n ? false : true;\n }\n }\n }\n\n return deserializedRow as T;\n }\n\n /**\n * Validate data using StandardSchema and return the transformed value\n * Note: Only synchronous validation is supported\n */\n private validateAndTransform(tableName: string, data: unknown): JsonObject {\n const schema = this.validationSchemas.get(tableName);\n if (!schema) {\n return data as JsonObject;\n }\n\n const result = schema['~standard'].validate(data);\n\n // Only synchronous validation is supported\n if (result instanceof Promise) {\n throw new Error(\n 'Asynchronous validation is not supported. Please use synchronous validation schemas.',\n );\n }\n\n if (result.issues && result.issues.length > 0) {\n // Format detailed error message with all validation issues\n const issueMessages = result.issues\n .map((issue) => {\n // Handle path: can be array of PathSegment or undefined\n let pathStr = 'root';\n if (issue.path && issue.path.length > 0) {\n pathStr = issue.path\n .map((segment) => {\n // PathSegment can be { key: PropertyKey } or just PropertyKey\n if (typeof segment === 'object' && segment !== null && 'key' in segment) {\n return String(segment.key);\n }\n return String(segment);\n })\n .join('.');\n }\n return ` - ${pathStr}: ${issue.message}`;\n })\n .join('\\n');\n\n const errorMessage = `Validation failed for table '${tableName}':\\n${issueMessages}`;\n const error = new Error(errorMessage) as ValidationError;\n error.name = 'ValidationError';\n error.issues = result.issues;\n throw error;\n }\n\n // Return the transformed value from validation\n // When there are no issues, result.value should be present\n const transformedValue = ('value' in result ? result.value : data) as JsonObject;\n\n // Convert undefined values to null for JSON compatibility\n const normalizedValue: JsonObject = {};\n for (const [key, value] of Object.entries(transformedValue)) {\n normalizedValue[key] = value === undefined ? null : value;\n }\n\n return normalizedValue;\n }\n\n /**\n * Validate data using StandardSchema (without returning transformed value)\n * Note: Only synchronous validation is supported\n */\n private validateData(tableName: string, data: unknown): void {\n // Use validateAndTransform but discard the result\n this.validateAndTransform(tableName, data);\n }\n\n /**\n * Insert a row into a table with validation\n */\n insert<K extends keyof Tables & string>(\n tableName: K,\n data: Tables[K],\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n // Validate if schema exists\n this.validateData(tableName, data);\n\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n const columnNames = Object.keys(data);\n const quotedColumns = columnNames.map((col) => this.quoteIdentifier(col));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteTableName(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const values = Object.values(data).map((v) => this.normalizeValue(v));\n const result = this.execute(sql, values);\n\n // Auto-sync if not in transaction\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return result;\n }\n\n /**\n * Batch insert rows with validation per record.\n */\n batchInsert<K extends keyof Tables & string>(\n tableName: K,\n records: Tables[K][],\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n if (records.length === 0) {\n return { changes: 0, lastInsertRowid: 0 };\n }\n\n let totalChanges = 0n;\n let lastRowid = 0n;\n\n for (const record of records) {\n this.validateData(tableName, record);\n\n const columnNames = Object.keys(record);\n const quotedColumns = columnNames.map((col) => this.quoteIdentifier(col));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteTableName(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const values = columnNames.map((col) => this.normalizeValue(record[col as keyof Tables[K]]));\n\n const result = this.execute(sql, values);\n totalChanges += BigInt(result.changes);\n lastRowid = BigInt(result.lastInsertRowid);\n }\n\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return {\n changes: totalChanges,\n lastInsertRowid: lastRowid,\n };\n }\n\n /**\n * Update rows in a table with validation (supports OR/AND with arrays)\n * Note: Function filters are not supported for update operations\n * Note: By default, validation is enabled. For partial updates, existing data is fetched\n * and merged before validation. Set options.validate = false to disable validation.\n */\n update<K extends keyof Tables & string>(\n tableName: K,\n data: Partial<Tables[K]>,\n where: WhereCondition<Tables[K]>,\n options?: { validate?: boolean },\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n // Validate by default (can be disabled with validate: false)\n const shouldValidate = options?.validate !== false;\n const hasValidationSchema = this.validationSchemas.has(tableName);\n\n if (shouldValidate && hasValidationSchema) {\n // Get existing rows to merge with partial data\n const existingRows = this.find(tableName, where);\n\n // Validate each merged row\n for (const existingRow of existingRows) {\n const mergedData = { ...existingRow, ...data };\n this.validateData(tableName, mergedData);\n }\n }\n\n const { sql: whereSql, values: whereValues, functionFilters } = this.buildWhereClause(where);\n\n if (functionFilters.length > 0) {\n throw new Error('Function filters are not supported in update operations');\n }\n\n const setClauses = Object.keys(data)\n .map((key) => `${this.quoteIdentifier(key)} = ?`)\n .join(', ');\n const sql = `UPDATE ${this.quoteTableName(tableName)} SET ${setClauses} WHERE ${whereSql}`;\n\n const values = [...Object.values(data).map((v) => this.normalizeValue(v)), ...whereValues];\n\n const result = this.execute(sql, values);\n\n // Auto-sync if not in transaction\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return result;\n }\n\n /**\n * Batch update rows with record-specific values and validation.\n * Each record must include the primary key to identify the target row.\n * Validation runs once per merged record unless explicitly disabled.\n */\n batchUpdate<K extends keyof Tables & string>(\n tableName: K,\n records: Array<Partial<Tables[K]> & Record<string, unknown>>,\n options?: { validate?: boolean },\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n if (records.length === 0) {\n return { changes: 0, lastInsertRowid: 0 };\n }\n\n // Get primary key column\n const pkColumn = schema.columns.find((col) => col.primaryKey);\n if (!pkColumn) {\n throw new Error(`Table ${tableName} does not have a primary key`);\n }\n\n const pkName = pkColumn.name;\n\n // Extract primary key values from records\n const pkValues: unknown[] = [];\n for (const record of records) {\n const pkValue = record[pkName];\n if (pkValue === undefined) {\n throw new Error(\n `Record is missing primary key '${String(pkName)}': ${JSON.stringify(record)}`,\n );\n }\n pkValues.push(pkValue);\n }\n\n // Validate by default (can be disabled with validate: false)\n const shouldValidate = options?.validate !== false;\n const hasValidationSchema = this.validationSchemas.has(tableName);\n\n if (shouldValidate && hasValidationSchema) {\n // Build OR condition to fetch all existing rows at once\n const orCondition = pkValues.map((pkValue) => ({\n [pkName]: pkValue,\n })) as WhereCondition<Tables[K]>;\n\n // Fetch all existing rows in one query\n const existingRows = this.find(tableName, orCondition);\n\n // Create a map for fast lookup: pkValue -> existingRow\n const existingRowsMap = new Map<unknown, Tables[K]>();\n for (const row of existingRows) {\n const pkValue = (row as Record<string, unknown>)[pkName];\n existingRowsMap.set(pkValue, row);\n }\n\n // Validate each merged record and collect all errors\n const validationErrors: Array<{\n rowIndex: number;\n rowData: unknown;\n pkValue: unknown;\n error: ValidationError;\n }> = [];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i];\n const pkValue = record[pkName];\n const existingRow = existingRowsMap.get(pkValue);\n\n if (!existingRow) {\n throw new Error(\n `No existing row found with ${String(pkName)}=${JSON.stringify(pkValue)}`,\n );\n }\n\n const mergedData = { ...existingRow, ...record };\n\n try {\n this.validateData(tableName, mergedData);\n } catch (error) {\n // Collect validation errors instead of throwing immediately\n if (error instanceof Error && error.name === 'ValidationError') {\n validationErrors.push({\n rowIndex: i,\n rowData: mergedData,\n pkValue,\n error: error as ValidationError,\n });\n } else {\n throw error;\n }\n }\n }\n\n // If there are validation errors, throw with all error information\n if (validationErrors.length > 0) {\n const enhancedError = new Error(\n `Validation failed for ${validationErrors.length} row(s)`,\n ) as ValidationError & { validationErrors: typeof validationErrors };\n enhancedError.name = 'ValidationError';\n enhancedError.validationErrors = validationErrors;\n // For backward compatibility, include issues from first error\n enhancedError.issues = validationErrors[0].error.issues;\n throw enhancedError;\n }\n }\n\n // All validations passed - perform updates\n let totalChanges = 0n;\n let lastRowid = 0n;\n\n for (const record of records) {\n const pkValue = record[pkName];\n const where = { [pkName]: pkValue } as WhereCondition<Tables[K]>;\n\n // Call update without validation (already validated above)\n const result = this.update(tableName, record as Partial<Tables[K]>, where, {\n validate: false,\n });\n\n totalChanges += BigInt(result.changes);\n lastRowid = BigInt(result.lastInsertRowid);\n }\n\n return {\n changes: totalChanges,\n lastInsertRowid: lastRowid,\n };\n }\n\n /**\n * Delete rows from a table (supports OR/AND with arrays)\n * Note: Function filters are not supported for delete operations\n */\n delete<K extends keyof Tables & string>(\n tableName: K,\n where: WhereCondition<Tables[K]>,\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n const { sql: whereSql, values, functionFilters } = this.buildWhereClause(where);\n\n if (functionFilters.length > 0) {\n throw new Error('Function filters are not supported in delete operations');\n }\n\n const sql = `DELETE FROM ${this.quoteTableName(tableName)} WHERE ${whereSql}`;\n const result = this.execute(sql, values);\n\n // Auto-sync if not in transaction\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return result;\n }\n\n /**\n * Batch delete rows by primary key.\n */\n batchDelete<K extends keyof Tables & string>(\n tableName: K,\n records: Array<Partial<Tables[K]> & Record<string, unknown>>,\n ): { changes: number | bigint; lastInsertRowid: number | bigint } {\n const schema = this.schemas.get(tableName);\n if (!schema) {\n throw new Error(`Table ${tableName} does not exist`);\n }\n\n if (records.length === 0) {\n return { changes: 0, lastInsertRowid: 0 };\n }\n\n const pkColumn = schema.columns.find((col) => col.primaryKey);\n if (!pkColumn) {\n throw new Error(`Table ${tableName} does not have a primary key`);\n }\n const pkName = pkColumn.name;\n\n const pkValues = records.map((record, index) => {\n const pkValue = record[pkName as keyof Tables[K]];\n if (pkValue === undefined) {\n throw new Error(`Record at index ${index} is missing primary key '${String(pkName)}'`);\n }\n return pkValue;\n });\n\n const placeholders = pkValues.map(() => '?').join(', ');\n const sql = `DELETE FROM ${this.quoteTableName(tableName)} WHERE ${this.quoteIdentifier(pkName)} IN (${placeholders})`;\n const values = pkValues.map((value) => this.normalizeValue(value));\n\n const result = this.execute(sql, values);\n\n if (!this.inTransaction) {\n this.syncTable(tableName).catch((err) => {\n console.error(`Failed to sync table ${tableName}:`, err);\n });\n }\n\n return {\n changes: BigInt(result.changes),\n lastInsertRowid: BigInt(result.lastInsertRowid),\n };\n }\n\n /**\n * Normalize value for SQLite\n */\n private normalizeValue(value: unknown): string | number | bigint | null | Uint8Array {\n if (value === null || value === undefined) return null;\n if (typeof value === 'boolean') return value ? 1 : 0;\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint')\n return value;\n if (value instanceof Uint8Array) return value;\n // For objects, convert to JSON string\n return JSON.stringify(value);\n }\n\n /**\n * Build WHERE clause from condition (supports OR/AND with arrays and functions)\n */\n private buildWhereClause<T extends Record<string, unknown>>(\n condition: WhereCondition<T>,\n ): {\n sql: string;\n values: Array<string | number | bigint | null | Uint8Array>;\n functionFilters: Array<{\n key: string;\n fn: (value: unknown) => boolean;\n }>;\n hasOrWithFunctionFilters: boolean;\n } {\n const values: Array<string | number | bigint | null | Uint8Array> = [];\n const functionFilters: Array<{ key: string; fn: (value: unknown) => boolean }> = [];\n let hasOrWithFunctionFilters = false;\n\n const buildCondition = (cond: WhereCondition<T>, isInOr = false): string => {\n // Handle array (OR conditions)\n if (Array.isArray(cond)) {\n const clauses = cond\n .map((item) => {\n const clause = Array.isArray(item)\n ? buildCondition(item, true)\n : buildCondition(item, true);\n return clause ? `(${clause})` : '';\n })\n .filter((clause) => clause !== ''); // Filter out empty clauses\n\n return clauses.join(' OR ');\n }\n\n // Handle object (AND conditions)\n const conditions: string[] = [];\n let hasFunctionFilter = false;\n for (const [key, value] of Object.entries(cond)) {\n if (typeof value === 'function') {\n // Function filter - will be applied later\n functionFilters.push({ key, fn: value as (value: unknown) => boolean });\n hasFunctionFilter = true;\n } else {\n // Regular value\n conditions.push(`${this.quoteIdentifier(key)} = ?`);\n values.push(this.normalizeValue(value));\n }\n }\n\n if (isInOr && hasFunctionFilter) {\n hasOrWithFunctionFilters = true;\n }\n\n return conditions.join(' AND ');\n };\n\n const sql = buildCondition(condition);\n return { sql, values, functionFilters, hasOrWithFunctionFilters };\n }\n\n /**\n * Apply OR condition with function filters by evaluating each row against the condition\n */\n private applyOrConditionWithFilters<T extends Record<string, unknown>>(\n rows: T[],\n condition: WhereCondition<T>,\n ): T[] {\n return rows.filter((row) => this.matchesOrCondition(row, condition));\n }\n\n /**\n * Check if a row matches an OR/AND condition (recursively)\n */\n private matchesOrCondition<T extends Record<string, unknown>>(\n row: T,\n condition: WhereCondition<T>,\n ): boolean {\n // Handle array (OR conditions)\n if (Array.isArray(condition)) {\n return condition.some((item) => this.matchesOrCondition(row, item));\n }\n\n // Handle object (AND conditions)\n return Object.entries(condition).every(([key, value]) => {\n const rowValue = row[key as keyof T];\n if (typeof value === 'function') {\n return (value as (value: unknown) => boolean)(rowValue);\n }\n return rowValue === value;\n });\n }\n\n /**\n * Apply function filters to rows\n */\n private applyFunctionFilters<T extends Record<string, unknown>>(\n rows: T[],\n functionFilters: Array<{ key: string; fn: (value: unknown) => boolean }>,\n ): T[] {\n if (functionFilters.length === 0) return rows;\n\n return rows.filter((row) => {\n return functionFilters.every(({ key, fn }) => {\n const value = row[key as keyof T];\n return fn(value);\n });\n });\n }\n\n /**\n * Get table schema\n */\n getSchema(tableName: string): TableSchema | undefined {\n return this.schemas.get(tableName);\n }\n\n /**\n * Get all table names\n */\n getTableNames(): string[] {\n return Array.from(this.schemas.keys());\n }\n\n /**\n * Sync a specific table back to its JSONL file\n * Uses backward transformation when available\n */\n private async syncTable(tableName: string): Promise<void> {\n const tableConfig = this.tables.get(tableName);\n if (!tableConfig) {\n throw new Error(`Table ${tableName} not found`);\n }\n\n // Get all rows from the table\n const rows = this.query<JsonObject>(`SELECT * FROM ${this.quoteTableName(tableName)}`);\n\n // Deserialize JSON columns\n const deserializedRows = rows.map((row) => this.deserializeRow(tableName, row));\n\n // Apply backward transformation if available\n const validationSchema = this.validationSchemas.get(tableName);\n let finalRows = deserializedRows;\n\n if (validationSchema && hasBackward(validationSchema)) {\n const biSchema = validationSchema as BiDirectionalSchema<Table, Table>;\n finalRows = deserializedRows.map((row) => biSchema.backward!(row) as JsonObject);\n }\n\n // Write back to JSONL file\n await JsonlWriter.write(tableConfig.jsonlPath, finalRows);\n }\n\n /**\n * Sync database changes back to JSONL files\n * Uses backward transformation when available\n */\n async sync(): Promise<void> {\n for (const [tableName] of this.tables) {\n await this.syncTable(tableName);\n }\n }\n\n /**\n * Execute a function within a transaction\n * Automatically commits on success or rolls back on error\n */\n async transaction<T>(fn: (tx: LinesDB<Tables>) => Promise<T> | T): Promise<T> {\n if (this.inTransaction) {\n throw new Error('Nested transactions are not supported');\n }\n\n this.db.exec('BEGIN TRANSACTION');\n this.inTransaction = true;\n\n try {\n const result = await fn(this);\n this.db.exec('COMMIT');\n this.inTransaction = false;\n\n // Sync all tables after successful commit\n await this.sync();\n\n return result;\n } catch (error) {\n if (this.inTransaction) {\n this.db.exec('ROLLBACK');\n }\n this.inTransaction = false;\n throw error;\n }\n }\n\n /**\n * Close the database connection\n */\n async close(): Promise<void> {\n try {\n this.db.close();\n } catch (_error) {\n // Ignore errors if database is already closed\n }\n }\n\n /**\n * Get the underlying SQLite database instance\n */\n getDb(): SQLiteDatabase {\n return this.db;\n }\n}\n","import { readdir } from 'node:fs/promises';\nimport { join, relative, basename, dirname, isAbsolute } from 'node:path';\nimport { writeFile, mkdir } from 'node:fs/promises';\n\nexport interface TypeGeneratorOptions {\n dataDir: string;\n projectRoot?: string; // Default: current working directory\n}\n\ninterface TableInfo {\n tableName: string;\n schemaFile?: string;\n}\n\nexport class TypeGenerator {\n private dataDir: string;\n private projectRoot: string;\n private outputFile: string;\n private dataDirPath: string;\n\n constructor(options: TypeGeneratorOptions) {\n // For testing: allow overriding projectRoot via environment variable\n const envProjectRoot = process.env.LINES_DB_TEST_PROJECT_ROOT;\n this.projectRoot =\n envProjectRoot !== undefined ? envProjectRoot : options.projectRoot || process.cwd();\n this.dataDir = options.dataDir;\n this.dataDirPath = isAbsolute(this.dataDir)\n ? this.dataDir\n : join(this.projectRoot, this.dataDir);\n this.outputFile = join(this.dataDirPath, 'db.ts');\n }\n\n /**\n * Generate types file from JSONL files and their optional schema files.\n */\n async generate(): Promise<string> {\n // Find all JSONL files and their corresponding schema files\n const tables = await this.findTables();\n\n if (tables.length === 0) {\n throw new Error(\n `No JSONL files found in ${this.dataDirPath}. Place one or more *.jsonl files in the directory.`,\n );\n }\n\n // Generate type declarations\n const content = this.generateTypeDeclarations(tables);\n\n // Ensure output directory exists\n const outputDir = dirname(this.outputFile);\n await mkdir(outputDir, { recursive: true });\n\n // Write to file\n await writeFile(this.outputFile, content, 'utf-8');\n console.log(`Generated types at ${this.outputFile}`);\n return this.outputFile;\n }\n\n /**\n * Find all *.jsonl files and check if they have corresponding *.schema.ts files\n */\n private async findTables(): Promise<TableInfo[]> {\n try {\n const entries = await readdir(this.dataDirPath, { withFileTypes: true });\n const tables: TableInfo[] = [];\n\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n const tableName = basename(entry.name, '.jsonl');\n const schemaFileName = `${tableName}.schema.ts`;\n const schemaFilePath = join(this.dataDirPath, schemaFileName);\n\n // Check if schema file exists\n const hasSchema = entries.some((e) => e.isFile() && e.name === schemaFileName);\n\n tables.push({\n tableName,\n schemaFile: hasSchema ? schemaFilePath : undefined,\n });\n }\n }\n\n return tables;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(\n `Data directory not found: ${this.dataDirPath}. Set lines-db.dataDir to the correct location.`,\n );\n }\n throw error;\n }\n }\n\n /**\n * Generate type declaration content\n */\n private generateTypeDeclarations(tables: TableInfo[]): string {\n const imports: string[] = [];\n const tableEntries: string[] = [];\n const usedAliases = new Set<string>();\n\n for (const table of tables) {\n const tableKey = this.formatTableKey(table.tableName);\n\n if (table.schemaFile) {\n // Table has a schema file\n const schemaIdentifier = this.createSchemaIdentifier(table.tableName, usedAliases);\n usedAliases.add(schemaIdentifier);\n\n // Calculate relative path from output file to schema file\n let relativePath = relative(join(this.outputFile, '..'), table.schemaFile)\n .replace(/\\\\/g, '/') // Convert Windows paths to Unix-style\n .replace('.ts', '.js'); // Import from .js (TypeScript module resolution)\n\n // Ensure relative path starts with './' or '../'\n if (!relativePath.startsWith('.')) {\n relativePath = './' + relativePath;\n }\n\n // Add import statement for schema\n imports.push(`import { schema as ${schemaIdentifier} } from '${relativePath}';`);\n\n // Add table entry with InferOutput\n tableEntries.push(` ${tableKey}: InferOutput<typeof ${schemaIdentifier}>;`);\n } else {\n // Table has no schema file, use Record<string, unknown>\n tableEntries.push(` ${tableKey}: Record<string, unknown>;`);\n }\n }\n\n // Generate full content\n const importSection = imports.length > 0 ? `${imports.join('\\n')}\\n` : '';\n const inferOutputImport = imports.length > 0 ? ', InferOutput' : '';\n\n return `// Auto-generated by lines-db\n// Do not edit this file manually\n\n${importSection}import type { DatabaseConfig${inferOutputImport} } from '@toiroakr/lines-db';\nimport { fileURLToPath } from 'node:url';\nimport { dirname } from 'node:path';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport type Tables = {\n${tableEntries.join('\\n')}\n};\n\nexport const config: DatabaseConfig<Tables> = {\n dataDir: __dirname,\n};\n`;\n }\n\n private createSchemaIdentifier(tableName: string, usedAliases: Set<string>): string {\n const camel = toCamelCase(tableName);\n const sanitizedBase = sanitizeIdentifier(camel);\n let base = sanitizedBase || 'table';\n\n if (!/^[A-Za-z_$]/.test(base)) {\n base = `_${base}`;\n }\n\n let candidate = `${base}Schema`;\n let suffix = 1;\n while (usedAliases.has(candidate)) {\n candidate = `${base}${++suffix}Schema`;\n }\n\n return candidate;\n }\n\n private formatTableKey(tableName: string): string {\n const identifierPattern = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n if (identifierPattern.test(tableName)) {\n return tableName;\n }\n const escaped = tableName.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n return `'${escaped}'`;\n }\n}\n\nfunction toCamelCase(value: string): string {\n const parts = value\n .split(/[^A-Za-z0-9]+/)\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n\n if (parts.length === 0) {\n return value;\n }\n\n const [first, ...rest] = parts;\n return first + rest.map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('');\n}\n\nfunction sanitizeIdentifier(value: string): string {\n return value.replace(/[^A-Za-z0-9_$]/g, '');\n}\n","import { readdir, stat } from 'node:fs/promises';\nimport { join, basename, dirname } from 'node:path';\nimport { JsonlReader } from './jsonl-reader.js';\nimport { SchemaLoader } from './schema-loader.js';\nimport { LinesDB } from './database.js';\nimport type { StandardSchemaIssue } from './types.js';\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationErrorDetail[];\n warnings: string[];\n}\n\nexport interface ValidationErrorDetail {\n file: string;\n tableName: string;\n rowIndex: number;\n issues: ReadonlyArray<StandardSchemaIssue>;\n type?: 'schema' | 'foreignKey';\n foreignKeyError?: {\n column: string;\n value: unknown;\n referencedTable: string;\n referencedColumn: string;\n };\n}\n\nexport interface ValidatorOptions {\n path: string; // File or directory path\n projectRoot?: string;\n}\n\nexport class Validator {\n private path: string;\n private projectRoot: string;\n\n constructor(options: ValidatorOptions) {\n this.path = options.path;\n this.projectRoot = options.projectRoot || process.cwd();\n }\n\n /**\n * Validate JSONL file(s)\n */\n async validate(): Promise<ValidationResult> {\n // Use absolute path if provided, otherwise resolve relative to projectRoot\n const fullPath = this.path.startsWith('/') ? this.path : join(this.projectRoot, this.path);\n const stats = await stat(fullPath);\n\n if (stats.isDirectory()) {\n return this.validateDirectory(fullPath);\n } else if (stats.isFile() && fullPath.endsWith('.jsonl')) {\n return this.validateFile(fullPath);\n } else {\n throw new Error(`Invalid path: ${this.path}. Must be a directory or .jsonl file.`);\n }\n }\n\n /**\n * Validate all JSONL files in a directory\n */\n private async validateDirectory(dirPath: string): Promise<ValidationResult> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const jsonlFiles = entries\n .filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl'))\n .map((entry) => join(dirPath, entry.name));\n\n if (jsonlFiles.length === 0) {\n throw new Error(`No JSONL files found in directory: ${dirPath}`);\n }\n\n const allErrors: ValidationErrorDetail[] = [];\n const allWarnings: string[] = [];\n const filesWithSchema: string[] = [];\n\n // Filter files with schema and collect warnings for files without schema\n for (const file of jsonlFiles) {\n const hasSchema = await SchemaLoader.hasSchema(file);\n if (hasSchema) {\n filesWithSchema.push(file);\n } else {\n const tableName = basename(file, '.jsonl');\n allWarnings.push(`Skipping validation for '${tableName}': schema file not found`);\n }\n }\n\n // Validate schema for each file with schema\n for (const file of filesWithSchema) {\n const result = await this.validateFile(file);\n allErrors.push(...result.errors);\n allWarnings.push(...result.warnings);\n }\n\n // Validate by loading into database with detailed error tracking\n if (filesWithSchema.length > 0 && allErrors.length === 0) {\n const dbErrors = await this.validateWithDatabase(dirPath, filesWithSchema);\n allErrors.push(...dbErrors);\n }\n\n return {\n valid: allErrors.length === 0,\n errors: allErrors,\n warnings: allWarnings,\n };\n }\n\n /**\n * Validate by loading data into database one row at a time\n * This catches constraint violations and extracts detailed error information\n */\n private async validateWithDatabase(\n dirPath: string,\n jsonlFiles: string[],\n ): Promise<ValidationErrorDetail[]> {\n const errors: ValidationErrorDetail[] = [];\n\n try {\n const db = LinesDB.create({ dataDir: ':memory:' });\n\n // Load all tables one by one, checking each row\n for (const file of jsonlFiles) {\n const tableName = basename(file, '.jsonl');\n const data = await JsonlReader.read(file);\n\n // Load schema and metadata\n let schema: any;\n let foreignKeys: any[] = [];\n let indexes: any[] = [];\n let primaryKey: string | undefined;\n try {\n schema = await SchemaLoader.loadSchema(file);\n const { pathToFileURL } = await import('node:url');\n const schemaPath = file.replace('.jsonl', '.schema.ts');\n const schemaUrl = pathToFileURL(schemaPath).href;\n const schemaModule = await import(`${schemaUrl}?t=${Date.now()}`);\n const schemaExport = schemaModule.schema || schemaModule.default;\n if (schemaExport?.foreignKeys) {\n foreignKeys = schemaExport.foreignKeys;\n }\n if (schemaExport?.indexes) {\n indexes = schemaExport.indexes;\n }\n if (schemaExport?.primaryKey) {\n primaryKey = schemaExport.primaryKey;\n }\n } catch (_error) {\n // Schema not found or failed to load\n continue;\n }\n\n // Create table schema\n try {\n const tableSchema = this.createTableSchema(\n tableName,\n data,\n schema,\n foreignKeys,\n indexes,\n primaryKey,\n );\n\n // Create the table in the database\n this.createTableInDb(db, tableSchema);\n\n // Insert rows one by one to catch constraint violations\n for (let rowIndex = 0; rowIndex < data.length; rowIndex++) {\n const row = data[rowIndex];\n try {\n this.insertRowIntoDb(db, tableName, tableSchema, row);\n } catch (error) {\n // Constraint violation occurred\n const constraintError = this.analyzeConstraintError(\n error,\n file,\n tableName,\n rowIndex,\n row,\n foreignKeys,\n db,\n );\n if (constraintError) {\n errors.push(constraintError);\n }\n }\n }\n } catch (_error) {\n // Skip this table and continue if table creation fails\n continue;\n }\n }\n\n await db.close();\n } catch (error) {\n // Database initialization failed\n errors.push({\n file: dirPath,\n tableName: 'database',\n rowIndex: 0,\n issues: [\n {\n message: `Database initialization failed: ${error instanceof Error ? error.message : String(error)}`,\n path: [],\n },\n ],\n type: 'schema',\n });\n }\n\n return errors;\n }\n\n /**\n * Create table schema from data and validation schema\n */\n private createTableSchema(\n tableName: string,\n data: any[],\n validationSchema: any,\n foreignKeys: any[],\n indexes: any[],\n primaryKey?: string,\n ): any {\n if (data.length === 0) {\n throw new Error(`No data found in ${tableName}`);\n }\n\n // Infer schema from data\n const schema = JsonlReader.inferSchema(tableName, data);\n\n // Set primary key if specified\n if (primaryKey) {\n const pkColumn = schema.columns.find((col: any) => col.name === primaryKey);\n if (pkColumn) {\n pkColumn.primaryKey = true;\n }\n } else if (!schema.columns.some((col: any) => col.primaryKey)) {\n // If no primary key is defined, use 'id' column as primary key if it exists\n // This matches the behavior of database.ts\n const idColumn = schema.columns.find((c: any) => c.name === 'id');\n if (idColumn) {\n idColumn.primaryKey = true;\n }\n }\n\n // Add foreign keys\n if (foreignKeys && foreignKeys.length > 0) {\n schema.foreignKeys = foreignKeys;\n }\n\n // Add indexes\n if (indexes && indexes.length > 0) {\n schema.indexes = indexes;\n }\n\n return schema;\n }\n\n /**\n * Create table in database\n */\n private createTableInDb(db: LinesDB<any>, schema: any): void {\n const columns = schema.columns.map((col: any) => {\n let colDef = `${this.quoteIdentifier(col.name)} ${col.type.toUpperCase()}`;\n if (col.primaryKey) {\n colDef += ' PRIMARY KEY';\n }\n return colDef;\n });\n\n // Add foreign key constraints\n if (schema.foreignKeys && schema.foreignKeys.length > 0) {\n for (const fk of schema.foreignKeys) {\n columns.push(\n `FOREIGN KEY (${this.quoteIdentifier(fk.column)}) REFERENCES ${this.quoteIdentifier(fk.references.table)}(${this.quoteIdentifier(fk.references.column)})`,\n );\n }\n }\n\n const sql = `CREATE TABLE IF NOT EXISTS ${this.quoteIdentifier(schema.name)} (${columns.join(', ')})`;\n db.execute(sql);\n\n // Create indexes\n if (schema.indexes && schema.indexes.length > 0) {\n for (const index of schema.indexes) {\n const indexName = index.name || `idx_${schema.name}_${index.columns.join('_')}`;\n const uniqueKeyword = index.unique ? 'UNIQUE' : '';\n const indexColumns = index.columns\n .map((col: string) => this.quoteIdentifier(col))\n .join(', ');\n const indexSql = `CREATE ${uniqueKeyword} INDEX IF NOT EXISTS ${this.quoteIdentifier(indexName)} ON ${this.quoteIdentifier(schema.name)} (${indexColumns})`;\n db.execute(indexSql);\n }\n }\n }\n\n /**\n * Insert a row into database\n */\n private insertRowIntoDb(db: LinesDB<any>, tableName: string, schema: any, row: any): void {\n const columnNames = schema.columns.map((col: any) => col.name);\n const quotedColumns = columnNames.map((name: string) => this.quoteIdentifier(name));\n const placeholders = columnNames.map(() => '?').join(', ');\n const sql = `INSERT INTO ${this.quoteIdentifier(tableName)} (${quotedColumns.join(', ')}) VALUES (${placeholders})`;\n\n const values = columnNames.map((col: string) => {\n const value = row[col];\n if (value === null || value === undefined) return null;\n if (typeof value === 'object') return JSON.stringify(value);\n if (typeof value === 'boolean') return value ? 1 : 0;\n return value;\n });\n\n db.execute(sql, values);\n }\n\n /**\n * Analyze constraint error and extract detailed information\n */\n private analyzeConstraintError(\n error: any,\n file: string,\n tableName: string,\n rowIndex: number,\n row: any,\n foreignKeys: any[],\n db: LinesDB<any>,\n ): ValidationErrorDetail | null {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // Foreign key constraint\n if (errorMessage.includes('FOREIGN KEY constraint failed')) {\n // Find which foreign key failed\n for (const fk of foreignKeys) {\n const fkValue = row[fk.column];\n if (fkValue === null || fkValue === undefined) continue;\n\n // Check if referenced value exists\n try {\n const result = db.query(\n `SELECT COUNT(*) as count FROM ${this.quoteIdentifier(fk.references.table)} WHERE ${this.quoteIdentifier(fk.references.column)} = ?`,\n [fkValue],\n );\n if (result.length > 0 && (result[0] as any).count === 0) {\n return {\n file,\n tableName,\n rowIndex,\n issues: [],\n type: 'foreignKey',\n foreignKeyError: {\n column: fk.column,\n value: fkValue,\n referencedTable: fk.references.table,\n referencedColumn: fk.references.column,\n },\n };\n }\n } catch (_) {\n // Referenced table doesn't exist yet\n }\n }\n }\n\n // Other constraint errors (primary key, unique, etc.)\n return {\n file,\n tableName,\n rowIndex,\n issues: [\n {\n message: errorMessage,\n path: [],\n },\n ],\n type: 'schema',\n };\n }\n\n /**\n * Quote SQL identifier\n */\n private quoteIdentifier(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n }\n\n /**\n * Validate a single JSONL file\n */\n private async validateFile(filePath: string): Promise<ValidationResult> {\n const tableName = basename(filePath, '.jsonl');\n const data = await JsonlReader.read(filePath);\n\n // Try to load schema\n const schema = await SchemaLoader.loadSchema(filePath);\n\n const errors: ValidationErrorDetail[] = [];\n\n // Validate each row with schema\n for (let i = 0; i < data.length; i++) {\n const row = data[i];\n const result = schema['~standard'].validate(row);\n\n // Only synchronous validation is supported\n if (result instanceof Promise) {\n throw new Error('Asynchronous validation is not supported.');\n }\n\n if (result.issues && result.issues.length > 0) {\n errors.push({\n file: filePath,\n tableName,\n rowIndex: i, // 0-indexed, will be converted to 1-indexed in formatter\n issues: result.issues,\n type: 'schema',\n });\n }\n }\n\n // If schema validation passed, validate database constraints\n if (errors.length === 0) {\n const dirPath = dirname(filePath);\n\n // Get all JSONL files in the directory\n const entries = await readdir(dirPath, { withFileTypes: true });\n const allJsonlFiles = entries\n .filter((entry) => entry.isFile() && entry.name.endsWith('.jsonl'))\n .map((entry) => join(dirPath, entry.name));\n\n // Validate database constraints (including foreign keys)\n const dbErrors = await this.validateWithDatabase(dirPath, allJsonlFiles);\n // Only include errors for the current file\n errors.push(...dbErrors.filter((e) => e.file === filePath));\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings: [],\n };\n }\n}\n","import { join } from 'node:path';\nimport type { JsonObject } from './types.js';\nimport { JsonlReader } from './jsonl-reader.js';\nimport { LinesDB } from './database.js';\n\nexport interface TableValidationOptions {\n dataDir: string;\n tableName: string;\n rows: JsonObject[];\n}\n\n/**\n * Validate a table by temporarily supplying in-memory rows while reusing the existing LinesDB validation pipeline.\n * If validation fails, the underlying LinesDB error is rethrown so callers can inspect validation details.\n */\nexport async function ensureTableRowsValid(options: TableValidationOptions): Promise<void> {\n console.log('[ensureTableRowsValid] START');\n console.log('[ensureTableRowsValid] dataDir:', options.dataDir);\n console.log('[ensureTableRowsValid] tableName:', options.tableName);\n console.log('[ensureTableRowsValid] rows count:', options.rows.length);\n\n const tablePath = join(options.dataDir, `${options.tableName}.jsonl`);\n const overrides = new Map<string, JsonObject[]>([[tablePath, options.rows]]);\n console.log('[ensureTableRowsValid] tablePath:', tablePath);\n\n let capturedError: Error | null = null;\n\n // Intercept console.warn to capture validation errors\n const originalWarn = console.warn;\n const warnMessages: string[] = [];\n console.warn = (...args: any[]) => {\n const message = args.join(' ');\n console.log('[ensureTableRowsValid] Captured warn:', message);\n warnMessages.push(message);\n // Check if this is a validation error for our table\n if (\n message.includes(`Failed to load table '${options.tableName}'`) &&\n message.includes('Validation failed')\n ) {\n // Extract the original error from the warn message\n capturedError = new Error(message);\n console.log('[ensureTableRowsValid] Captured validation error!');\n }\n };\n\n try {\n console.log('[ensureTableRowsValid] Calling JsonlReader.withOverrides');\n await JsonlReader.withOverrides(overrides, async () => {\n console.log('[ensureTableRowsValid] Inside withOverrides callback');\n const db = LinesDB.create({ dataDir: options.dataDir });\n console.log('[ensureTableRowsValid] LinesDB created');\n try {\n console.log('[ensureTableRowsValid] Calling db.initialize()');\n await db.initialize();\n console.log('[ensureTableRowsValid] db.initialize() completed');\n } finally {\n console.log('[ensureTableRowsValid] Calling db.close()');\n await db.close();\n }\n });\n console.log('[ensureTableRowsValid] withOverrides completed');\n } finally {\n // Restore original console.warn\n console.warn = originalWarn;\n }\n\n console.log('[ensureTableRowsValid] Warnings captured:', warnMessages.length);\n console.log('[ensureTableRowsValid] capturedError:', capturedError ? 'YES' : 'NO');\n\n if (capturedError) {\n console.log('[ensureTableRowsValid] Throwing captured error');\n throw capturedError;\n }\n\n console.log('[ensureTableRowsValid] END (success)');\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toiroakr/lines-db",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "A database implementation that treats JSONL files as tables using SQLite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",