@hedystia/db 2.1.1 → 2.2.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/LICENSE +21 -0
- package/dist/drivers/driver.cjs.map +1 -1
- package/dist/drivers/driver.mjs.map +1 -1
- package/dist/drivers/file.cjs +1 -0
- package/dist/drivers/file.cjs.map +1 -1
- package/dist/drivers/file.mjs +1 -0
- package/dist/drivers/file.mjs.map +1 -1
- package/dist/drivers/mysql.cjs +1 -0
- package/dist/drivers/mysql.cjs.map +1 -1
- package/dist/drivers/mysql.mjs +1 -0
- package/dist/drivers/mysql.mjs.map +1 -1
- package/dist/drivers/s3.cjs +1 -0
- package/dist/drivers/s3.cjs.map +1 -1
- package/dist/drivers/s3.mjs +1 -0
- package/dist/drivers/s3.mjs.map +1 -1
- package/dist/drivers/sql-compiler.cjs +1 -0
- package/dist/drivers/sql-compiler.cjs.map +1 -1
- package/dist/drivers/sql-compiler.mjs +1 -0
- package/dist/drivers/sql-compiler.mjs.map +1 -1
- package/dist/drivers/sqlite.cjs +1 -0
- package/dist/drivers/sqlite.cjs.map +1 -1
- package/dist/drivers/sqlite.mjs +1 -0
- package/dist/drivers/sqlite.mjs.map +1 -1
- package/package.json +3 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Hedystia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.cjs","names":[],"sources":["../../src/drivers/driver.ts"],"sourcesContent":["import type { ColumnMetadata, DatabaseDriver, TableMetadata } from \"../types\";\n\n/**\n * Abstract base class for database drivers\n */\nexport abstract class BaseDriver implements DatabaseDriver {\n protected connected = false;\n\n /**\n * Connect to the database\n */\n abstract connect(): Promise<void>;\n\n /**\n * Disconnect from the database\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Execute a SQL statement that does not return rows\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n abstract execute(sql: string, params?: unknown[]): Promise<any>;\n\n /**\n * Execute a SQL query that returns rows\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n abstract query(sql: string, params?: unknown[]): Promise<any[]>;\n\n /**\n * Check if a table exists in the database\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n abstract tableExists(name: string): Promise<boolean>;\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata array\n */\n abstract getTableColumns(name: string): Promise<ColumnMetadata[]>;\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n abstract createTable(meta: TableMetadata): Promise<void>;\n\n /**\n * Drop a table by name\n * @param {string} name - Table name\n */\n abstract dropTable(name: string): Promise<void>;\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n abstract addColumn(table: string, column: ColumnMetadata): Promise<void>;\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n abstract dropColumn(table: string, name: string): Promise<void>;\n\n /**\n * Rename a column in a table\n * @param {string} table - Table name\n * @param {string} oldName - Current column name\n * @param {string} newName - New column name\n */\n abstract renameColumn(table: string, oldName: string, newName: string): Promise<void>;\n\n /**\n * Execute a function within a transaction\n * @param {() => Promise<T>} fn - Function to execute within the transaction\n * @returns {Promise<T>} Function result\n */\n abstract transaction<T>(fn: () => Promise<T>): Promise<T>;\n}\n"],"mappings":";;;;AAKA,IAAsB,aAAtB,MAA2D;CACzD,YAAsB"}
|
|
1
|
+
{"version":3,"file":"driver.cjs","names":[],"sources":["../../src/drivers/driver.ts"],"sourcesContent":["import type { ColumnMetadata, DatabaseDriver, DatabaseType, TableMetadata } from \"../types\";\n\n/**\n * Abstract base class for database drivers\n */\nexport abstract class BaseDriver implements DatabaseDriver {\n protected connected = false;\n abstract readonly dialect: DatabaseType;\n\n /**\n * Connect to the database\n */\n abstract connect(): Promise<void>;\n\n /**\n * Disconnect from the database\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Execute a SQL statement that does not return rows\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n abstract execute(sql: string, params?: unknown[]): Promise<any>;\n\n /**\n * Execute a SQL query that returns rows\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n abstract query(sql: string, params?: unknown[]): Promise<any[]>;\n\n /**\n * Check if a table exists in the database\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n abstract tableExists(name: string): Promise<boolean>;\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata array\n */\n abstract getTableColumns(name: string): Promise<ColumnMetadata[]>;\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n abstract createTable(meta: TableMetadata): Promise<void>;\n\n /**\n * Drop a table by name\n * @param {string} name - Table name\n */\n abstract dropTable(name: string): Promise<void>;\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n abstract addColumn(table: string, column: ColumnMetadata): Promise<void>;\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n abstract dropColumn(table: string, name: string): Promise<void>;\n\n /**\n * Rename a column in a table\n * @param {string} table - Table name\n * @param {string} oldName - Current column name\n * @param {string} newName - New column name\n */\n abstract renameColumn(table: string, oldName: string, newName: string): Promise<void>;\n\n /**\n * Execute a function within a transaction\n * @param {() => Promise<T>} fn - Function to execute within the transaction\n * @returns {Promise<T>} Function result\n */\n abstract transaction<T>(fn: () => Promise<T>): Promise<T>;\n}\n"],"mappings":";;;;AAKA,IAAsB,aAAtB,MAA2D;CACzD,YAAsB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.mjs","names":[],"sources":["../../src/drivers/driver.ts"],"sourcesContent":["import type { ColumnMetadata, DatabaseDriver, TableMetadata } from \"../types\";\n\n/**\n * Abstract base class for database drivers\n */\nexport abstract class BaseDriver implements DatabaseDriver {\n protected connected = false;\n\n /**\n * Connect to the database\n */\n abstract connect(): Promise<void>;\n\n /**\n * Disconnect from the database\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Execute a SQL statement that does not return rows\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n abstract execute(sql: string, params?: unknown[]): Promise<any>;\n\n /**\n * Execute a SQL query that returns rows\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n abstract query(sql: string, params?: unknown[]): Promise<any[]>;\n\n /**\n * Check if a table exists in the database\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n abstract tableExists(name: string): Promise<boolean>;\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata array\n */\n abstract getTableColumns(name: string): Promise<ColumnMetadata[]>;\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n abstract createTable(meta: TableMetadata): Promise<void>;\n\n /**\n * Drop a table by name\n * @param {string} name - Table name\n */\n abstract dropTable(name: string): Promise<void>;\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n abstract addColumn(table: string, column: ColumnMetadata): Promise<void>;\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n abstract dropColumn(table: string, name: string): Promise<void>;\n\n /**\n * Rename a column in a table\n * @param {string} table - Table name\n * @param {string} oldName - Current column name\n * @param {string} newName - New column name\n */\n abstract renameColumn(table: string, oldName: string, newName: string): Promise<void>;\n\n /**\n * Execute a function within a transaction\n * @param {() => Promise<T>} fn - Function to execute within the transaction\n * @returns {Promise<T>} Function result\n */\n abstract transaction<T>(fn: () => Promise<T>): Promise<T>;\n}\n"],"mappings":";;;;AAKsB,cAAtB,MAA2D;EACzD,YAAsB"}
|
|
1
|
+
{"version":3,"file":"driver.mjs","names":[],"sources":["../../src/drivers/driver.ts"],"sourcesContent":["import type { ColumnMetadata, DatabaseDriver, DatabaseType, TableMetadata } from \"../types\";\n\n/**\n * Abstract base class for database drivers\n */\nexport abstract class BaseDriver implements DatabaseDriver {\n protected connected = false;\n abstract readonly dialect: DatabaseType;\n\n /**\n * Connect to the database\n */\n abstract connect(): Promise<void>;\n\n /**\n * Disconnect from the database\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Execute a SQL statement that does not return rows\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n abstract execute(sql: string, params?: unknown[]): Promise<any>;\n\n /**\n * Execute a SQL query that returns rows\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n abstract query(sql: string, params?: unknown[]): Promise<any[]>;\n\n /**\n * Check if a table exists in the database\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n abstract tableExists(name: string): Promise<boolean>;\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata array\n */\n abstract getTableColumns(name: string): Promise<ColumnMetadata[]>;\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n abstract createTable(meta: TableMetadata): Promise<void>;\n\n /**\n * Drop a table by name\n * @param {string} name - Table name\n */\n abstract dropTable(name: string): Promise<void>;\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n abstract addColumn(table: string, column: ColumnMetadata): Promise<void>;\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n abstract dropColumn(table: string, name: string): Promise<void>;\n\n /**\n * Rename a column in a table\n * @param {string} table - Table name\n * @param {string} oldName - Current column name\n * @param {string} newName - New column name\n */\n abstract renameColumn(table: string, oldName: string, newName: string): Promise<void>;\n\n /**\n * Execute a function within a transaction\n * @param {() => Promise<T>} fn - Function to execute within the transaction\n * @returns {Promise<T>} Function result\n */\n abstract transaction<T>(fn: () => Promise<T>): Promise<T>;\n}\n"],"mappings":";;;;AAKsB,cAAtB,MAA2D;EACzD,YAAsB"}
|
package/dist/drivers/file.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.cjs","names":["BaseDriver","DriverError"],"sources":["../../src/drivers/file.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { DriverError } from \"../errors\";\nimport type { ColumnMetadata, FileConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\n\ninterface FileTableData {\n rows: Record<string, unknown>[];\n autoIncrementId: number;\n meta: {\n columns: ColumnMetadata[];\n };\n}\n\n/**\n * File-based database driver using JSON files for storage\n */\nexport class FileDriver extends BaseDriver {\n private config: FileConnectionConfig;\n private data = new Map<string, FileTableData>();\n\n constructor(config: FileConnectionConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Connect to the file database (ensures directory exists and loads data)\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n if (!existsSync(this.config.directory)) {\n mkdirSync(this.config.directory, { recursive: true });\n }\n this.loadAll();\n this.connected = true;\n }\n\n /**\n * Disconnect from the file database (flushes data to disk)\n */\n async disconnect(): Promise<void> {\n this.flushAll();\n this.data.clear();\n this.connected = false;\n }\n\n /**\n * Execute a SQL-like statement (parsed internally for file driver)\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n return this.executeParsed(sql, params);\n }\n\n /**\n * Execute a SQL-like query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n const result = this.executeParsed(sql, params);\n return Array.isArray(result) ? result : [];\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n return this.data.has(name);\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const table = this.data.get(name);\n if (!table) {\n return [];\n }\n return Object.values(table.meta.columns);\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n if (this.data.has(meta.name)) {\n return;\n }\n this.data.set(meta.name, {\n rows: [],\n autoIncrementId: 0,\n meta: { columns: [...meta.columns] },\n });\n this.flush(meta.name);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n this.data.delete(name);\n const filePath = join(this.config.directory, `${name}.json`);\n try {\n const { unlinkSync } = await import(\"fs\");\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n } catch {}\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns.push(column);\n for (const row of tableData.rows) {\n row[column.name] = column.defaultValue ?? null;\n }\n this.flush(table);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns = tableData.meta.columns.filter((c) => c.name !== name);\n for (const row of tableData.rows) {\n delete row[name];\n }\n this.flush(table);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n const col = tableData.meta.columns.find((c) => c.name === oldName);\n if (col) {\n col.name = newName;\n }\n for (const row of tableData.rows) {\n row[newName] = row[oldName];\n delete row[oldName];\n }\n this.flush(table);\n }\n\n /**\n * Execute within a transaction (pseudo-transaction for file driver)\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const snapshot = new Map<string, string>();\n for (const [name, tableData] of this.data) {\n snapshot.set(name, JSON.stringify(tableData));\n }\n try {\n const result = await fn();\n this.flushAll();\n return result;\n } catch (err) {\n for (const [name, json] of snapshot) {\n this.data.set(name, JSON.parse(json));\n }\n throw err;\n }\n }\n\n /**\n * Batch fetch all table columns (already in memory for file driver)\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n const result: Record<string, ColumnMetadata[]> = {};\n for (const [name, tableData] of this.data) {\n result[name] = [...tableData.meta.columns];\n }\n return result;\n }\n\n private loadAll(): void {\n if (!existsSync(this.config.directory)) {\n return;\n }\n const { readdirSync } = require(\"fs\");\n const files = readdirSync(this.config.directory) as string[];\n for (const file of files) {\n if (file.endsWith(\".json\")) {\n const name = file.replace(\".json\", \"\");\n try {\n const content = readFileSync(join(this.config.directory, file), \"utf-8\");\n this.data.set(name, JSON.parse(content));\n } catch {}\n }\n }\n }\n\n private flush(tableName: string): void {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return;\n }\n const filePath = join(this.config.directory, `${tableName}.json`);\n writeFileSync(filePath, JSON.stringify(tableData, null, 2), \"utf-8\");\n }\n\n private flushAll(): void {\n for (const [name] of this.data) {\n this.flush(name);\n }\n }\n\n private executeParsed(sql: string, params: unknown[]): any {\n const trimmed = sql.trim().toUpperCase();\n\n if (trimmed.startsWith(\"CREATE TABLE\")) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"DROP TABLE\")) {\n const match = sql.match(/DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?`?(\\w+)`?/i);\n if (match?.[1]) {\n this.data.delete(match[1]);\n }\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"INSERT\")) {\n return this.handleInsert(sql, params);\n }\n\n if (trimmed.startsWith(\"UPDATE\")) {\n return this.handleUpdate(sql, params);\n }\n if (trimmed.startsWith(\"DELETE\")) {\n return this.handleDelete(sql, params);\n }\n\n if (trimmed.startsWith(\"SELECT\")) {\n return this.handleSelect(sql, params);\n }\n\n return { insertId: 0, affectedRows: 0 };\n }\n\n private handleInsert(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/INTO\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const colMatch = sql.match(/\\(([^)]+)\\)\\s+VALUES/i);\n if (!colMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const cols = colMatch[1]\n .split(\",\")\n .map((c) => c.trim().replace(/`/g, \"\"))\n .filter(Boolean);\n\n const rowCount = Math.floor(params.length / cols.length);\n\n let insertId = 0;\n let pkCol: string | null = null;\n for (const col of tableData.meta.columns) {\n if (col.autoIncrement) {\n pkCol = col.name;\n break;\n }\n }\n\n for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {\n const row: Record<string, unknown> = {};\n const rowParamStart = rowIdx * cols.length;\n\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i];\n if (col) {\n row[col] = params[rowParamStart + i];\n }\n }\n\n if (pkCol && row[pkCol] === undefined) {\n tableData.autoIncrementId++;\n row[pkCol] = tableData.autoIncrementId;\n if (rowIdx === 0) {\n insertId = tableData.autoIncrementId;\n }\n } else if (pkCol && row[pkCol]) {\n if (rowIdx === 0) {\n insertId = row[pkCol] as number;\n }\n }\n\n tableData.rows.push({ ...row });\n }\n\n this.flush(tableName);\n\n return { insertId, affectedRows: rowCount };\n }\n\n private handleUpdate(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/UPDATE\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const setMatch = sql.match(/SET\\s+(.+?)\\s+WHERE/i) || sql.match(/SET\\s+(.+)$/i);\n if (!setMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const setClauses = setMatch[1].split(\",\");\n const updates: Record<string, unknown> = {};\n let paramIndex = 0;\n\n for (const clause of setClauses) {\n const eqMatch = clause.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch?.[1]) {\n updates[eqMatch[1]] = params[paramIndex];\n paramIndex++;\n }\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n const whereConditions = whereMatch?.[1] || \"\";\n\n let affectedRows = 0;\n for (const row of tableData.rows) {\n if (this.matchesWhere(row, whereConditions, params, paramIndex)) {\n Object.assign(row, updates);\n affectedRows++;\n }\n }\n\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleDelete(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n if (!whereMatch?.[1]) {\n const affectedRows = tableData.rows.length;\n tableData.rows = [];\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n return { affectedRows };\n }\n\n const whereConditions = whereMatch[1];\n const before = tableData.rows.length;\n\n tableData.rows = tableData.rows.filter(\n (row) => !this.matchesWhere(row, whereConditions, params, 0),\n );\n\n const affectedRows = before - tableData.rows.length;\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleSelect(sql: string, params: unknown[]): any {\n const countMatch = sql.match(/SELECT\\s+COUNT\\s*\\(\\s*\\*\\s*\\)\\s+as\\s+(\\w+)/i);\n if (countMatch) {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [{ count: 0 }];\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n const filter = (row: Record<string, unknown>) =>\n this.matchesWhere(row, whereMatch[1]!, params, 0);\n const count = tableData.rows.filter(filter).length;\n return [{ count }];\n }\n\n return [{ count: tableData.rows.length }];\n }\n\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [];\n }\n\n let rows = [...tableData.rows];\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER\\s+BY|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n rows = rows.filter((row) => this.matchesWhere(row, whereMatch[1]!, params, 0));\n }\n\n const orderMatch = sql.match(/ORDER\\s+BY\\s+(.+?)(?:\\s+LIMIT|\\s*$)/i);\n if (orderMatch?.[1]) {\n const orders = orderMatch[1].split(\",\");\n rows.sort((a, b) => {\n for (const orderClause of orders) {\n const [col, dir] = orderClause.trim().split(/\\s+/);\n const colName = col?.replace(/`/g, \"\") ?? \"\";\n const aVal = (a as any)[colName];\n const bVal = (b as any)[colName];\n if (aVal < bVal) {\n return dir?.toUpperCase() === \"DESC\" ? 1 : -1;\n }\n if (aVal > bVal) {\n return dir?.toUpperCase() === \"DESC\" ? -1 : 1;\n }\n }\n return 0;\n });\n }\n\n const limitMatch = sql.match(/LIMIT\\s+(\\d+)(?:\\s+OFFSET\\s+(\\d+)|\\s*,\\s*(\\d+))?/i);\n if (limitMatch) {\n const limit = Number.parseInt(limitMatch[1]!, 10);\n const offset = limitMatch[2]\n ? Number.parseInt(limitMatch[2], 10)\n : limitMatch[3]\n ? Number.parseInt(limitMatch[3], 10)\n : 0;\n rows = rows.slice(offset, offset + limit);\n }\n\n return rows.map((r) => ({ ...r }));\n }\n\n private matchesWhere(\n row: Record<string, unknown>,\n whereStr: string,\n params: unknown[],\n paramOffset: number,\n ): boolean {\n return this.evaluateWhereExpression(row, whereStr, params, paramOffset).matched;\n }\n\n private evaluateWhereExpression(\n row: Record<string, unknown>,\n expr: string,\n params: unknown[],\n startParamIdx: number,\n ): { matched: boolean; paramIdx: number } {\n let paramIdx = startParamIdx;\n expr = expr.trim();\n\n if (expr.startsWith(\"(\") && expr.endsWith(\")\")) {\n const result = this.evaluateWhereExpression(row, expr.slice(1, -1), params, paramIdx);\n return result;\n }\n\n const orClauses = this.splitByTopLevel(expr, \"OR\");\n if (orClauses.length > 1) {\n for (const orClause of orClauses) {\n const result = this.evaluateWhereExpression(row, orClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (result.matched) {\n return { matched: true, paramIdx };\n }\n }\n return { matched: false, paramIdx };\n }\n\n const andClauses = this.splitByTopLevel(expr, \"AND\");\n if (andClauses.length > 1) {\n for (const andClause of andClauses) {\n const result = this.evaluateWhereExpression(row, andClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (!result.matched) {\n return { matched: false, paramIdx };\n }\n }\n return { matched: true, paramIdx };\n }\n\n return this.evaluateSingleCondition(row, expr, params, paramIdx);\n }\n\n private splitByTopLevel(expr: string, operator: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n const opRegex = new RegExp(`\\\\s+${operator}\\\\s+`, \"i\");\n let i = 0;\n\n while (i < expr.length) {\n const char = expr[i];\n\n if (char === \"(\") {\n parenDepth++;\n current += char;\n i++;\n } else if (char === \")\") {\n parenDepth--;\n current += char;\n i++;\n } else if (parenDepth === 0) {\n const remaining = expr.slice(i);\n const match = remaining.match(opRegex);\n\n if (match && match.index === 0) {\n if (current.trim()) {\n parts.push(current.trim());\n }\n i += match[0]!.length;\n current = \"\";\n } else {\n current += char;\n i++;\n }\n } else {\n current += char;\n i++;\n }\n }\n\n if (current.trim()) {\n parts.push(current.trim());\n }\n\n return parts.length > 0 ? parts : [expr];\n }\n\n private evaluateSingleCondition(\n row: Record<string, unknown>,\n condition: string,\n params: unknown[],\n paramIdx: number,\n ): { matched: boolean; paramIdx: number } {\n condition = condition.trim();\n\n const notInMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+IN\\s+\\(([^)]*)\\)/i);\n if (notInMatch) {\n const col = notInMatch[1]!;\n const placeholders = notInMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = !values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const inMatch = condition.match(/`?(\\w+)`?\\s+IN\\s+\\(([^)]*)\\)/i);\n if (inMatch) {\n const col = inMatch[1]!;\n const placeholders = inMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const eqMatch = condition.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch) {\n const matched = row[eqMatch[1]!] === params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const neqMatch = condition.match(/`?(\\w+)`?\\s*!=\\s*\\?/);\n if (neqMatch) {\n const matched = row[neqMatch[1]!] !== params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gtMatch = condition.match(/`?(\\w+)`?\\s*>\\s*\\?/);\n if (gtMatch) {\n const matched = (row[gtMatch[1]!] as any) > (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gteMatch = condition.match(/`?(\\w+)`?\\s*>=\\s*\\?/);\n if (gteMatch) {\n const matched = (row[gteMatch[1]!] as any) >= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const ltMatch = condition.match(/`?(\\w+)`?\\s*<\\s*\\?/);\n if (ltMatch) {\n const matched = (row[ltMatch[1]!] as any) < (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const lteMatch = condition.match(/`?(\\w+)`?\\s*<=\\s*\\?/);\n if (lteMatch) {\n const matched = (row[lteMatch[1]!] as any) <= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const notLikeMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+LIKE\\s+\\?/i);\n if (notLikeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = !new RegExp(`^${pattern}$`).test(String(row[notLikeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const likeMatch = condition.match(/`?(\\w+)`?\\s+LIKE\\s+\\?/i);\n if (likeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = new RegExp(`^${pattern}$`).test(String(row[likeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n return { matched: true, paramIdx };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file.cjs","names":["BaseDriver","DriverError"],"sources":["../../src/drivers/file.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { DriverError } from \"../errors\";\nimport type { ColumnMetadata, FileConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\n\ninterface FileTableData {\n rows: Record<string, unknown>[];\n autoIncrementId: number;\n meta: {\n columns: ColumnMetadata[];\n };\n}\n\n/**\n * File-based database driver using JSON files for storage\n */\nexport class FileDriver extends BaseDriver {\n readonly dialect = \"file\" as const;\n private config: FileConnectionConfig;\n private data = new Map<string, FileTableData>();\n\n constructor(config: FileConnectionConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Connect to the file database (ensures directory exists and loads data)\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n if (!existsSync(this.config.directory)) {\n mkdirSync(this.config.directory, { recursive: true });\n }\n this.loadAll();\n this.connected = true;\n }\n\n /**\n * Disconnect from the file database (flushes data to disk)\n */\n async disconnect(): Promise<void> {\n this.flushAll();\n this.data.clear();\n this.connected = false;\n }\n\n /**\n * Execute a SQL-like statement (parsed internally for file driver)\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n return this.executeParsed(sql, params);\n }\n\n /**\n * Execute a SQL-like query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n const result = this.executeParsed(sql, params);\n return Array.isArray(result) ? result : [];\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n return this.data.has(name);\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const table = this.data.get(name);\n if (!table) {\n return [];\n }\n return Object.values(table.meta.columns);\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n if (this.data.has(meta.name)) {\n return;\n }\n this.data.set(meta.name, {\n rows: [],\n autoIncrementId: 0,\n meta: { columns: [...meta.columns] },\n });\n this.flush(meta.name);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n this.data.delete(name);\n const filePath = join(this.config.directory, `${name}.json`);\n try {\n const { unlinkSync } = await import(\"fs\");\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n } catch {}\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns.push(column);\n for (const row of tableData.rows) {\n row[column.name] = column.defaultValue ?? null;\n }\n this.flush(table);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns = tableData.meta.columns.filter((c) => c.name !== name);\n for (const row of tableData.rows) {\n delete row[name];\n }\n this.flush(table);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n const col = tableData.meta.columns.find((c) => c.name === oldName);\n if (col) {\n col.name = newName;\n }\n for (const row of tableData.rows) {\n row[newName] = row[oldName];\n delete row[oldName];\n }\n this.flush(table);\n }\n\n /**\n * Execute within a transaction (pseudo-transaction for file driver)\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const snapshot = new Map<string, string>();\n for (const [name, tableData] of this.data) {\n snapshot.set(name, JSON.stringify(tableData));\n }\n try {\n const result = await fn();\n this.flushAll();\n return result;\n } catch (err) {\n for (const [name, json] of snapshot) {\n this.data.set(name, JSON.parse(json));\n }\n throw err;\n }\n }\n\n /**\n * Batch fetch all table columns (already in memory for file driver)\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n const result: Record<string, ColumnMetadata[]> = {};\n for (const [name, tableData] of this.data) {\n result[name] = [...tableData.meta.columns];\n }\n return result;\n }\n\n private loadAll(): void {\n if (!existsSync(this.config.directory)) {\n return;\n }\n const { readdirSync } = require(\"fs\");\n const files = readdirSync(this.config.directory) as string[];\n for (const file of files) {\n if (file.endsWith(\".json\")) {\n const name = file.replace(\".json\", \"\");\n try {\n const content = readFileSync(join(this.config.directory, file), \"utf-8\");\n this.data.set(name, JSON.parse(content));\n } catch {}\n }\n }\n }\n\n private flush(tableName: string): void {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return;\n }\n const filePath = join(this.config.directory, `${tableName}.json`);\n writeFileSync(filePath, JSON.stringify(tableData, null, 2), \"utf-8\");\n }\n\n private flushAll(): void {\n for (const [name] of this.data) {\n this.flush(name);\n }\n }\n\n private executeParsed(sql: string, params: unknown[]): any {\n const trimmed = sql.trim().toUpperCase();\n\n if (trimmed.startsWith(\"CREATE TABLE\")) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"DROP TABLE\")) {\n const match = sql.match(/DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?`?(\\w+)`?/i);\n if (match?.[1]) {\n this.data.delete(match[1]);\n }\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"INSERT\")) {\n return this.handleInsert(sql, params);\n }\n\n if (trimmed.startsWith(\"UPDATE\")) {\n return this.handleUpdate(sql, params);\n }\n if (trimmed.startsWith(\"DELETE\")) {\n return this.handleDelete(sql, params);\n }\n\n if (trimmed.startsWith(\"SELECT\")) {\n return this.handleSelect(sql, params);\n }\n\n return { insertId: 0, affectedRows: 0 };\n }\n\n private handleInsert(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/INTO\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const colMatch = sql.match(/\\(([^)]+)\\)\\s+VALUES/i);\n if (!colMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const cols = colMatch[1]\n .split(\",\")\n .map((c) => c.trim().replace(/`/g, \"\"))\n .filter(Boolean);\n\n const rowCount = Math.floor(params.length / cols.length);\n\n let insertId = 0;\n let pkCol: string | null = null;\n for (const col of tableData.meta.columns) {\n if (col.autoIncrement) {\n pkCol = col.name;\n break;\n }\n }\n\n for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {\n const row: Record<string, unknown> = {};\n const rowParamStart = rowIdx * cols.length;\n\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i];\n if (col) {\n row[col] = params[rowParamStart + i];\n }\n }\n\n if (pkCol && row[pkCol] === undefined) {\n tableData.autoIncrementId++;\n row[pkCol] = tableData.autoIncrementId;\n if (rowIdx === 0) {\n insertId = tableData.autoIncrementId;\n }\n } else if (pkCol && row[pkCol]) {\n if (rowIdx === 0) {\n insertId = row[pkCol] as number;\n }\n }\n\n tableData.rows.push({ ...row });\n }\n\n this.flush(tableName);\n\n return { insertId, affectedRows: rowCount };\n }\n\n private handleUpdate(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/UPDATE\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const setMatch = sql.match(/SET\\s+(.+?)\\s+WHERE/i) || sql.match(/SET\\s+(.+)$/i);\n if (!setMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const setClauses = setMatch[1].split(\",\");\n const updates: Record<string, unknown> = {};\n let paramIndex = 0;\n\n for (const clause of setClauses) {\n const eqMatch = clause.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch?.[1]) {\n updates[eqMatch[1]] = params[paramIndex];\n paramIndex++;\n }\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n const whereConditions = whereMatch?.[1] || \"\";\n\n let affectedRows = 0;\n for (const row of tableData.rows) {\n if (this.matchesWhere(row, whereConditions, params, paramIndex)) {\n Object.assign(row, updates);\n affectedRows++;\n }\n }\n\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleDelete(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n if (!whereMatch?.[1]) {\n const affectedRows = tableData.rows.length;\n tableData.rows = [];\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n return { affectedRows };\n }\n\n const whereConditions = whereMatch[1];\n const before = tableData.rows.length;\n\n tableData.rows = tableData.rows.filter(\n (row) => !this.matchesWhere(row, whereConditions, params, 0),\n );\n\n const affectedRows = before - tableData.rows.length;\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleSelect(sql: string, params: unknown[]): any {\n const countMatch = sql.match(/SELECT\\s+COUNT\\s*\\(\\s*\\*\\s*\\)\\s+as\\s+(\\w+)/i);\n if (countMatch) {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [{ count: 0 }];\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n const filter = (row: Record<string, unknown>) =>\n this.matchesWhere(row, whereMatch[1]!, params, 0);\n const count = tableData.rows.filter(filter).length;\n return [{ count }];\n }\n\n return [{ count: tableData.rows.length }];\n }\n\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [];\n }\n\n let rows = [...tableData.rows];\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER\\s+BY|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n rows = rows.filter((row) => this.matchesWhere(row, whereMatch[1]!, params, 0));\n }\n\n const orderMatch = sql.match(/ORDER\\s+BY\\s+(.+?)(?:\\s+LIMIT|\\s*$)/i);\n if (orderMatch?.[1]) {\n const orders = orderMatch[1].split(\",\");\n rows.sort((a, b) => {\n for (const orderClause of orders) {\n const [col, dir] = orderClause.trim().split(/\\s+/);\n const colName = col?.replace(/`/g, \"\") ?? \"\";\n const aVal = (a as any)[colName];\n const bVal = (b as any)[colName];\n if (aVal < bVal) {\n return dir?.toUpperCase() === \"DESC\" ? 1 : -1;\n }\n if (aVal > bVal) {\n return dir?.toUpperCase() === \"DESC\" ? -1 : 1;\n }\n }\n return 0;\n });\n }\n\n const limitMatch = sql.match(/LIMIT\\s+(\\d+)(?:\\s+OFFSET\\s+(\\d+)|\\s*,\\s*(\\d+))?/i);\n if (limitMatch) {\n const limit = Number.parseInt(limitMatch[1]!, 10);\n const offset = limitMatch[2]\n ? Number.parseInt(limitMatch[2], 10)\n : limitMatch[3]\n ? Number.parseInt(limitMatch[3], 10)\n : 0;\n rows = rows.slice(offset, offset + limit);\n }\n\n return rows.map((r) => ({ ...r }));\n }\n\n private matchesWhere(\n row: Record<string, unknown>,\n whereStr: string,\n params: unknown[],\n paramOffset: number,\n ): boolean {\n return this.evaluateWhereExpression(row, whereStr, params, paramOffset).matched;\n }\n\n private evaluateWhereExpression(\n row: Record<string, unknown>,\n expr: string,\n params: unknown[],\n startParamIdx: number,\n ): { matched: boolean; paramIdx: number } {\n let paramIdx = startParamIdx;\n expr = expr.trim();\n\n if (expr.startsWith(\"(\") && expr.endsWith(\")\")) {\n const result = this.evaluateWhereExpression(row, expr.slice(1, -1), params, paramIdx);\n return result;\n }\n\n const orClauses = this.splitByTopLevel(expr, \"OR\");\n if (orClauses.length > 1) {\n for (const orClause of orClauses) {\n const result = this.evaluateWhereExpression(row, orClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (result.matched) {\n return { matched: true, paramIdx };\n }\n }\n return { matched: false, paramIdx };\n }\n\n const andClauses = this.splitByTopLevel(expr, \"AND\");\n if (andClauses.length > 1) {\n for (const andClause of andClauses) {\n const result = this.evaluateWhereExpression(row, andClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (!result.matched) {\n return { matched: false, paramIdx };\n }\n }\n return { matched: true, paramIdx };\n }\n\n return this.evaluateSingleCondition(row, expr, params, paramIdx);\n }\n\n private splitByTopLevel(expr: string, operator: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n const opRegex = new RegExp(`\\\\s+${operator}\\\\s+`, \"i\");\n let i = 0;\n\n while (i < expr.length) {\n const char = expr[i];\n\n if (char === \"(\") {\n parenDepth++;\n current += char;\n i++;\n } else if (char === \")\") {\n parenDepth--;\n current += char;\n i++;\n } else if (parenDepth === 0) {\n const remaining = expr.slice(i);\n const match = remaining.match(opRegex);\n\n if (match && match.index === 0) {\n if (current.trim()) {\n parts.push(current.trim());\n }\n i += match[0]!.length;\n current = \"\";\n } else {\n current += char;\n i++;\n }\n } else {\n current += char;\n i++;\n }\n }\n\n if (current.trim()) {\n parts.push(current.trim());\n }\n\n return parts.length > 0 ? parts : [expr];\n }\n\n private evaluateSingleCondition(\n row: Record<string, unknown>,\n condition: string,\n params: unknown[],\n paramIdx: number,\n ): { matched: boolean; paramIdx: number } {\n condition = condition.trim();\n\n const notInMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+IN\\s+\\(([^)]*)\\)/i);\n if (notInMatch) {\n const col = notInMatch[1]!;\n const placeholders = notInMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = !values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const inMatch = condition.match(/`?(\\w+)`?\\s+IN\\s+\\(([^)]*)\\)/i);\n if (inMatch) {\n const col = inMatch[1]!;\n const placeholders = inMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const eqMatch = condition.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch) {\n const matched = row[eqMatch[1]!] === params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const neqMatch = condition.match(/`?(\\w+)`?\\s*!=\\s*\\?/);\n if (neqMatch) {\n const matched = row[neqMatch[1]!] !== params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gtMatch = condition.match(/`?(\\w+)`?\\s*>\\s*\\?/);\n if (gtMatch) {\n const matched = (row[gtMatch[1]!] as any) > (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gteMatch = condition.match(/`?(\\w+)`?\\s*>=\\s*\\?/);\n if (gteMatch) {\n const matched = (row[gteMatch[1]!] as any) >= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const ltMatch = condition.match(/`?(\\w+)`?\\s*<\\s*\\?/);\n if (ltMatch) {\n const matched = (row[ltMatch[1]!] as any) < (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const lteMatch = condition.match(/`?(\\w+)`?\\s*<=\\s*\\?/);\n if (lteMatch) {\n const matched = (row[lteMatch[1]!] as any) <= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const notLikeMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+LIKE\\s+\\?/i);\n if (notLikeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = !new RegExp(`^${pattern}$`).test(String(row[notLikeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const likeMatch = condition.match(/`?(\\w+)`?\\s+LIKE\\s+\\?/i);\n if (likeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = new RegExp(`^${pattern}$`).test(String(row[likeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n return { matched: true, paramIdx };\n }\n}\n"],"mappings":"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"}
|
package/dist/drivers/file.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.mjs","names":[],"sources":["../../src/drivers/file.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { DriverError } from \"../errors\";\nimport type { ColumnMetadata, FileConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\n\ninterface FileTableData {\n rows: Record<string, unknown>[];\n autoIncrementId: number;\n meta: {\n columns: ColumnMetadata[];\n };\n}\n\n/**\n * File-based database driver using JSON files for storage\n */\nexport class FileDriver extends BaseDriver {\n private config: FileConnectionConfig;\n private data = new Map<string, FileTableData>();\n\n constructor(config: FileConnectionConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Connect to the file database (ensures directory exists and loads data)\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n if (!existsSync(this.config.directory)) {\n mkdirSync(this.config.directory, { recursive: true });\n }\n this.loadAll();\n this.connected = true;\n }\n\n /**\n * Disconnect from the file database (flushes data to disk)\n */\n async disconnect(): Promise<void> {\n this.flushAll();\n this.data.clear();\n this.connected = false;\n }\n\n /**\n * Execute a SQL-like statement (parsed internally for file driver)\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n return this.executeParsed(sql, params);\n }\n\n /**\n * Execute a SQL-like query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n const result = this.executeParsed(sql, params);\n return Array.isArray(result) ? result : [];\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n return this.data.has(name);\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const table = this.data.get(name);\n if (!table) {\n return [];\n }\n return Object.values(table.meta.columns);\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n if (this.data.has(meta.name)) {\n return;\n }\n this.data.set(meta.name, {\n rows: [],\n autoIncrementId: 0,\n meta: { columns: [...meta.columns] },\n });\n this.flush(meta.name);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n this.data.delete(name);\n const filePath = join(this.config.directory, `${name}.json`);\n try {\n const { unlinkSync } = await import(\"fs\");\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n } catch {}\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns.push(column);\n for (const row of tableData.rows) {\n row[column.name] = column.defaultValue ?? null;\n }\n this.flush(table);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns = tableData.meta.columns.filter((c) => c.name !== name);\n for (const row of tableData.rows) {\n delete row[name];\n }\n this.flush(table);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n const col = tableData.meta.columns.find((c) => c.name === oldName);\n if (col) {\n col.name = newName;\n }\n for (const row of tableData.rows) {\n row[newName] = row[oldName];\n delete row[oldName];\n }\n this.flush(table);\n }\n\n /**\n * Execute within a transaction (pseudo-transaction for file driver)\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const snapshot = new Map<string, string>();\n for (const [name, tableData] of this.data) {\n snapshot.set(name, JSON.stringify(tableData));\n }\n try {\n const result = await fn();\n this.flushAll();\n return result;\n } catch (err) {\n for (const [name, json] of snapshot) {\n this.data.set(name, JSON.parse(json));\n }\n throw err;\n }\n }\n\n /**\n * Batch fetch all table columns (already in memory for file driver)\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n const result: Record<string, ColumnMetadata[]> = {};\n for (const [name, tableData] of this.data) {\n result[name] = [...tableData.meta.columns];\n }\n return result;\n }\n\n private loadAll(): void {\n if (!existsSync(this.config.directory)) {\n return;\n }\n const { readdirSync } = require(\"fs\");\n const files = readdirSync(this.config.directory) as string[];\n for (const file of files) {\n if (file.endsWith(\".json\")) {\n const name = file.replace(\".json\", \"\");\n try {\n const content = readFileSync(join(this.config.directory, file), \"utf-8\");\n this.data.set(name, JSON.parse(content));\n } catch {}\n }\n }\n }\n\n private flush(tableName: string): void {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return;\n }\n const filePath = join(this.config.directory, `${tableName}.json`);\n writeFileSync(filePath, JSON.stringify(tableData, null, 2), \"utf-8\");\n }\n\n private flushAll(): void {\n for (const [name] of this.data) {\n this.flush(name);\n }\n }\n\n private executeParsed(sql: string, params: unknown[]): any {\n const trimmed = sql.trim().toUpperCase();\n\n if (trimmed.startsWith(\"CREATE TABLE\")) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"DROP TABLE\")) {\n const match = sql.match(/DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?`?(\\w+)`?/i);\n if (match?.[1]) {\n this.data.delete(match[1]);\n }\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"INSERT\")) {\n return this.handleInsert(sql, params);\n }\n\n if (trimmed.startsWith(\"UPDATE\")) {\n return this.handleUpdate(sql, params);\n }\n if (trimmed.startsWith(\"DELETE\")) {\n return this.handleDelete(sql, params);\n }\n\n if (trimmed.startsWith(\"SELECT\")) {\n return this.handleSelect(sql, params);\n }\n\n return { insertId: 0, affectedRows: 0 };\n }\n\n private handleInsert(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/INTO\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const colMatch = sql.match(/\\(([^)]+)\\)\\s+VALUES/i);\n if (!colMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const cols = colMatch[1]\n .split(\",\")\n .map((c) => c.trim().replace(/`/g, \"\"))\n .filter(Boolean);\n\n const rowCount = Math.floor(params.length / cols.length);\n\n let insertId = 0;\n let pkCol: string | null = null;\n for (const col of tableData.meta.columns) {\n if (col.autoIncrement) {\n pkCol = col.name;\n break;\n }\n }\n\n for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {\n const row: Record<string, unknown> = {};\n const rowParamStart = rowIdx * cols.length;\n\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i];\n if (col) {\n row[col] = params[rowParamStart + i];\n }\n }\n\n if (pkCol && row[pkCol] === undefined) {\n tableData.autoIncrementId++;\n row[pkCol] = tableData.autoIncrementId;\n if (rowIdx === 0) {\n insertId = tableData.autoIncrementId;\n }\n } else if (pkCol && row[pkCol]) {\n if (rowIdx === 0) {\n insertId = row[pkCol] as number;\n }\n }\n\n tableData.rows.push({ ...row });\n }\n\n this.flush(tableName);\n\n return { insertId, affectedRows: rowCount };\n }\n\n private handleUpdate(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/UPDATE\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const setMatch = sql.match(/SET\\s+(.+?)\\s+WHERE/i) || sql.match(/SET\\s+(.+)$/i);\n if (!setMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const setClauses = setMatch[1].split(\",\");\n const updates: Record<string, unknown> = {};\n let paramIndex = 0;\n\n for (const clause of setClauses) {\n const eqMatch = clause.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch?.[1]) {\n updates[eqMatch[1]] = params[paramIndex];\n paramIndex++;\n }\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n const whereConditions = whereMatch?.[1] || \"\";\n\n let affectedRows = 0;\n for (const row of tableData.rows) {\n if (this.matchesWhere(row, whereConditions, params, paramIndex)) {\n Object.assign(row, updates);\n affectedRows++;\n }\n }\n\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleDelete(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n if (!whereMatch?.[1]) {\n const affectedRows = tableData.rows.length;\n tableData.rows = [];\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n return { affectedRows };\n }\n\n const whereConditions = whereMatch[1];\n const before = tableData.rows.length;\n\n tableData.rows = tableData.rows.filter(\n (row) => !this.matchesWhere(row, whereConditions, params, 0),\n );\n\n const affectedRows = before - tableData.rows.length;\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleSelect(sql: string, params: unknown[]): any {\n const countMatch = sql.match(/SELECT\\s+COUNT\\s*\\(\\s*\\*\\s*\\)\\s+as\\s+(\\w+)/i);\n if (countMatch) {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [{ count: 0 }];\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n const filter = (row: Record<string, unknown>) =>\n this.matchesWhere(row, whereMatch[1]!, params, 0);\n const count = tableData.rows.filter(filter).length;\n return [{ count }];\n }\n\n return [{ count: tableData.rows.length }];\n }\n\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [];\n }\n\n let rows = [...tableData.rows];\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER\\s+BY|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n rows = rows.filter((row) => this.matchesWhere(row, whereMatch[1]!, params, 0));\n }\n\n const orderMatch = sql.match(/ORDER\\s+BY\\s+(.+?)(?:\\s+LIMIT|\\s*$)/i);\n if (orderMatch?.[1]) {\n const orders = orderMatch[1].split(\",\");\n rows.sort((a, b) => {\n for (const orderClause of orders) {\n const [col, dir] = orderClause.trim().split(/\\s+/);\n const colName = col?.replace(/`/g, \"\") ?? \"\";\n const aVal = (a as any)[colName];\n const bVal = (b as any)[colName];\n if (aVal < bVal) {\n return dir?.toUpperCase() === \"DESC\" ? 1 : -1;\n }\n if (aVal > bVal) {\n return dir?.toUpperCase() === \"DESC\" ? -1 : 1;\n }\n }\n return 0;\n });\n }\n\n const limitMatch = sql.match(/LIMIT\\s+(\\d+)(?:\\s+OFFSET\\s+(\\d+)|\\s*,\\s*(\\d+))?/i);\n if (limitMatch) {\n const limit = Number.parseInt(limitMatch[1]!, 10);\n const offset = limitMatch[2]\n ? Number.parseInt(limitMatch[2], 10)\n : limitMatch[3]\n ? Number.parseInt(limitMatch[3], 10)\n : 0;\n rows = rows.slice(offset, offset + limit);\n }\n\n return rows.map((r) => ({ ...r }));\n }\n\n private matchesWhere(\n row: Record<string, unknown>,\n whereStr: string,\n params: unknown[],\n paramOffset: number,\n ): boolean {\n return this.evaluateWhereExpression(row, whereStr, params, paramOffset).matched;\n }\n\n private evaluateWhereExpression(\n row: Record<string, unknown>,\n expr: string,\n params: unknown[],\n startParamIdx: number,\n ): { matched: boolean; paramIdx: number } {\n let paramIdx = startParamIdx;\n expr = expr.trim();\n\n if (expr.startsWith(\"(\") && expr.endsWith(\")\")) {\n const result = this.evaluateWhereExpression(row, expr.slice(1, -1), params, paramIdx);\n return result;\n }\n\n const orClauses = this.splitByTopLevel(expr, \"OR\");\n if (orClauses.length > 1) {\n for (const orClause of orClauses) {\n const result = this.evaluateWhereExpression(row, orClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (result.matched) {\n return { matched: true, paramIdx };\n }\n }\n return { matched: false, paramIdx };\n }\n\n const andClauses = this.splitByTopLevel(expr, \"AND\");\n if (andClauses.length > 1) {\n for (const andClause of andClauses) {\n const result = this.evaluateWhereExpression(row, andClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (!result.matched) {\n return { matched: false, paramIdx };\n }\n }\n return { matched: true, paramIdx };\n }\n\n return this.evaluateSingleCondition(row, expr, params, paramIdx);\n }\n\n private splitByTopLevel(expr: string, operator: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n const opRegex = new RegExp(`\\\\s+${operator}\\\\s+`, \"i\");\n let i = 0;\n\n while (i < expr.length) {\n const char = expr[i];\n\n if (char === \"(\") {\n parenDepth++;\n current += char;\n i++;\n } else if (char === \")\") {\n parenDepth--;\n current += char;\n i++;\n } else if (parenDepth === 0) {\n const remaining = expr.slice(i);\n const match = remaining.match(opRegex);\n\n if (match && match.index === 0) {\n if (current.trim()) {\n parts.push(current.trim());\n }\n i += match[0]!.length;\n current = \"\";\n } else {\n current += char;\n i++;\n }\n } else {\n current += char;\n i++;\n }\n }\n\n if (current.trim()) {\n parts.push(current.trim());\n }\n\n return parts.length > 0 ? parts : [expr];\n }\n\n private evaluateSingleCondition(\n row: Record<string, unknown>,\n condition: string,\n params: unknown[],\n paramIdx: number,\n ): { matched: boolean; paramIdx: number } {\n condition = condition.trim();\n\n const notInMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+IN\\s+\\(([^)]*)\\)/i);\n if (notInMatch) {\n const col = notInMatch[1]!;\n const placeholders = notInMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = !values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const inMatch = condition.match(/`?(\\w+)`?\\s+IN\\s+\\(([^)]*)\\)/i);\n if (inMatch) {\n const col = inMatch[1]!;\n const placeholders = inMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const eqMatch = condition.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch) {\n const matched = row[eqMatch[1]!] === params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const neqMatch = condition.match(/`?(\\w+)`?\\s*!=\\s*\\?/);\n if (neqMatch) {\n const matched = row[neqMatch[1]!] !== params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gtMatch = condition.match(/`?(\\w+)`?\\s*>\\s*\\?/);\n if (gtMatch) {\n const matched = (row[gtMatch[1]!] as any) > (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gteMatch = condition.match(/`?(\\w+)`?\\s*>=\\s*\\?/);\n if (gteMatch) {\n const matched = (row[gteMatch[1]!] as any) >= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const ltMatch = condition.match(/`?(\\w+)`?\\s*<\\s*\\?/);\n if (ltMatch) {\n const matched = (row[ltMatch[1]!] as any) < (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const lteMatch = condition.match(/`?(\\w+)`?\\s*<=\\s*\\?/);\n if (lteMatch) {\n const matched = (row[lteMatch[1]!] as any) <= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const notLikeMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+LIKE\\s+\\?/i);\n if (notLikeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = !new RegExp(`^${pattern}$`).test(String(row[notLikeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const likeMatch = condition.match(/`?(\\w+)`?\\s+LIKE\\s+\\?/i);\n if (likeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = new RegExp(`^${pattern}$`).test(String(row[likeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n return { matched: true, paramIdx };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file.mjs","names":[],"sources":["../../src/drivers/file.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { DriverError } from \"../errors\";\nimport type { ColumnMetadata, FileConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\n\ninterface FileTableData {\n rows: Record<string, unknown>[];\n autoIncrementId: number;\n meta: {\n columns: ColumnMetadata[];\n };\n}\n\n/**\n * File-based database driver using JSON files for storage\n */\nexport class FileDriver extends BaseDriver {\n readonly dialect = \"file\" as const;\n private config: FileConnectionConfig;\n private data = new Map<string, FileTableData>();\n\n constructor(config: FileConnectionConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Connect to the file database (ensures directory exists and loads data)\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n if (!existsSync(this.config.directory)) {\n mkdirSync(this.config.directory, { recursive: true });\n }\n this.loadAll();\n this.connected = true;\n }\n\n /**\n * Disconnect from the file database (flushes data to disk)\n */\n async disconnect(): Promise<void> {\n this.flushAll();\n this.data.clear();\n this.connected = false;\n }\n\n /**\n * Execute a SQL-like statement (parsed internally for file driver)\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n return this.executeParsed(sql, params);\n }\n\n /**\n * Execute a SQL-like query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n const result = this.executeParsed(sql, params);\n return Array.isArray(result) ? result : [];\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n return this.data.has(name);\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const table = this.data.get(name);\n if (!table) {\n return [];\n }\n return Object.values(table.meta.columns);\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n if (this.data.has(meta.name)) {\n return;\n }\n this.data.set(meta.name, {\n rows: [],\n autoIncrementId: 0,\n meta: { columns: [...meta.columns] },\n });\n this.flush(meta.name);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n this.data.delete(name);\n const filePath = join(this.config.directory, `${name}.json`);\n try {\n const { unlinkSync } = await import(\"fs\");\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n } catch {}\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns.push(column);\n for (const row of tableData.rows) {\n row[column.name] = column.defaultValue ?? null;\n }\n this.flush(table);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns = tableData.meta.columns.filter((c) => c.name !== name);\n for (const row of tableData.rows) {\n delete row[name];\n }\n this.flush(table);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n const col = tableData.meta.columns.find((c) => c.name === oldName);\n if (col) {\n col.name = newName;\n }\n for (const row of tableData.rows) {\n row[newName] = row[oldName];\n delete row[oldName];\n }\n this.flush(table);\n }\n\n /**\n * Execute within a transaction (pseudo-transaction for file driver)\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const snapshot = new Map<string, string>();\n for (const [name, tableData] of this.data) {\n snapshot.set(name, JSON.stringify(tableData));\n }\n try {\n const result = await fn();\n this.flushAll();\n return result;\n } catch (err) {\n for (const [name, json] of snapshot) {\n this.data.set(name, JSON.parse(json));\n }\n throw err;\n }\n }\n\n /**\n * Batch fetch all table columns (already in memory for file driver)\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n const result: Record<string, ColumnMetadata[]> = {};\n for (const [name, tableData] of this.data) {\n result[name] = [...tableData.meta.columns];\n }\n return result;\n }\n\n private loadAll(): void {\n if (!existsSync(this.config.directory)) {\n return;\n }\n const { readdirSync } = require(\"fs\");\n const files = readdirSync(this.config.directory) as string[];\n for (const file of files) {\n if (file.endsWith(\".json\")) {\n const name = file.replace(\".json\", \"\");\n try {\n const content = readFileSync(join(this.config.directory, file), \"utf-8\");\n this.data.set(name, JSON.parse(content));\n } catch {}\n }\n }\n }\n\n private flush(tableName: string): void {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return;\n }\n const filePath = join(this.config.directory, `${tableName}.json`);\n writeFileSync(filePath, JSON.stringify(tableData, null, 2), \"utf-8\");\n }\n\n private flushAll(): void {\n for (const [name] of this.data) {\n this.flush(name);\n }\n }\n\n private executeParsed(sql: string, params: unknown[]): any {\n const trimmed = sql.trim().toUpperCase();\n\n if (trimmed.startsWith(\"CREATE TABLE\")) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"DROP TABLE\")) {\n const match = sql.match(/DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?`?(\\w+)`?/i);\n if (match?.[1]) {\n this.data.delete(match[1]);\n }\n return { insertId: 0, affectedRows: 0 };\n }\n\n if (trimmed.startsWith(\"INSERT\")) {\n return this.handleInsert(sql, params);\n }\n\n if (trimmed.startsWith(\"UPDATE\")) {\n return this.handleUpdate(sql, params);\n }\n if (trimmed.startsWith(\"DELETE\")) {\n return this.handleDelete(sql, params);\n }\n\n if (trimmed.startsWith(\"SELECT\")) {\n return this.handleSelect(sql, params);\n }\n\n return { insertId: 0, affectedRows: 0 };\n }\n\n private handleInsert(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/INTO\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const colMatch = sql.match(/\\(([^)]+)\\)\\s+VALUES/i);\n if (!colMatch?.[1]) {\n return { insertId: 0, affectedRows: 0 };\n }\n\n const cols = colMatch[1]\n .split(\",\")\n .map((c) => c.trim().replace(/`/g, \"\"))\n .filter(Boolean);\n\n const rowCount = Math.floor(params.length / cols.length);\n\n let insertId = 0;\n let pkCol: string | null = null;\n for (const col of tableData.meta.columns) {\n if (col.autoIncrement) {\n pkCol = col.name;\n break;\n }\n }\n\n for (let rowIdx = 0; rowIdx < rowCount; rowIdx++) {\n const row: Record<string, unknown> = {};\n const rowParamStart = rowIdx * cols.length;\n\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i];\n if (col) {\n row[col] = params[rowParamStart + i];\n }\n }\n\n if (pkCol && row[pkCol] === undefined) {\n tableData.autoIncrementId++;\n row[pkCol] = tableData.autoIncrementId;\n if (rowIdx === 0) {\n insertId = tableData.autoIncrementId;\n }\n } else if (pkCol && row[pkCol]) {\n if (rowIdx === 0) {\n insertId = row[pkCol] as number;\n }\n }\n\n tableData.rows.push({ ...row });\n }\n\n this.flush(tableName);\n\n return { insertId, affectedRows: rowCount };\n }\n\n private handleUpdate(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/UPDATE\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const setMatch = sql.match(/SET\\s+(.+?)\\s+WHERE/i) || sql.match(/SET\\s+(.+)$/i);\n if (!setMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const setClauses = setMatch[1].split(\",\");\n const updates: Record<string, unknown> = {};\n let paramIndex = 0;\n\n for (const clause of setClauses) {\n const eqMatch = clause.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch?.[1]) {\n updates[eqMatch[1]] = params[paramIndex];\n paramIndex++;\n }\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n const whereConditions = whereMatch?.[1] || \"\";\n\n let affectedRows = 0;\n for (const row of tableData.rows) {\n if (this.matchesWhere(row, whereConditions, params, paramIndex)) {\n Object.assign(row, updates);\n affectedRows++;\n }\n }\n\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleDelete(sql: string, params: unknown[]): any {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return { affectedRows: 0 };\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return { affectedRows: 0 };\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+)$/i);\n if (!whereMatch?.[1]) {\n const affectedRows = tableData.rows.length;\n tableData.rows = [];\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n return { affectedRows };\n }\n\n const whereConditions = whereMatch[1];\n const before = tableData.rows.length;\n\n tableData.rows = tableData.rows.filter(\n (row) => !this.matchesWhere(row, whereConditions, params, 0),\n );\n\n const affectedRows = before - tableData.rows.length;\n if (affectedRows > 0) {\n this.flush(tableName);\n }\n\n return { affectedRows };\n }\n\n private handleSelect(sql: string, params: unknown[]): any {\n const countMatch = sql.match(/SELECT\\s+COUNT\\s*\\(\\s*\\*\\s*\\)\\s+as\\s+(\\w+)/i);\n if (countMatch) {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [{ count: 0 }];\n }\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n const filter = (row: Record<string, unknown>) =>\n this.matchesWhere(row, whereMatch[1]!, params, 0);\n const count = tableData.rows.filter(filter).length;\n return [{ count }];\n }\n\n return [{ count: tableData.rows.length }];\n }\n\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch?.[1]) {\n return [];\n }\n\n const tableName = tableMatch[1];\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [];\n }\n\n let rows = [...tableData.rows];\n\n const whereMatch = sql.match(/WHERE\\s+(.+?)(?:\\s+ORDER\\s+BY|\\s+LIMIT|\\s*$)/i);\n if (whereMatch?.[1]) {\n rows = rows.filter((row) => this.matchesWhere(row, whereMatch[1]!, params, 0));\n }\n\n const orderMatch = sql.match(/ORDER\\s+BY\\s+(.+?)(?:\\s+LIMIT|\\s*$)/i);\n if (orderMatch?.[1]) {\n const orders = orderMatch[1].split(\",\");\n rows.sort((a, b) => {\n for (const orderClause of orders) {\n const [col, dir] = orderClause.trim().split(/\\s+/);\n const colName = col?.replace(/`/g, \"\") ?? \"\";\n const aVal = (a as any)[colName];\n const bVal = (b as any)[colName];\n if (aVal < bVal) {\n return dir?.toUpperCase() === \"DESC\" ? 1 : -1;\n }\n if (aVal > bVal) {\n return dir?.toUpperCase() === \"DESC\" ? -1 : 1;\n }\n }\n return 0;\n });\n }\n\n const limitMatch = sql.match(/LIMIT\\s+(\\d+)(?:\\s+OFFSET\\s+(\\d+)|\\s*,\\s*(\\d+))?/i);\n if (limitMatch) {\n const limit = Number.parseInt(limitMatch[1]!, 10);\n const offset = limitMatch[2]\n ? Number.parseInt(limitMatch[2], 10)\n : limitMatch[3]\n ? Number.parseInt(limitMatch[3], 10)\n : 0;\n rows = rows.slice(offset, offset + limit);\n }\n\n return rows.map((r) => ({ ...r }));\n }\n\n private matchesWhere(\n row: Record<string, unknown>,\n whereStr: string,\n params: unknown[],\n paramOffset: number,\n ): boolean {\n return this.evaluateWhereExpression(row, whereStr, params, paramOffset).matched;\n }\n\n private evaluateWhereExpression(\n row: Record<string, unknown>,\n expr: string,\n params: unknown[],\n startParamIdx: number,\n ): { matched: boolean; paramIdx: number } {\n let paramIdx = startParamIdx;\n expr = expr.trim();\n\n if (expr.startsWith(\"(\") && expr.endsWith(\")\")) {\n const result = this.evaluateWhereExpression(row, expr.slice(1, -1), params, paramIdx);\n return result;\n }\n\n const orClauses = this.splitByTopLevel(expr, \"OR\");\n if (orClauses.length > 1) {\n for (const orClause of orClauses) {\n const result = this.evaluateWhereExpression(row, orClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (result.matched) {\n return { matched: true, paramIdx };\n }\n }\n return { matched: false, paramIdx };\n }\n\n const andClauses = this.splitByTopLevel(expr, \"AND\");\n if (andClauses.length > 1) {\n for (const andClause of andClauses) {\n const result = this.evaluateWhereExpression(row, andClause.trim(), params, paramIdx);\n paramIdx = result.paramIdx;\n if (!result.matched) {\n return { matched: false, paramIdx };\n }\n }\n return { matched: true, paramIdx };\n }\n\n return this.evaluateSingleCondition(row, expr, params, paramIdx);\n }\n\n private splitByTopLevel(expr: string, operator: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n const opRegex = new RegExp(`\\\\s+${operator}\\\\s+`, \"i\");\n let i = 0;\n\n while (i < expr.length) {\n const char = expr[i];\n\n if (char === \"(\") {\n parenDepth++;\n current += char;\n i++;\n } else if (char === \")\") {\n parenDepth--;\n current += char;\n i++;\n } else if (parenDepth === 0) {\n const remaining = expr.slice(i);\n const match = remaining.match(opRegex);\n\n if (match && match.index === 0) {\n if (current.trim()) {\n parts.push(current.trim());\n }\n i += match[0]!.length;\n current = \"\";\n } else {\n current += char;\n i++;\n }\n } else {\n current += char;\n i++;\n }\n }\n\n if (current.trim()) {\n parts.push(current.trim());\n }\n\n return parts.length > 0 ? parts : [expr];\n }\n\n private evaluateSingleCondition(\n row: Record<string, unknown>,\n condition: string,\n params: unknown[],\n paramIdx: number,\n ): { matched: boolean; paramIdx: number } {\n condition = condition.trim();\n\n const notInMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+IN\\s+\\(([^)]*)\\)/i);\n if (notInMatch) {\n const col = notInMatch[1]!;\n const placeholders = notInMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = !values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const inMatch = condition.match(/`?(\\w+)`?\\s+IN\\s+\\(([^)]*)\\)/i);\n if (inMatch) {\n const col = inMatch[1]!;\n const placeholders = inMatch[2]!.split(\",\").map((p) => p.trim());\n const values: unknown[] = [];\n for (const placeholder of placeholders) {\n if (placeholder === \"?\") {\n values.push(params[paramIdx]);\n paramIdx++;\n }\n }\n const matched = values.includes(row[col]);\n return { matched, paramIdx };\n }\n\n const eqMatch = condition.match(/`?(\\w+)`?\\s*=\\s*\\?/);\n if (eqMatch) {\n const matched = row[eqMatch[1]!] === params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const neqMatch = condition.match(/`?(\\w+)`?\\s*!=\\s*\\?/);\n if (neqMatch) {\n const matched = row[neqMatch[1]!] !== params[paramIdx];\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gtMatch = condition.match(/`?(\\w+)`?\\s*>\\s*\\?/);\n if (gtMatch) {\n const matched = (row[gtMatch[1]!] as any) > (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const gteMatch = condition.match(/`?(\\w+)`?\\s*>=\\s*\\?/);\n if (gteMatch) {\n const matched = (row[gteMatch[1]!] as any) >= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const ltMatch = condition.match(/`?(\\w+)`?\\s*<\\s*\\?/);\n if (ltMatch) {\n const matched = (row[ltMatch[1]!] as any) < (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const lteMatch = condition.match(/`?(\\w+)`?\\s*<=\\s*\\?/);\n if (lteMatch) {\n const matched = (row[lteMatch[1]!] as any) <= (params[paramIdx] as any);\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const notLikeMatch = condition.match(/`?(\\w+)`?\\s+NOT\\s+LIKE\\s+\\?/i);\n if (notLikeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = !new RegExp(`^${pattern}$`).test(String(row[notLikeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n const likeMatch = condition.match(/`?(\\w+)`?\\s+LIKE\\s+\\?/i);\n if (likeMatch) {\n const pattern = (params[paramIdx] as string).replace(/%/g, \".*\");\n const matched = new RegExp(`^${pattern}$`).test(String(row[likeMatch[1]!]));\n return { matched, paramIdx: paramIdx + 1 };\n }\n\n return { matched: true, paramIdx };\n }\n}\n"],"mappings":"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"}
|
package/dist/drivers/mysql.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.cjs","names":["BaseDriver","DriverError","compileCreateTable","compileColumnDef"],"sources":["../../src/drivers/mysql.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ColumnMetadata, MySQLConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\nimport { compileColumnDef, compileCreateTable } from \"./sql-compiler\";\n\ninterface MySQLPool {\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n getConnection(): Promise<MySQLConnection>;\n end(): Promise<void>;\n}\n\ninterface MySQLConnection {\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n}\n\n/**\n * MySQL database driver supporting mysql2 and mysql\n */\nexport class MySQLDriver extends BaseDriver {\n private pool: MySQLPool | null = null;\n private config: MySQLConnectionConfig;\n private provider?: \"mysql\" | \"mysql2\";\n\n constructor(config: MySQLConnectionConfig, provider?: \"mysql\" | \"mysql2\") {\n super();\n this.config = config;\n this.provider = provider;\n }\n\n /**\n * Connect to the MySQL/MariaDB database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const provider = this.provider;\n\n try {\n if (!provider || provider === \"mysql2\") {\n try {\n const mysql2 = await import(\"mysql2/promise\");\n this.pool = mysql2.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n waitForConnections: true,\n connectionLimit: 10,\n enableKeepAlive: true,\n keepAliveInitialDelay: 10000,\n decimalNumbers: true,\n });\n this.connected = true;\n return;\n } catch (err) {\n if (provider === \"mysql2\") {\n throw err;\n }\n }\n }\n\n if (!provider || provider === \"mysql\") {\n try {\n const mysql = await import(\"mysql\");\n const pool = mysql.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n connectionLimit: 10,\n waitForConnections: true,\n acquireTimeout: 10000,\n });\n\n this.pool = {\n execute: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n query: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n getConnection: () =>\n new Promise((resolve, reject) => {\n pool.getConnection((err, conn) => {\n if (err) {\n return reject(err);\n }\n const wrappedConn: MySQLConnection = {\n beginTransaction: () =>\n new Promise<void>((res, rej) =>\n conn.beginTransaction((e) => (e ? rej(e) : res())),\n ),\n commit: () =>\n new Promise<void>((res, rej) => conn.commit((e) => (e ? rej(e) : res()))),\n rollback: () =>\n new Promise<void>((res, rej) => conn.rollback((e) => (e ? rej(e) : res()))),\n release: () => conn.release(),\n query: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n execute: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n };\n resolve(wrappedConn);\n });\n }),\n end: () => new Promise<void>((res, rej) => pool.end((e) => (e ? rej(e) : res()))),\n };\n this.connected = true;\n } catch (err) {\n if (provider === \"mysql\") {\n throw err;\n }\n throw new Error(\"No MySQL driver found. Please install mysql2 or mysql.\");\n }\n }\n } catch (err: any) {\n throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n this.connected = false;\n }\n }\n\n private getPool(): MySQLPool {\n if (!this.pool) {\n throw new DriverError(\"Database not connected\");\n }\n return this.pool;\n }\n\n /**\n * Execute a SQL statement\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n try {\n const [result] = await this.getPool().query(sql, this.formatParams(params));\n return {\n insertId: result.insertId,\n affectedRows: result.affectedRows,\n };\n } catch (err: any) {\n throw new DriverError(`MySQL execute error: ${err.message}`);\n }\n }\n\n /**\n * Execute a SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n try {\n const [rows] = await this.getPool().query(sql, this.formatParams(params));\n return rows as any[];\n } catch (err: any) {\n throw new DriverError(`MySQL query error: ${err.message}`);\n }\n }\n\n private formatParams(params: unknown[]): unknown[] {\n return params.map((p) => {\n if (p instanceof Date) {\n return p.toISOString().slice(0, 19).replace(\"T\", \" \");\n }\n return p;\n });\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n const rows = await this.query(\n \"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\",\n [this.config.database, name],\n );\n return rows.length > 0;\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const rows = await this.query(\n \"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION\",\n [this.config.database, name],\n );\n return rows.map((row: any) => ({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n }));\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n const sql = compileCreateTable(meta, \"mysql\");\n await this.execute(sql);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n await this.execute(`DROP TABLE IF EXISTS \\`${name}\\``);\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const colDef = compileColumnDef(column, \"mysql\");\n await this.execute(`ALTER TABLE \\`${table}\\` ADD COLUMN ${colDef}`);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` DROP COLUMN \\`${name}\\``);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` RENAME COLUMN \\`${oldName}\\` TO \\`${newName}\\``);\n }\n\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const conn = await this.getPool().getConnection();\n try {\n await conn.beginTransaction();\n const result = await fn();\n await conn.commit();\n return result;\n } catch (err) {\n await conn.rollback();\n throw err;\n } finally {\n conn.release();\n }\n }\n\n /**\n * Fetch all column metadata for all tables in the database in a single query\n * @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n try {\n const rows = await this.query(\n \"SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION\",\n [this.config.database],\n );\n\n const result: Record<string, ColumnMetadata[]> = {};\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as any;\n if (!row?.TABLE_NAME) {\n continue;\n }\n const tableName = row.TABLE_NAME;\n if (!result[tableName]) {\n result[tableName] = [];\n }\n result[tableName].push({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n });\n }\n return result;\n } catch (err: any) {\n throw new DriverError(`Failed to fetch all table columns: ${err.message}`);\n }\n }\n\n private mapMySQLType(type: string): ColumnMetadata[\"type\"] {\n const lower = type.toLowerCase();\n if (\n lower === \"int\" ||\n lower === \"integer\" ||\n lower === \"tinyint\" ||\n lower === \"smallint\" ||\n lower === \"mediumint\"\n ) {\n return \"integer\";\n }\n if (lower === \"bigint\") {\n return \"bigint\";\n }\n if (lower === \"varchar\") {\n return \"varchar\";\n }\n if (lower === \"char\") {\n return \"char\";\n }\n if (lower === \"text\" || lower === \"mediumtext\" || lower === \"longtext\") {\n return \"text\";\n }\n if (lower === \"json\") {\n return \"json\";\n }\n if (lower === \"datetime\") {\n return \"datetime\";\n }\n if (lower === \"timestamp\") {\n return \"timestamp\";\n }\n if (lower === \"decimal\" || lower === \"numeric\") {\n return \"decimal\";\n }\n if (lower === \"float\" || lower === \"double\" || lower === \"real\") {\n return \"float\";\n }\n if (lower === \"blob\" || lower === \"mediumblob\" || lower === \"longblob\") {\n return \"blob\";\n }\n return \"text\";\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mysql.cjs","names":["BaseDriver","DriverError","compileCreateTable","compileColumnDef"],"sources":["../../src/drivers/mysql.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ColumnMetadata, MySQLConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\nimport { compileColumnDef, compileCreateTable } from \"./sql-compiler\";\n\ninterface MySQLPool {\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n getConnection(): Promise<MySQLConnection>;\n end(): Promise<void>;\n}\n\ninterface MySQLConnection {\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n}\n\n/**\n * MySQL database driver supporting mysql2 and mysql\n */\nexport class MySQLDriver extends BaseDriver {\n readonly dialect = \"mysql\" as const;\n private pool: MySQLPool | null = null;\n private config: MySQLConnectionConfig;\n private provider?: \"mysql\" | \"mysql2\";\n\n constructor(config: MySQLConnectionConfig, provider?: \"mysql\" | \"mysql2\") {\n super();\n this.config = config;\n this.provider = provider;\n }\n\n /**\n * Connect to the MySQL/MariaDB database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const provider = this.provider;\n\n try {\n if (!provider || provider === \"mysql2\") {\n try {\n const mysql2 = await import(\"mysql2/promise\");\n this.pool = mysql2.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n waitForConnections: true,\n connectionLimit: 10,\n enableKeepAlive: true,\n keepAliveInitialDelay: 10000,\n decimalNumbers: true,\n });\n this.connected = true;\n return;\n } catch (err) {\n if (provider === \"mysql2\") {\n throw err;\n }\n }\n }\n\n if (!provider || provider === \"mysql\") {\n try {\n const mysql = await import(\"mysql\");\n const pool = mysql.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n connectionLimit: 10,\n waitForConnections: true,\n acquireTimeout: 10000,\n });\n\n this.pool = {\n execute: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n query: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n getConnection: () =>\n new Promise((resolve, reject) => {\n pool.getConnection((err, conn) => {\n if (err) {\n return reject(err);\n }\n const wrappedConn: MySQLConnection = {\n beginTransaction: () =>\n new Promise<void>((res, rej) =>\n conn.beginTransaction((e) => (e ? rej(e) : res())),\n ),\n commit: () =>\n new Promise<void>((res, rej) => conn.commit((e) => (e ? rej(e) : res()))),\n rollback: () =>\n new Promise<void>((res, rej) => conn.rollback((e) => (e ? rej(e) : res()))),\n release: () => conn.release(),\n query: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n execute: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n };\n resolve(wrappedConn);\n });\n }),\n end: () => new Promise<void>((res, rej) => pool.end((e) => (e ? rej(e) : res()))),\n };\n this.connected = true;\n } catch (err) {\n if (provider === \"mysql\") {\n throw err;\n }\n throw new Error(\"No MySQL driver found. Please install mysql2 or mysql.\");\n }\n }\n } catch (err: any) {\n throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n this.connected = false;\n }\n }\n\n private getPool(): MySQLPool {\n if (!this.pool) {\n throw new DriverError(\"Database not connected\");\n }\n return this.pool;\n }\n\n /**\n * Execute a SQL statement\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n try {\n const [result] = await this.getPool().query(sql, this.formatParams(params));\n return {\n insertId: result.insertId,\n affectedRows: result.affectedRows,\n };\n } catch (err: any) {\n throw new DriverError(`MySQL execute error: ${err.message}`);\n }\n }\n\n /**\n * Execute a SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n try {\n const [rows] = await this.getPool().query(sql, this.formatParams(params));\n return rows as any[];\n } catch (err: any) {\n throw new DriverError(`MySQL query error: ${err.message}`);\n }\n }\n\n private formatParams(params: unknown[]): unknown[] {\n return params.map((p) => {\n if (p instanceof Date) {\n return p.toISOString().slice(0, 19).replace(\"T\", \" \");\n }\n return p;\n });\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n const rows = await this.query(\n \"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\",\n [this.config.database, name],\n );\n return rows.length > 0;\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const rows = await this.query(\n \"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION\",\n [this.config.database, name],\n );\n return rows.map((row: any) => ({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n }));\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n const sql = compileCreateTable(meta, \"mysql\");\n await this.execute(sql);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n await this.execute(`DROP TABLE IF EXISTS \\`${name}\\``);\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const colDef = compileColumnDef(column, \"mysql\");\n await this.execute(`ALTER TABLE \\`${table}\\` ADD COLUMN ${colDef}`);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` DROP COLUMN \\`${name}\\``);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` RENAME COLUMN \\`${oldName}\\` TO \\`${newName}\\``);\n }\n\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const conn = await this.getPool().getConnection();\n try {\n await conn.beginTransaction();\n const result = await fn();\n await conn.commit();\n return result;\n } catch (err) {\n await conn.rollback();\n throw err;\n } finally {\n conn.release();\n }\n }\n\n /**\n * Fetch all column metadata for all tables in the database in a single query\n * @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n try {\n const rows = await this.query(\n \"SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION\",\n [this.config.database],\n );\n\n const result: Record<string, ColumnMetadata[]> = {};\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as any;\n if (!row?.TABLE_NAME) {\n continue;\n }\n const tableName = row.TABLE_NAME;\n if (!result[tableName]) {\n result[tableName] = [];\n }\n result[tableName].push({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n });\n }\n return result;\n } catch (err: any) {\n throw new DriverError(`Failed to fetch all table columns: ${err.message}`);\n }\n }\n\n private mapMySQLType(type: string): ColumnMetadata[\"type\"] {\n const lower = type.toLowerCase();\n if (\n lower === \"int\" ||\n lower === \"integer\" ||\n lower === \"tinyint\" ||\n lower === \"smallint\" ||\n lower === \"mediumint\"\n ) {\n return \"integer\";\n }\n if (lower === \"bigint\") {\n return \"bigint\";\n }\n if (lower === \"varchar\") {\n return \"varchar\";\n }\n if (lower === \"char\") {\n return \"char\";\n }\n if (lower === \"text\" || lower === \"mediumtext\" || lower === \"longtext\") {\n return \"text\";\n }\n if (lower === \"json\") {\n return \"json\";\n }\n if (lower === \"datetime\") {\n return \"datetime\";\n }\n if (lower === \"timestamp\") {\n return \"timestamp\";\n }\n if (lower === \"decimal\" || lower === \"numeric\") {\n return \"decimal\";\n }\n if (lower === \"float\" || lower === \"double\" || lower === \"real\") {\n return \"float\";\n }\n if (lower === \"blob\" || lower === \"mediumblob\" || lower === \"longblob\") {\n return \"blob\";\n }\n return \"text\";\n }\n}\n"],"mappings":"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"}
|
package/dist/drivers/mysql.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql.mjs","names":[],"sources":["../../src/drivers/mysql.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ColumnMetadata, MySQLConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\nimport { compileColumnDef, compileCreateTable } from \"./sql-compiler\";\n\ninterface MySQLPool {\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n getConnection(): Promise<MySQLConnection>;\n end(): Promise<void>;\n}\n\ninterface MySQLConnection {\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n}\n\n/**\n * MySQL database driver supporting mysql2 and mysql\n */\nexport class MySQLDriver extends BaseDriver {\n private pool: MySQLPool | null = null;\n private config: MySQLConnectionConfig;\n private provider?: \"mysql\" | \"mysql2\";\n\n constructor(config: MySQLConnectionConfig, provider?: \"mysql\" | \"mysql2\") {\n super();\n this.config = config;\n this.provider = provider;\n }\n\n /**\n * Connect to the MySQL/MariaDB database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const provider = this.provider;\n\n try {\n if (!provider || provider === \"mysql2\") {\n try {\n const mysql2 = await import(\"mysql2/promise\");\n this.pool = mysql2.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n waitForConnections: true,\n connectionLimit: 10,\n enableKeepAlive: true,\n keepAliveInitialDelay: 10000,\n decimalNumbers: true,\n });\n this.connected = true;\n return;\n } catch (err) {\n if (provider === \"mysql2\") {\n throw err;\n }\n }\n }\n\n if (!provider || provider === \"mysql\") {\n try {\n const mysql = await import(\"mysql\");\n const pool = mysql.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n connectionLimit: 10,\n waitForConnections: true,\n acquireTimeout: 10000,\n });\n\n this.pool = {\n execute: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n query: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n getConnection: () =>\n new Promise((resolve, reject) => {\n pool.getConnection((err, conn) => {\n if (err) {\n return reject(err);\n }\n const wrappedConn: MySQLConnection = {\n beginTransaction: () =>\n new Promise<void>((res, rej) =>\n conn.beginTransaction((e) => (e ? rej(e) : res())),\n ),\n commit: () =>\n new Promise<void>((res, rej) => conn.commit((e) => (e ? rej(e) : res()))),\n rollback: () =>\n new Promise<void>((res, rej) => conn.rollback((e) => (e ? rej(e) : res()))),\n release: () => conn.release(),\n query: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n execute: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n };\n resolve(wrappedConn);\n });\n }),\n end: () => new Promise<void>((res, rej) => pool.end((e) => (e ? rej(e) : res()))),\n };\n this.connected = true;\n } catch (err) {\n if (provider === \"mysql\") {\n throw err;\n }\n throw new Error(\"No MySQL driver found. Please install mysql2 or mysql.\");\n }\n }\n } catch (err: any) {\n throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n this.connected = false;\n }\n }\n\n private getPool(): MySQLPool {\n if (!this.pool) {\n throw new DriverError(\"Database not connected\");\n }\n return this.pool;\n }\n\n /**\n * Execute a SQL statement\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n try {\n const [result] = await this.getPool().query(sql, this.formatParams(params));\n return {\n insertId: result.insertId,\n affectedRows: result.affectedRows,\n };\n } catch (err: any) {\n throw new DriverError(`MySQL execute error: ${err.message}`);\n }\n }\n\n /**\n * Execute a SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n try {\n const [rows] = await this.getPool().query(sql, this.formatParams(params));\n return rows as any[];\n } catch (err: any) {\n throw new DriverError(`MySQL query error: ${err.message}`);\n }\n }\n\n private formatParams(params: unknown[]): unknown[] {\n return params.map((p) => {\n if (p instanceof Date) {\n return p.toISOString().slice(0, 19).replace(\"T\", \" \");\n }\n return p;\n });\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n const rows = await this.query(\n \"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\",\n [this.config.database, name],\n );\n return rows.length > 0;\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const rows = await this.query(\n \"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION\",\n [this.config.database, name],\n );\n return rows.map((row: any) => ({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n }));\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n const sql = compileCreateTable(meta, \"mysql\");\n await this.execute(sql);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n await this.execute(`DROP TABLE IF EXISTS \\`${name}\\``);\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const colDef = compileColumnDef(column, \"mysql\");\n await this.execute(`ALTER TABLE \\`${table}\\` ADD COLUMN ${colDef}`);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` DROP COLUMN \\`${name}\\``);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` RENAME COLUMN \\`${oldName}\\` TO \\`${newName}\\``);\n }\n\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const conn = await this.getPool().getConnection();\n try {\n await conn.beginTransaction();\n const result = await fn();\n await conn.commit();\n return result;\n } catch (err) {\n await conn.rollback();\n throw err;\n } finally {\n conn.release();\n }\n }\n\n /**\n * Fetch all column metadata for all tables in the database in a single query\n * @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n try {\n const rows = await this.query(\n \"SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION\",\n [this.config.database],\n );\n\n const result: Record<string, ColumnMetadata[]> = {};\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as any;\n if (!row?.TABLE_NAME) {\n continue;\n }\n const tableName = row.TABLE_NAME;\n if (!result[tableName]) {\n result[tableName] = [];\n }\n result[tableName].push({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n });\n }\n return result;\n } catch (err: any) {\n throw new DriverError(`Failed to fetch all table columns: ${err.message}`);\n }\n }\n\n private mapMySQLType(type: string): ColumnMetadata[\"type\"] {\n const lower = type.toLowerCase();\n if (\n lower === \"int\" ||\n lower === \"integer\" ||\n lower === \"tinyint\" ||\n lower === \"smallint\" ||\n lower === \"mediumint\"\n ) {\n return \"integer\";\n }\n if (lower === \"bigint\") {\n return \"bigint\";\n }\n if (lower === \"varchar\") {\n return \"varchar\";\n }\n if (lower === \"char\") {\n return \"char\";\n }\n if (lower === \"text\" || lower === \"mediumtext\" || lower === \"longtext\") {\n return \"text\";\n }\n if (lower === \"json\") {\n return \"json\";\n }\n if (lower === \"datetime\") {\n return \"datetime\";\n }\n if (lower === \"timestamp\") {\n return \"timestamp\";\n }\n if (lower === \"decimal\" || lower === \"numeric\") {\n return \"decimal\";\n }\n if (lower === \"float\" || lower === \"double\" || lower === \"real\") {\n return \"float\";\n }\n if (lower === \"blob\" || lower === \"mediumblob\" || lower === \"longblob\") {\n return \"blob\";\n }\n return \"text\";\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mysql.mjs","names":[],"sources":["../../src/drivers/mysql.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ColumnMetadata, MySQLConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\nimport { compileColumnDef, compileCreateTable } from \"./sql-compiler\";\n\ninterface MySQLPool {\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n getConnection(): Promise<MySQLConnection>;\n end(): Promise<void>;\n}\n\ninterface MySQLConnection {\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n}\n\n/**\n * MySQL database driver supporting mysql2 and mysql\n */\nexport class MySQLDriver extends BaseDriver {\n readonly dialect = \"mysql\" as const;\n private pool: MySQLPool | null = null;\n private config: MySQLConnectionConfig;\n private provider?: \"mysql\" | \"mysql2\";\n\n constructor(config: MySQLConnectionConfig, provider?: \"mysql\" | \"mysql2\") {\n super();\n this.config = config;\n this.provider = provider;\n }\n\n /**\n * Connect to the MySQL/MariaDB database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const provider = this.provider;\n\n try {\n if (!provider || provider === \"mysql2\") {\n try {\n const mysql2 = await import(\"mysql2/promise\");\n this.pool = mysql2.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n waitForConnections: true,\n connectionLimit: 10,\n enableKeepAlive: true,\n keepAliveInitialDelay: 10000,\n decimalNumbers: true,\n });\n this.connected = true;\n return;\n } catch (err) {\n if (provider === \"mysql2\") {\n throw err;\n }\n }\n }\n\n if (!provider || provider === \"mysql\") {\n try {\n const mysql = await import(\"mysql\");\n const pool = mysql.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n connectionLimit: 10,\n waitForConnections: true,\n acquireTimeout: 10000,\n });\n\n this.pool = {\n execute: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n query: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n getConnection: () =>\n new Promise((resolve, reject) => {\n pool.getConnection((err, conn) => {\n if (err) {\n return reject(err);\n }\n const wrappedConn: MySQLConnection = {\n beginTransaction: () =>\n new Promise<void>((res, rej) =>\n conn.beginTransaction((e) => (e ? rej(e) : res())),\n ),\n commit: () =>\n new Promise<void>((res, rej) => conn.commit((e) => (e ? rej(e) : res()))),\n rollback: () =>\n new Promise<void>((res, rej) => conn.rollback((e) => (e ? rej(e) : res()))),\n release: () => conn.release(),\n query: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n execute: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n };\n resolve(wrappedConn);\n });\n }),\n end: () => new Promise<void>((res, rej) => pool.end((e) => (e ? rej(e) : res()))),\n };\n this.connected = true;\n } catch (err) {\n if (provider === \"mysql\") {\n throw err;\n }\n throw new Error(\"No MySQL driver found. Please install mysql2 or mysql.\");\n }\n }\n } catch (err: any) {\n throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n this.connected = false;\n }\n }\n\n private getPool(): MySQLPool {\n if (!this.pool) {\n throw new DriverError(\"Database not connected\");\n }\n return this.pool;\n }\n\n /**\n * Execute a SQL statement\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n try {\n const [result] = await this.getPool().query(sql, this.formatParams(params));\n return {\n insertId: result.insertId,\n affectedRows: result.affectedRows,\n };\n } catch (err: any) {\n throw new DriverError(`MySQL execute error: ${err.message}`);\n }\n }\n\n /**\n * Execute a SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n try {\n const [rows] = await this.getPool().query(sql, this.formatParams(params));\n return rows as any[];\n } catch (err: any) {\n throw new DriverError(`MySQL query error: ${err.message}`);\n }\n }\n\n private formatParams(params: unknown[]): unknown[] {\n return params.map((p) => {\n if (p instanceof Date) {\n return p.toISOString().slice(0, 19).replace(\"T\", \" \");\n }\n return p;\n });\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n const rows = await this.query(\n \"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\",\n [this.config.database, name],\n );\n return rows.length > 0;\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const rows = await this.query(\n \"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION\",\n [this.config.database, name],\n );\n return rows.map((row: any) => ({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n }));\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n const sql = compileCreateTable(meta, \"mysql\");\n await this.execute(sql);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n await this.execute(`DROP TABLE IF EXISTS \\`${name}\\``);\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const colDef = compileColumnDef(column, \"mysql\");\n await this.execute(`ALTER TABLE \\`${table}\\` ADD COLUMN ${colDef}`);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` DROP COLUMN \\`${name}\\``);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` RENAME COLUMN \\`${oldName}\\` TO \\`${newName}\\``);\n }\n\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const conn = await this.getPool().getConnection();\n try {\n await conn.beginTransaction();\n const result = await fn();\n await conn.commit();\n return result;\n } catch (err) {\n await conn.rollback();\n throw err;\n } finally {\n conn.release();\n }\n }\n\n /**\n * Fetch all column metadata for all tables in the database in a single query\n * @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n try {\n const rows = await this.query(\n \"SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION\",\n [this.config.database],\n );\n\n const result: Record<string, ColumnMetadata[]> = {};\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as any;\n if (!row?.TABLE_NAME) {\n continue;\n }\n const tableName = row.TABLE_NAME;\n if (!result[tableName]) {\n result[tableName] = [];\n }\n result[tableName].push({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n });\n }\n return result;\n } catch (err: any) {\n throw new DriverError(`Failed to fetch all table columns: ${err.message}`);\n }\n }\n\n private mapMySQLType(type: string): ColumnMetadata[\"type\"] {\n const lower = type.toLowerCase();\n if (\n lower === \"int\" ||\n lower === \"integer\" ||\n lower === \"tinyint\" ||\n lower === \"smallint\" ||\n lower === \"mediumint\"\n ) {\n return \"integer\";\n }\n if (lower === \"bigint\") {\n return \"bigint\";\n }\n if (lower === \"varchar\") {\n return \"varchar\";\n }\n if (lower === \"char\") {\n return \"char\";\n }\n if (lower === \"text\" || lower === \"mediumtext\" || lower === \"longtext\") {\n return \"text\";\n }\n if (lower === \"json\") {\n return \"json\";\n }\n if (lower === \"datetime\") {\n return \"datetime\";\n }\n if (lower === \"timestamp\") {\n return \"timestamp\";\n }\n if (lower === \"decimal\" || lower === \"numeric\") {\n return \"decimal\";\n }\n if (lower === \"float\" || lower === \"double\" || lower === \"real\") {\n return \"float\";\n }\n if (lower === \"blob\" || lower === \"mediumblob\" || lower === \"longblob\") {\n return \"blob\";\n }\n return \"text\";\n }\n}\n"],"mappings":"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"}
|
package/dist/drivers/s3.cjs
CHANGED