|
@ -8,10 +8,10 @@ import { SQLiteFS } from "absurd-sql"; |
|
|
import IndexedDBBackend from "absurd-sql/dist/indexeddb-backend"; |
|
|
import IndexedDBBackend from "absurd-sql/dist/indexeddb-backend"; |
|
|
|
|
|
|
|
|
import { runMigrations } from "../db-sql/migration"; |
|
|
import { runMigrations } from "../db-sql/migration"; |
|
|
import type { QueryExecResult } from "../interfaces/database"; |
|
|
import type { DatabaseService, QueryExecResult } from "../interfaces/database"; |
|
|
import { logger } from "@/utils/logger"; |
|
|
import { logger } from "@/utils/logger"; |
|
|
|
|
|
|
|
|
interface SQLDatabase { |
|
|
interface AbsurdSqlDatabase { |
|
|
exec: (sql: string, params?: unknown[]) => Promise<QueryExecResult[]>; |
|
|
exec: (sql: string, params?: unknown[]) => Promise<QueryExecResult[]>; |
|
|
run: ( |
|
|
run: ( |
|
|
sql: string, |
|
|
sql: string, |
|
@ -19,9 +19,9 @@ interface SQLDatabase { |
|
|
) => Promise<{ changes: number; lastId?: number }>; |
|
|
) => Promise<{ changes: number; lastId?: number }>; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
class DatabaseService { |
|
|
class AbsurdSqlDatabaseService implements DatabaseService { |
|
|
private static instance: DatabaseService | null = null; |
|
|
private static instance: AbsurdSqlDatabaseService | null = null; |
|
|
private db: SQLDatabase | null; |
|
|
private db: AbsurdSqlDatabase | null; |
|
|
private initialized: boolean; |
|
|
private initialized: boolean; |
|
|
private initializationPromise: Promise<void> | null = null; |
|
|
private initializationPromise: Promise<void> | null = null; |
|
|
|
|
|
|
|
@ -30,11 +30,11 @@ class DatabaseService { |
|
|
this.initialized = false; |
|
|
this.initialized = false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static getInstance(): DatabaseService { |
|
|
static getInstance(): AbsurdSqlDatabaseService { |
|
|
if (!DatabaseService.instance) { |
|
|
if (!AbsurdSqlDatabaseService.instance) { |
|
|
DatabaseService.instance = new DatabaseService(); |
|
|
AbsurdSqlDatabaseService.instance = new AbsurdSqlDatabaseService(); |
|
|
} |
|
|
} |
|
|
return DatabaseService.instance; |
|
|
return AbsurdSqlDatabaseService.instance; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async initialize(): Promise<void> { |
|
|
async initialize(): Promise<void> { |
|
@ -53,7 +53,7 @@ class DatabaseService { |
|
|
try { |
|
|
try { |
|
|
await this.initializationPromise; |
|
|
await this.initializationPromise; |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
logger.error(`DatabaseService initialize method failed:`, error); |
|
|
logger.error(`AbsurdSqlDatabaseService initialize method failed:`, error); |
|
|
this.initializationPromise = null; // Reset on failure
|
|
|
this.initializationPromise = null; // Reset on failure
|
|
|
throw error; |
|
|
throw error; |
|
|
} |
|
|
} |
|
@ -79,7 +79,7 @@ class DatabaseService { |
|
|
SQL.FS.mkdir("/sql"); |
|
|
SQL.FS.mkdir("/sql"); |
|
|
SQL.FS.mount(sqlFS, {}, "/sql"); |
|
|
SQL.FS.mount(sqlFS, {}, "/sql"); |
|
|
|
|
|
|
|
|
const path = "/sql/db.sqlite"; |
|
|
const path = "/sql/timesafari.sqlite"; |
|
|
if (typeof SharedArrayBuffer === "undefined") { |
|
|
if (typeof SharedArrayBuffer === "undefined") { |
|
|
const stream = SQL.FS.open(path, "a+"); |
|
|
const stream = SQL.FS.open(path, "a+"); |
|
|
await stream.node.contents.readIfFallback(); |
|
|
await stream.node.contents.readIfFallback(); |
|
@ -93,6 +93,7 @@ class DatabaseService { |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// An error is thrown without this pragma: "File has invalid page size. (the first block of a new file must be written first)"
|
|
|
await this.db.exec(`PRAGMA journal_mode=MEMORY;`); |
|
|
await this.db.exec(`PRAGMA journal_mode=MEMORY;`); |
|
|
const sqlExec = this.db.exec.bind(this.db); |
|
|
const sqlExec = this.db.exec.bind(this.db); |
|
|
|
|
|
|
|
@ -150,7 +151,7 @@ class DatabaseService { |
|
|
return result[0]?.values[0]; |
|
|
return result[0]?.values[0]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async all(sql: string, params: unknown[] = []): Promise<unknown[][]> { |
|
|
async getAll(sql: string, params: unknown[] = []): Promise<unknown[][]> { |
|
|
await this.waitForInitialization(); |
|
|
await this.waitForInitialization(); |
|
|
const result = await this.db!.exec(sql, params); |
|
|
const result = await this.db!.exec(sql, params); |
|
|
return result[0]?.values || []; |
|
|
return result[0]?.values || []; |
|
@ -158,6 +159,6 @@ class DatabaseService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Create a singleton instance
|
|
|
// Create a singleton instance
|
|
|
const databaseService = DatabaseService.getInstance(); |
|
|
const databaseService = AbsurdSqlDatabaseService.getInstance(); |
|
|
|
|
|
|
|
|
export default databaseService; |
|
|
export default databaseService; |