Add biome

This commit is contained in:
Endeavorance 2025-04-06 19:28:42 -04:00
parent 09d25c926c
commit 6479d09196
9 changed files with 586 additions and 538 deletions

View file

@ -28,7 +28,7 @@ export const ColumnOf = {
type: otherTable.primaryColumnType(),
references: otherTable.reference(),
nullable: false,
cascade
cascade,
};
},
@ -36,7 +36,6 @@ export const ColumnOf = {
Text: {
type: "TEXT",
nullable: true,
},
Int: {
@ -94,7 +93,7 @@ export const ColumnOf = {
return {
type: "TEXT",
default: defaultValue,
}
};
},
Int(defaultValue: number): ColumnShorthand {
@ -109,7 +108,6 @@ export const ColumnOf = {
type: "REAL",
default: defaultValue,
} as const;
}
},
},
} as const;

View file

@ -1,6 +1,13 @@
import { ColumnOf } from "./column-types";
import type { Column, ColumnShorthand, DataType } from "./columns";
import { Prequel } from "./prequel";
import { Table } from "./table";
import { ColumnOf } from "./column-types";
export { Prequel, Table, ColumnOf, type DataType, type Column, type ColumnShorthand };
export {
Prequel,
Table,
ColumnOf,
type DataType,
type Column,
type ColumnShorthand,
};

View file

@ -4,194 +4,194 @@ import { SchemaError } from "./error";
import { Table } from "./table";
interface KVRow {
kv_id: number;
key: string;
value: string;
kv_id: number;
key: string;
value: string;
}
/**
* Represents a key-value store using Prequel.
*/
export class PrequelKVStore {
private table: Table<KVRow>;
private table: Table<KVRow>;
/**
* Creates a new instance of the PrequelKVStore class.
* @param pq The Prequel instance.
* @param tableName The name of the table.
*/
constructor(pq: Prequel, tableName: string) {
this.table = pq.table<KVRow>(tableName, {
kv_id: {
type: "INTEGER",
primary: true,
autoincrement: true,
},
key: "TEXT",
value: "TEXT",
});
}
/**
* Creates a new instance of the PrequelKVStore class.
* @param pq The Prequel instance.
* @param tableName The name of the table.
*/
constructor(pq: Prequel, tableName: string) {
this.table = pq.table<KVRow>(tableName, {
kv_id: {
type: "INTEGER",
primary: true,
autoincrement: true,
},
key: "TEXT",
value: "TEXT",
});
}
/**
* Inserts or updates a key-value pair in the store.
* @param key The key.
* @param value The value.
*/
put<T>(key: string, value: T): void {
const lookup = this.table.findOneWhere({
key,
});
/**
* Inserts or updates a key-value pair in the store.
* @param key The key.
* @param value The value.
*/
put<T>(key: string, value: T): void {
const lookup = this.table.findOneWhere({
key,
});
if (lookup === null) {
this.table.insertPartial({
key,
value: JSON.stringify(value),
});
} else {
lookup.value = JSON.stringify(value);
this.table.update(lookup);
}
}
if (lookup === null) {
this.table.insertPartial({
key,
value: JSON.stringify(value),
});
} else {
lookup.value = JSON.stringify(value);
this.table.update(lookup);
}
}
/**
* Retrieves the value associated with the specified key from the store.
* @param key The key.
* @returns The value associated with the key, or null if the key is not found.
*/
get<T>(key: string): T | null {
const lookup = this.table.findOneWhere({ key });
/**
* Retrieves the value associated with the specified key from the store.
* @param key The key.
* @returns The value associated with the key, or null if the key is not found.
*/
get<T>(key: string): T | null {
const lookup = this.table.findOneWhere({ key });
if (lookup === null) {
return null;
}
if (lookup === null) {
return null;
}
return JSON.parse(lookup.value) as T;
}
return JSON.parse(lookup.value) as T;
}
/**
* Checks if a key exists in the table.
* @param key - The key to check.
* @returns `true` if the key exists, `false` otherwise.
*/
has(key: string): boolean {
return (
this.table.findOneWhere({
key,
}) !== null
);
}
/**
* Checks if a key exists in the table.
* @param key - The key to check.
* @returns `true` if the key exists, `false` otherwise.
*/
has(key: string): boolean {
return (
this.table.findOneWhere({
key,
}) !== null
);
}
/**
* Get an array of all of the keys in the KV store
* @returns The keys in the store.
*/
keys(): string[] {
return this.table.findAll().map((row) => row.key);
}
/**
* Get an array of all of the keys in the KV store
* @returns The keys in the store.
*/
keys(): string[] {
return this.table.findAll().map((row) => row.key);
}
/**
* Get an array of all of the values in the KV store
* @returns The values in the store.
*/
values(): unknown[] {
return this.table.findAll().map((row) => JSON.parse(row.value));
}
/**
* Get an array of all of the values in the KV store
* @returns The values in the store.
*/
values(): unknown[] {
return this.table.findAll().map((row) => JSON.parse(row.value));
}
}
/**
* Represents a Prequel database instance.
*/
export class Prequel {
public db: Database;
public kv: PrequelKVStore;
public tables: Record<string, Table<unknown>> = {};
public query: typeof Database.prototype.query;
public uncachedQuery: typeof Database.prototype.prepare;
public db: Database;
public kv: PrequelKVStore;
public tables: Record<string, Table<unknown>> = {};
public query: typeof Database.prototype.query;
public uncachedQuery: typeof Database.prototype.prepare;
/**
* Creates a new Prequel database instance.
* @param filename The filename of the database. Defaults to ":memory:" if not provided.
*/
constructor(filename = ":memory:") {
this.db = new Database(filename);
this.query = this.db.query.bind(this.db);
this.uncachedQuery = this.db.prepare.bind(this.db);
this.db.exec("PRAGMA foreign_keys=ON");
this.kv = new PrequelKVStore(this, "PrequelManagedKVStore");
}
/**
* Creates a new Prequel database instance.
* @param filename The filename of the database. Defaults to ":memory:" if not provided.
*/
constructor(filename = ":memory:") {
this.db = new Database(filename);
this.query = this.db.query.bind(this.db);
this.uncachedQuery = this.db.prepare.bind(this.db);
this.db.exec("PRAGMA foreign_keys=ON");
this.kv = new PrequelKVStore(this, "PrequelManagedKVStore");
}
/**
* Enables Write-Ahead Logging (WAL) mode for the database.
*/
enableWAL() {
this.db.exec("PRAGMA journal_mode=WAL;");
}
/**
* Enables Write-Ahead Logging (WAL) mode for the database.
*/
enableWAL() {
this.db.exec("PRAGMA journal_mode=WAL;");
}
/**
* Closes the database connection.
*/
close() {
this.db.close();
}
/**
* Closes the database connection.
*/
close() {
this.db.close();
}
/**
* Checks if a table with the given name exists in the database.
* @param name The name of the table.
* @returns `true` if the table exists, `false` otherwise.
*/
hasTable(name: string): boolean {
return Object.keys(this.tables).includes(name);
}
/**
* Checks if a table with the given name exists in the database.
* @param name The name of the table.
* @returns `true` if the table exists, `false` otherwise.
*/
hasTable(name: string): boolean {
return Object.keys(this.tables).includes(name);
}
/**
* Creates a new table in the database.
* @param name The name of the table.
* @param cols The column definitions of the table.
* @returns The created table.
* @throws {SchemaError} If a table with the same name already exists.
*/
table<RowShape>(
name: string,
cols: ColumnShorthandMap<RowShape>,
): Table<RowShape> {
if (this.hasTable(name)) {
throw new SchemaError("Duplicate table name", name);
}
/**
* Creates a new table in the database.
* @param name The name of the table.
* @param cols The column definitions of the table.
* @returns The created table.
* @throws {SchemaError} If a table with the same name already exists.
*/
table<RowShape>(
name: string,
cols: ColumnShorthandMap<RowShape>,
): Table<RowShape> {
if (this.hasTable(name)) {
throw new SchemaError("Duplicate table name", name);
}
const newTable = new Table(this, name, cols);
this.tables[name] = newTable;
return newTable;
}
const newTable = new Table(this, name, cols);
this.tables[name] = newTable;
return newTable;
}
/**
* Attaches an existing table to the database.
* @param table The table to attach.
* @throws {SchemaError} If a table with the same name already exists.
*/
attachTable(table: Table<unknown>) {
if (this.hasTable(table.name)) {
throw new SchemaError("Duplicate table name", table.name);
}
/**
* Attaches an existing table to the database.
* @param table The table to attach.
* @throws {SchemaError} If a table with the same name already exists.
*/
attachTable(table: Table<unknown>) {
if (this.hasTable(table.name)) {
throw new SchemaError("Duplicate table name", table.name);
}
this.tables[table.name] = table;
}
/**
* Executes a function within a database transaction.
* If the function throws an error, the transaction is rolled back.
* Otherwise, the transaction is committed.
* @param transactionFn The function to execute within the transaction.
* @returns `true` if the transaction was committed successfully, otherwise `false`.
* @throws The error thrown by the transaction function if the transaction fails.
*/
transaction<T>(transactionFn: () => T): T {
try {
this.db.exec("BEGIN TRANSACTION;");
const result: T = transactionFn();
this.db.exec("COMMIT;");
return result;
} catch (error) {
this.db.exec("ROLLBACK;");
throw error;
}
}
this.tables[table.name] = table;
}
/**
* Executes a function within a database transaction.
* If the function throws an error, the transaction is rolled back.
* Otherwise, the transaction is committed.
* @param transactionFn The function to execute within the transaction.
* @returns `true` if the transaction was committed successfully, otherwise `false`.
* @throws The error thrown by the transaction function if the transaction fails.
*/
transaction<T>(transactionFn: () => T): T {
try {
this.db.exec("BEGIN TRANSACTION;");
const result: T = transactionFn();
this.db.exec("COMMIT;");
return result;
} catch (error) {
this.db.exec("ROLLBACK;");
throw error;
}
}
}

View file

@ -37,9 +37,15 @@ function shapeForQuery<T>(obj: Partial<T>): ArbitraryRow {
for (const key of keys) {
const val = obj[key as keyof T];
if (typeof val !== "string" && typeof val !== "number" && val !== null) {
if (
typeof val === "string" &&
typeof val === "number" &&
typeof val === "boolean" &&
typeof val === "bigint" &&
val !== null
) {
throw new SchemaError(
`Invalid value in query: ${key}: ${val} (type: ${typeof val})`,
`Invalid value in query: ${key} -> ${val} (type: ${typeof val})`,
);
}
@ -97,7 +103,7 @@ export class Table<RowShape> {
for (const columnName of this._columnNames) {
const columnDefinition =
this._columnDefinitions[
columnName as keyof typeof this._columnDefinitions
columnName as keyof typeof this._columnDefinitions
];
// Identify a primary column besides ROWID if specified
@ -160,7 +166,8 @@ export class Table<RowShape> {
}
public primaryColumnType(): DataType {
const primary = this._primaryColumnName as keyof typeof this._columnDefinitions;
const primary = this
._primaryColumnName as keyof typeof this._columnDefinitions;
return this._columnDefinitions[primary].type;
}