2025-02-04 11:13:04 -05:00
|
|
|
// utils/db/db-service.ts
|
|
|
|
import {
|
2025-02-04 17:50:40 -05:00
|
|
|
openDatabaseSync,
|
|
|
|
SQLiteDatabase
|
|
|
|
} from 'expo-sqlite';
|
|
|
|
import {
|
|
|
|
SQLiteResult,
|
|
|
|
SQLiteError,
|
|
|
|
SQLiteRow
|
2025-02-04 11:13:04 -05:00
|
|
|
} from '@/types/sqlite';
|
|
|
|
|
|
|
|
export class DbService {
|
2025-02-04 17:50:40 -05:00
|
|
|
private db: SQLiteDatabase | null = null;
|
2025-02-04 11:13:04 -05:00
|
|
|
|
|
|
|
constructor(dbName: string) {
|
2025-02-04 17:50:40 -05:00
|
|
|
try {
|
|
|
|
this.db = openDatabaseSync(dbName);
|
|
|
|
console.log('Database opened:', this.db);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error opening database:', error);
|
|
|
|
throw error;
|
|
|
|
}
|
2025-02-04 11:13:04 -05:00
|
|
|
}
|
|
|
|
|
2025-02-04 17:50:40 -05:00
|
|
|
async executeSql<T extends SQLiteRow = any>(
|
|
|
|
sql: string,
|
|
|
|
params: (string | number | null)[] = []
|
|
|
|
): Promise<SQLiteResult<T>> {
|
|
|
|
if (!this.db) {
|
|
|
|
throw new Error('Database not initialized');
|
|
|
|
}
|
2025-02-04 11:13:04 -05:00
|
|
|
|
2025-02-04 17:50:40 -05:00
|
|
|
try {
|
|
|
|
const statement = this.db.prepareSync(sql);
|
|
|
|
const result = statement.executeSync<T>(params);
|
|
|
|
statement.finalizeSync();
|
|
|
|
|
|
|
|
return {
|
|
|
|
rows: {
|
|
|
|
_array: Array.isArray(result) ? result : [],
|
|
|
|
length: Array.isArray(result) ? result.length : 0,
|
|
|
|
item: (idx: number) => (Array.isArray(result) ? result[idx] : null) as T
|
|
|
|
},
|
|
|
|
rowsAffected: Array.isArray(result) ? result.length : 0,
|
|
|
|
insertId: undefined // SQLite doesn't provide this directly
|
|
|
|
};
|
|
|
|
} catch (error) {
|
|
|
|
console.error('SQL Error:', error, sql, params);
|
|
|
|
throw error;
|
|
|
|
}
|
2025-02-04 11:13:04 -05:00
|
|
|
}
|
|
|
|
|
2025-02-04 17:50:40 -05:00
|
|
|
async executeWrite<T extends SQLiteRow = any>(
|
|
|
|
sql: string,
|
|
|
|
params: (string | number | null)[] = []
|
|
|
|
): Promise<SQLiteResult<T>> {
|
|
|
|
return this.executeSql<T>(sql, params);
|
2025-02-04 11:13:04 -05:00
|
|
|
}
|
|
|
|
|
2025-02-04 17:50:40 -05:00
|
|
|
async executeWriteMany<T extends SQLiteRow = any>(
|
|
|
|
queries: Array<{
|
|
|
|
sql: string;
|
|
|
|
args?: (string | number | null)[]
|
|
|
|
}>
|
|
|
|
): Promise<SQLiteResult<T>[]> {
|
|
|
|
if (!this.db) {
|
|
|
|
throw new Error('Database not initialized');
|
|
|
|
}
|
|
|
|
|
|
|
|
const results: SQLiteResult<T>[] = [];
|
|
|
|
|
|
|
|
for (const query of queries) {
|
|
|
|
try {
|
|
|
|
const result = await this.executeSql<T>(query.sql, query.args || []);
|
|
|
|
results.push(result);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error executing query:', query, error);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
2025-02-04 11:13:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
async tableExists(tableName: string): Promise<boolean> {
|
|
|
|
try {
|
2025-02-04 17:50:40 -05:00
|
|
|
const result = await this.executeSql<{ name: string }>(
|
2025-02-04 11:13:04 -05:00
|
|
|
`SELECT name FROM sqlite_master WHERE type='table' AND name=?`,
|
|
|
|
[tableName]
|
|
|
|
);
|
2025-02-04 17:50:40 -05:00
|
|
|
return result.rows._array.length > 0;
|
2025-02-04 11:13:04 -05:00
|
|
|
} catch (error) {
|
|
|
|
console.error('Error checking table existence:', error);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-04 17:50:40 -05:00
|
|
|
async initialize(): Promise<void> {
|
2025-02-04 11:13:04 -05:00
|
|
|
try {
|
2025-02-04 17:50:40 -05:00
|
|
|
await this.executeSql('PRAGMA foreign_keys = ON;');
|
2025-02-04 11:13:04 -05:00
|
|
|
} catch (error) {
|
2025-02-04 17:50:40 -05:00
|
|
|
console.error('Error initializing database:', error);
|
2025-02-04 11:13:04 -05:00
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|