[fabric/sqlite-store] Refactor SQL key handling functions for consistency and clarity

This commit is contained in:
Pablo Baleztena 2024-10-20 23:13:41 -03:00
parent 9f9419c2b6
commit 523578e310
4 changed files with 24 additions and 21 deletions

View File

@ -14,23 +14,23 @@ export function recordToSQLKeys(record: Record<string, any>) {
/** /**
* Unfold a record into a string of it's keys separated by commas. * Unfold a record into a string of it's keys separated by commas.
*/ */
export function recordToSQLKeyParams(record: Record<string, any>) { export function recordToSQLParamKeys(record: Record<string, any>) {
return Object.keys(record) return Object.keys(record)
.map((key) => keyToParam(key)) .map((key) => keyToParamKey(key))
.join(", "); .join(", ");
} }
/** /**
* Unfold a record into a string of it's keys separated by commas. * Unfold a record into a string of it's keys separated by commas.
*/ */
export function recordToSQLParams( export function recordToSQLParamRecord(
model: Model, model: Model,
record: Record<string, any>, record: Record<string, any>,
) { ) {
return Object.keys(record).reduce( return Object.keys(record).reduce(
(acc, key) => ({ (acc, key) => ({
...acc, ...acc,
[keyToParam(key)]: fieldValueToSQL(model.fields[key]!, record[key]), [keyToParamKey(key)]: fieldValueToSQL(model.fields[key]!, record[key]),
}), }),
{}, {},
); );
@ -38,10 +38,10 @@ export function recordToSQLParams(
export function recordToSQLSet(record: Record<string, any>) { export function recordToSQLSet(record: Record<string, any>) {
return Object.keys(record) return Object.keys(record)
.map((key) => `${key} = ${keyToParam(key)}`) .map((key) => `${key} = ${keyToParamKey(key)}`)
.join(", "); .join(", ");
} }
export function keyToParam(key: string) { export function keyToParamKey(key: string) {
return `$${key}`; return `$${key}`;
} }

View File

@ -26,8 +26,9 @@ export class SQLiteDatabase {
this.run("BEGIN TRANSACTION"); this.run("BEGIN TRANSACTION");
await fn(); await fn();
this.run("COMMIT"); this.run("COMMIT");
} catch { } catch (e) {
this.run("ROLLBACK"); this.run("ROLLBACK");
throw e;
} }
} }

View File

@ -3,7 +3,8 @@ import { AsyncResult, Keyof, Optional } from "@fabric/core";
import { import {
FilterOptions, FilterOptions,
Model, Model,
ModelSchema, type ModelSchema,
NotFoundError,
OrderByOptions, OrderByOptions,
SelectableQuery, SelectableQuery,
StoreLimitableQuery, StoreLimitableQuery,
@ -12,7 +13,6 @@ import {
StoreQueryError, StoreQueryError,
StoreSortableQuery, StoreSortableQuery,
} from "@fabric/domain"; } from "@fabric/domain";
import { NotFoundError } from "../../domain/models/store-query/store-query.ts";
import { filterToParams, filterToSQL } from "../sqlite/filter-to-sql.ts"; import { filterToParams, filterToSQL } from "../sqlite/filter-to-sql.ts";
import { transformRow } from "../sqlite/sql-to-value.ts"; import { transformRow } from "../sqlite/sql-to-value.ts";
import { SQLiteDatabase } from "../sqlite/sqlite-database.ts"; import { SQLiteDatabase } from "../sqlite/sqlite-database.ts";

View File

@ -1,6 +1,6 @@
import { AsyncResult, UnexpectedError, UUID } from "@fabric/core"; import { AsyncResult, UnexpectedError, UUID } from "@fabric/core";
import { import {
type AggregateModel, Model,
ModelSchemaFromModels, ModelSchemaFromModels,
ModelToType, ModelToType,
StoreQuery, StoreQuery,
@ -9,16 +9,16 @@ import {
} from "@fabric/domain"; } from "@fabric/domain";
import { modelToSql } from "../sqlite/model-to-sql.ts"; import { modelToSql } from "../sqlite/model-to-sql.ts";
import { import {
keyToParam, keyToParamKey,
recordToSQLKeyParams,
recordToSQLKeys, recordToSQLKeys,
recordToSQLParams, recordToSQLParamKeys,
recordToSQLParamRecord,
recordToSQLSet, recordToSQLSet,
} from "../sqlite/record-utils.ts"; } from "../sqlite/record-utils.ts";
import { SQLiteDatabase } from "../sqlite/sqlite-database.ts"; import { SQLiteDatabase } from "../sqlite/sqlite-database.ts";
import { QueryBuilder } from "./query-builder.ts"; import { QueryBuilder } from "./query-builder.ts";
export class SQLiteStateStore<TModel extends AggregateModel> export class SQLiteStateStore<TModel extends Model>
implements WritableStateStore<TModel> { implements WritableStateStore<TModel> {
private schema: ModelSchemaFromModels<TModel>; private schema: ModelSchemaFromModels<TModel>;
private db: SQLiteDatabase; private db: SQLiteDatabase;
@ -47,8 +47,8 @@ export class SQLiteStateStore<TModel extends AggregateModel>
recordToSQLKeys( recordToSQLKeys(
record, record,
) )
}) VALUES (${recordToSQLKeyParams(record)})`, }) VALUES (${recordToSQLParamKeys(record)})`,
recordToSQLParams(model, record), recordToSQLParamRecord(model, record),
); );
}, },
(error) => new StoreQueryError(error.message), (error) => new StoreQueryError(error.message),
@ -72,7 +72,7 @@ export class SQLiteStateStore<TModel extends AggregateModel>
return AsyncResult.tryFrom( return AsyncResult.tryFrom(
() => { () => {
const params = recordToSQLParams(model, { const params = recordToSQLParamRecord(model, {
...record, ...record,
id, id,
}); });
@ -81,7 +81,7 @@ export class SQLiteStateStore<TModel extends AggregateModel>
recordToSQLSet( recordToSQLSet(
record, record,
) )
} WHERE id = ${keyToParam("id")}`, } WHERE id = ${keyToParamKey("id")}`,
params, params,
); );
}, },
@ -98,8 +98,10 @@ export class SQLiteStateStore<TModel extends AggregateModel>
return AsyncResult.tryFrom( return AsyncResult.tryFrom(
() => { () => {
this.db.runPrepared( this.db.runPrepared(
`DELETE FROM ${model.name} WHERE id = ${keyToParam("id")}`, `DELETE FROM ${model.name} WHERE id = ${keyToParamKey("id")}`,
{ $id: id }, {
[keyToParamKey("id")]: id,
},
); );
}, },
(error) => new StoreQueryError(error.message), (error) => new StoreQueryError(error.message),
@ -109,7 +111,7 @@ export class SQLiteStateStore<TModel extends AggregateModel>
migrate(): AsyncResult<void, StoreQueryError> { migrate(): AsyncResult<void, StoreQueryError> {
return AsyncResult.tryFrom( return AsyncResult.tryFrom(
async () => { async () => {
await this.db.init(); this.db.init();
await this.db.withTransaction(() => { await this.db.withTransaction(() => {
for (const modelKey in this.schema) { for (const modelKey in this.schema) {
const model = const model =