11/**
22 * SQLite Connector Implementation
33 *
4- * Implements SQLite database connectivity for DBHub
4+ * Implements SQLite database connectivity for DBHub using better-sqlite3
55 * To use this connector:
66 * 1. Set DSN=sqlite:///path/to/database.db in your .env file
77 * 2. Or set DB_CONNECTOR_TYPE=sqlite for default in-memory database
88 */
99
1010import { Connector , ConnectorRegistry , DSNParser , QueryResult , TableColumn } from '../interface.js' ;
11- import sqlite3 from 'sqlite3' ;
11+ import Database from 'better- sqlite3' ;
1212
1313/**
1414 * SQLite DSN Parser
@@ -81,54 +81,36 @@ export class SQLiteConnector implements Connector {
8181 name = 'SQLite' ;
8282 dsnParser = new SQLiteDSNParser ( ) ;
8383
84- private db : sqlite3 . Database | null = null ;
84+ private db : Database . Database | null = null ;
8585 private dbPath : string = ':memory:' ; // Default to in-memory database
8686
8787 async connect ( dsn : string , initScript ?: string ) : Promise < void > {
8888 const config = this . dsnParser . parse ( dsn ) ;
8989 this . dbPath = config . dbPath ;
9090
91- return new Promise ( ( resolve , reject ) => {
92- this . db = new sqlite3 . Database ( this . dbPath , ( err ) => {
93- if ( err ) {
94- console . error ( "Failed to connect to SQLite database:" , err ) ;
95- reject ( err ) ;
96- } else {
97- // Can't use console.log here because it will break the stdio transport
98- console . error ( "Successfully connected to SQLite database" ) ;
99-
100- // If an initialization script is provided, run it
101- if ( initScript ) {
102- this . db ! . exec ( initScript , ( err ) => {
103- if ( err ) {
104- console . error ( "Failed to initialize database with script:" , err ) ;
105- reject ( err ) ;
106- } else {
107- console . error ( "Successfully initialized database with script" ) ;
108- resolve ( ) ;
109- }
110- } ) ;
111- } else {
112- resolve ( ) ;
113- }
114- }
115- } ) ;
116- } ) ;
91+ try {
92+ this . db = new Database ( this . dbPath ) ;
93+ console . error ( "Successfully connected to SQLite database" ) ;
94+
95+ // If an initialization script is provided, run it
96+ if ( initScript ) {
97+ this . db . exec ( initScript ) ;
98+ console . error ( "Successfully initialized database with script" ) ;
99+ }
100+ } catch ( error ) {
101+ console . error ( "Failed to connect to SQLite database:" , error ) ;
102+ throw error ;
103+ }
117104 }
118105
119106 async disconnect ( ) : Promise < void > {
120- // Close the SQLite connection
121107 if ( this . db ) {
122- return new Promise ( ( resolve , reject ) => {
123- this . db ! . close ( ( err ) => {
124- if ( err ) {
125- reject ( err ) ;
126- } else {
127- this . db = null ;
128- resolve ( ) ;
129- }
130- } ) ;
131- } ) ;
108+ try {
109+ this . db . close ( ) ;
110+ this . db = null ;
111+ } catch ( error ) {
112+ throw error ;
113+ }
132114 }
133115 return Promise . resolve ( ) ;
134116 }
@@ -138,67 +120,56 @@ export class SQLiteConnector implements Connector {
138120 throw new Error ( "Not connected to SQLite database" ) ;
139121 }
140122
141- return new Promise ( ( resolve , reject ) => {
142- this . db ! . all < SQLiteTableNameRow > (
143- `SELECT name FROM sqlite_master
144- WHERE type='table' AND name NOT LIKE 'sqlite_%'
145- ORDER BY name` ,
146- ( err , rows ) => {
147- if ( err ) {
148- reject ( err ) ;
149- } else {
150- resolve ( rows . map ( row => row . name ) ) ;
151- }
152- }
153- ) ;
154- } ) ;
123+ try {
124+ const rows = this . db . prepare ( `
125+ SELECT name FROM sqlite_master
126+ WHERE type='table' AND name NOT LIKE 'sqlite_%'
127+ ORDER BY name
128+ ` ) . all ( ) as SQLiteTableNameRow [ ] ;
129+
130+ return rows . map ( row => row . name ) ;
131+ } catch ( error ) {
132+ throw error ;
133+ }
155134 }
156135
157136 async tableExists ( tableName : string ) : Promise < boolean > {
158137 if ( ! this . db ) {
159138 throw new Error ( "Not connected to SQLite database" ) ;
160139 }
161140
162- return new Promise ( ( resolve , reject ) => {
163- this . db ! . get < SQLiteTableNameRow > (
164- `SELECT name FROM sqlite_master
165- WHERE type='table' AND name = ?` ,
166- [ tableName ] ,
167- ( err , row ) => {
168- if ( err ) {
169- reject ( err ) ;
170- } else {
171- resolve ( ! ! row ) ;
172- }
173- }
174- ) ;
175- } ) ;
141+ try {
142+ const row = this . db . prepare ( `
143+ SELECT name FROM sqlite_master
144+ WHERE type='table' AND name = ?
145+ ` ) . get ( tableName ) as SQLiteTableNameRow | undefined ;
146+
147+ return ! ! row ;
148+ } catch ( error ) {
149+ throw error ;
150+ }
176151 }
177152
178153 async getTableSchema ( tableName : string ) : Promise < TableColumn [ ] > {
179154 if ( ! this . db ) {
180155 throw new Error ( "Not connected to SQLite database" ) ;
181156 }
182157
183- return new Promise ( ( resolve , reject ) => {
184- this . db ! . all < SQLiteTableInfo > (
185- `PRAGMA table_info(${ tableName } )` ,
186- ( err , rows ) => {
187- if ( err ) {
188- reject ( err ) ;
189- } else {
190- // Convert SQLite schema format to our standard TableColumn format
191- const columns = rows . map ( row => ( {
192- column_name : row . name ,
193- data_type : row . type ,
194- is_nullable : row . notnull === 0 ? 'YES' : 'NO' , // In SQLite, 0 means nullable
195- column_default : row . dflt_value
196- } ) ) ;
197- resolve ( columns ) ;
198- }
199- }
200- ) ;
201- } ) ;
158+ try {
159+ const rows = this . db . prepare ( `PRAGMA table_info(${ tableName } )` ) . all ( ) as SQLiteTableInfo [ ] ;
160+
161+ // Convert SQLite schema format to our standard TableColumn format
162+ const columns = rows . map ( row => ( {
163+ column_name : row . name ,
164+ data_type : row . type ,
165+ is_nullable : row . notnull === 0 ? 'YES' : 'NO' , // In SQLite, 0 means nullable
166+ column_default : row . dflt_value
167+ } ) ) ;
168+
169+ return columns ;
170+ } catch ( error ) {
171+ throw error ;
172+ }
202173 }
203174
204175 async executeQuery ( query : string ) : Promise < QueryResult > {
@@ -212,15 +183,12 @@ export class SQLiteConnector implements Connector {
212183 throw new Error ( safetyCheck . message || "Query validation failed" ) ;
213184 }
214185
215- return new Promise ( ( resolve , reject ) => {
216- this . db ! . all ( query , ( err , rows ) => {
217- if ( err ) {
218- reject ( err ) ;
219- } else {
220- resolve ( { rows } ) ;
221- }
222- } ) ;
223- } ) ;
186+ try {
187+ const rows = this . db . prepare ( query ) . all ( ) ;
188+ return { rows } ;
189+ } catch ( error ) {
190+ throw error ;
191+ }
224192 }
225193
226194 validateQuery ( query : string ) : { isValid : boolean ; message ?: string } {
0 commit comments