Skip to content

Instantly share code, notes, and snippets.

@Ciantic
Created June 11, 2023 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ciantic/5b9eb7e145c260a0a9be5fe60756286e to your computer and use it in GitHub Desktop.
Save Ciantic/5b9eb7e145c260a0a9be5fe60756286e to your computer and use it in GitHub Desktop.
// @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