Created
June 11, 2023 12:49
-
-
Save Ciantic/5b9eb7e145c260a0a9be5fe60756286e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @deno-types="npm:@types/sql.js" | |
import { default as initSqlJs } from "npm:sql.js"; | |
import { IDatabase, QueryResult } from "./Database.ts"; | |
export class Database implements IDatabase { | |
private path: string; | |
private sqliteJs?: initSqlJs.SqlJsStatic; | |
private db?: initSqlJs.Database; | |
private inited = false; | |
constructor(path: string, private onInit?: (db: IDatabase) => Promise<void>) { | |
this.path = path; | |
} | |
private async init() { | |
if (!this.inited) { | |
this.sqliteJs = await initSqlJs({ | |
locateFile: (file: string) => `https://sql.js.org/dist/${file}`, | |
// locateFile: (file: string) => { | |
// if (file === "sql-wasm.wasm") { | |
// return "/sql-wasm.wasm"; | |
// } | |
// return file; | |
// } | |
}); | |
await this.onInit?.(this); | |
return null as any; | |
} | |
if (this.sqliteJs) { | |
// TODO: Use this.path somehow | |
this.db = new this.sqliteJs.Database(); | |
} | |
} | |
async transaction<T>(fn: () => Promise<T>): Promise<T> { | |
await this.execute("BEGIN TRANSACTION"); | |
let result: T; | |
try { | |
result = await fn(); | |
} catch (e) { | |
await this.execute("ROLLBACK TRANSACTION"); | |
throw e; | |
} | |
await this.execute("COMMIT TRANSACTION"); | |
return result; | |
} | |
async execute(query: string, bindValues?: unknown[] | undefined): Promise<QueryResult> { | |
await this.init(); | |
if (!this.db) { | |
throw new Error("Database could not be initialized"); | |
} | |
this.db.run(query, bindValues as any); | |
// Get last insert id | |
const lastInsertId = this.db | |
.exec("SELECT last_insert_rowid()")[0] | |
.values[0][0]?.valueOf() as number; | |
const rowsAffected = this.db.getRowsModified(); | |
return { lastInsertId, rowsAffected }; | |
} | |
async select<T extends Record<string, unknown>>( | |
query: string, | |
bindValues?: unknown[] | undefined | |
): Promise<T[]> { | |
await this.init(); | |
if (!this.db) { | |
throw new Error("Database could not be initialized"); | |
} | |
const results = this.db.exec(query, bindValues as any); | |
if (results.length === 0) { | |
return []; | |
} | |
const columns = results[0].columns; | |
const values = results[0].values; | |
const rows = values.map((row) => { | |
const obj: Record<string, unknown> = {}; | |
for (let i = 0; i < columns.length; i++) { | |
obj[columns[i]] = row[i]; | |
} | |
return obj; | |
}); | |
return rows as T[]; | |
} | |
close(): Promise<boolean> { | |
if (this.db) { | |
this.db.close(); | |
return Promise.resolve(true); | |
} | |
return Promise.resolve(false); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment