From 20ac2da081c88ad7daf0046cab5e706ae7f90a19 Mon Sep 17 00:00:00 2001 From: Endeavorance Date: Wed, 1 Jan 2025 12:18:54 -0500 Subject: [PATCH] 1.1.0 --- package.json | 2 +- src/prequel.ts | 4 ++++ src/table.ts | 17 ++++++++++++----- test/prequel.test.ts | 8 ++++++++ test/table.test.ts | 22 ++++++++++++++++++++++ test/wrapped-row.ts | 4 ---- 6 files changed, 47 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index d532f11..8a51e09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@endeavorance/prequel", - "version": "1.0.0", + "version": "1.1.0", "exports": "./dist/index.js", "types": "./dist/index.d.ts", "scripts": { diff --git a/src/prequel.ts b/src/prequel.ts index ad12cf7..4e09fe2 100644 --- a/src/prequel.ts +++ b/src/prequel.ts @@ -105,6 +105,8 @@ export class Prequel { public db: Database; public kv: PrequelKVStore; public tables: Record> = {}; + public query: typeof Database.prototype.query; + public uncachedQuery: typeof Database.prototype.prepare; /** * Creates a new Prequel database instance. @@ -112,6 +114,8 @@ export class Prequel { */ 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"); } diff --git a/src/table.ts b/src/table.ts index b29dbf0..a17316e 100644 --- a/src/table.ts +++ b/src/table.ts @@ -27,12 +27,10 @@ export class PrequelEmptyResultsError extends Error { } /** An arbitrarily shaped Row */ -interface ArbitraryRow { - [key: string]: ColumnValue; -} +type ArbitraryRow = Record; -function shapeForQuery(obj: Partial): Record { - const asInsertDataShape: Record = {}; +function shapeForQuery(obj: Partial): ArbitraryRow { + const asInsertDataShape: ArbitraryRow = {}; const keys = Object.keys(obj); @@ -72,6 +70,8 @@ export class Table { private _sizeQuery: Statement<{ count: number }, []>; private _truncateQuery: Statement; + public query: typeof Database.prototype.query; + constructor( db: Database | Prequel, name: string, @@ -85,6 +85,7 @@ export class Table { this._name = name; this._columnDefinitions = normalizeColumns(cols); this._columnNames = Object.keys(this._columnDefinitions); + this.query = this._db.query.bind(this._db); const columnSQLParts: string[] = []; const updateColumnSQLParts: string[] = []; @@ -211,6 +212,12 @@ export class Table { return query.get(asInsertDataShape) as RowShape; } + public insertWithout( + rowWithKeysOmitted: Omit, + ): RowShape { + return this.insertPartial(rowWithKeysOmitted as Partial); + } + /** * Updates a row in the table with the provided data. * diff --git a/test/prequel.test.ts b/test/prequel.test.ts index a5b429f..164e3c3 100644 --- a/test/prequel.test.ts +++ b/test/prequel.test.ts @@ -135,3 +135,11 @@ test("kv store can set and retrieve arbitrary values", () => { expect(pq.kv.get<{ enabled: boolean }>("config")).toEqual({ enabled: true }); expect(pq.kv.get("list")).toEqual(["a", "b", "c"]); }); + +test(".query() creates a cached statement", () => { + const pq = new Prequel(); + const query = pq.query("SELECT 1"); + + expect(query).toBeDefined(); + expect(query).toBe(pq.query("SELECT 1")); +}); diff --git a/test/table.test.ts b/test/table.test.ts index 59f91d4..f3c4a69 100644 --- a/test/table.test.ts +++ b/test/table.test.ts @@ -138,6 +138,22 @@ test(".insertPartial() inserts a partial row", () => { }); }); +test(".insertWithout() inserts a partial row with type safety", () => { + const table = makeTestTable(); + table.insertWithout<"user_id">({ + name: "Jack", + }); + + const lookup = table.db.prepare( + `SELECT * FROM ${table} WHERE name = ?`, + ); + const found = lookup.get("Jack"); + expect(found).toEqual({ + user_id: 1, + name: "Jack", + }); +}); + test(".count() gets the current number of rows in the table", () => { const table = makeTestTable(); table.insertPartial({ name: "Jack" }); @@ -167,6 +183,12 @@ test(".findAll() returns the full table", () => { expect(allUsers[2]).toEqual({ user_id: 3, name: "Sayid" }); }); +test(".query() returns a prepared statement for the table", () => { + const table = makeTestTable(); + const query = table.query("SELECT * FROM Users WHERE name = ?"); + expect(query).toBeDefined(); +}); + test(".findOneWhere() returns a row based on basic criteria", () => { const table = makeTestTable(); table.insertPartial({ name: "Jack" }); diff --git a/test/wrapped-row.ts b/test/wrapped-row.ts index d500c7b..f92d621 100644 --- a/test/wrapped-row.ts +++ b/test/wrapped-row.ts @@ -7,10 +7,6 @@ interface User { name: string; } -interface SerializedUser { - name: string; -} - const db = new Database(); const table = new Table(db, "Users", { id: {