Move all database queries in ModelQuery class.
This commit is contained in:
parent
ff793f31f4
commit
a29e6f4428
2 changed files with 80 additions and 53 deletions
|
@ -1,16 +1,9 @@
|
|||
import {IdentifierType, Model, ModelShape, SerializedModel} from "@sharkitek/core";
|
||||
import {eq, getTableColumns, Table, TableConfig} from "drizzle-orm";
|
||||
import {IdentifierType, Model, ModelClass, ModelShape} from "@sharkitek/core";
|
||||
import {Table, TableConfig} from "drizzle-orm";
|
||||
import {PgDatabase} from "drizzle-orm/pg-core";
|
||||
import {PgQueryResultHKT} from "drizzle-orm/pg-core/session";
|
||||
import type {ExtractTablesWithRelations, TablesRelationalConfig} from "drizzle-orm/relations";
|
||||
import {ModelQuery} from "./Query";
|
||||
|
||||
/**
|
||||
* Serialized values converters for database.
|
||||
*/
|
||||
export const serializedToDatabaseTypes: Record<string, (serializedValue: any) => any> = {
|
||||
"date": (serializedValue: string) => new Date(serializedValue),
|
||||
};
|
||||
import {ModelQuery, query} from "./Query";
|
||||
|
||||
/**
|
||||
* Sharkitek model extension for Drizzle.
|
||||
|
@ -40,7 +33,8 @@ export class DrizzleModel<
|
|||
Shape extends ModelShape, Identifier extends keyof Shape = any, TSchema extends TablesRelationalConfig = ExtractTablesWithRelations<TFullSchema>
|
||||
>
|
||||
{
|
||||
constructor(protected model: ModelType,
|
||||
constructor(protected modelClass: ModelClass<ModelType & DrizzleExtension<ModelType, TableType, TC, TQueryResult, TFullSchema, Scopes, Shape, Identifier, TSchema>, Shape, Identifier>,
|
||||
protected model: ModelType,
|
||||
protected database: PgDatabase<TQueryResult, TFullSchema, TSchema>,
|
||||
protected table: TableType,
|
||||
protected scopes: Scopes & ThisType<ModelQuery<ModelType, TableType, TC, TQueryResult, TFullSchema, Shape, Identifier, TSchema>>)
|
||||
|
@ -75,50 +69,17 @@ export class DrizzleModel<
|
|||
*/
|
||||
async save(): Promise<boolean>
|
||||
{
|
||||
// Get serialized model update.
|
||||
const serializedModel = this.model.patch();
|
||||
|
||||
// Get table columns of the model.
|
||||
const tableColumns = getTableColumns(this.table);
|
||||
|
||||
// Create model data for the database.
|
||||
const databaseModelData = Object.fromEntries(
|
||||
Object.entries(serializedModel).map(
|
||||
// Only keep table column values and convert them into database types, if it is required.
|
||||
([key, value]) => [key, tableColumns?.[key] ? (serializedToDatabaseTypes?.[tableColumns?.[key].dataType]?.(value) ?? value) : undefined]
|
||||
)
|
||||
) as Partial<SerializedModel<Shape>>;
|
||||
|
||||
// Initialize query result variable.
|
||||
let result: any;
|
||||
|
||||
if (this.model.isNew())
|
||||
{ // Insert the new model in database and get the inserted row data.
|
||||
result = (await (this.database.insert(this.table)).values(databaseModelData as any).returning() as any)?.[0];
|
||||
}
|
||||
else
|
||||
{ // Update model data in database, and get the updated row data.
|
||||
result = (await (this.database.update(this.table)
|
||||
.set(databaseModelData)
|
||||
.where(eq((this.table as any)?.[this.model.getIdentifierName()], this.model.getIdentifier())))
|
||||
.returning() as any)?.[0];
|
||||
}
|
||||
|
||||
// Update model from inserted or updated row data.
|
||||
this.model.deserialize(result);
|
||||
|
||||
return true;
|
||||
// New query to save the model.
|
||||
return query(this.modelClass).save(this.model as any);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh model data from database.
|
||||
*/
|
||||
async refresh(): Promise<void>
|
||||
{
|
||||
// Update model from up-to-date row data.
|
||||
this.model.deserialize(
|
||||
(( // Retrieve model data from database.
|
||||
await this.database.select().from(this.table)
|
||||
.where(eq((this.table as any)?.[this.model.getIdentifierName()], this.model.getIdentifier()))
|
||||
) as any)[0]
|
||||
);
|
||||
// New query to refresh the model.
|
||||
await query(this.modelClass).refresh(this.model as any);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +106,10 @@ export function drizzle<
|
|||
drizzle(): DrizzleModel<ModelType, TableType, TC, TQueryResult, TFullSchema, Scopes, Shape, Identifier, TSchema>
|
||||
{
|
||||
// Initialize drizzle model manager instance.
|
||||
return new DrizzleModel<ModelType, TableType, TC, TQueryResult, TFullSchema, Scopes, Shape, Identifier, TSchema>(this, database, table, scopes);
|
||||
return new DrizzleModel<ModelType, TableType, TC, TQueryResult, TFullSchema, Scopes, Shape, Identifier, TSchema>(
|
||||
this.constructor as ModelClass<ModelType & DrizzleExtension<ModelType, TableType, TC, TQueryResult, TFullSchema, Scopes, Shape, Identifier, TSchema>, Shape, Identifier>,
|
||||
this, database, table, scopes
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
65
src/Query.ts
65
src/Query.ts
|
@ -1,5 +1,5 @@
|
|||
import {AnyModel, IdentifierType, Model, ModelClass, ModelShape, SerializedModel} from "@sharkitek/core";
|
||||
import {eq, getTableName, Table, TableConfig} from "drizzle-orm";
|
||||
import {eq, getTableColumns, getTableName, Table, TableConfig} from "drizzle-orm";
|
||||
import {PgDatabase} from "drizzle-orm/pg-core";
|
||||
import {PgQueryResultHKT} from "drizzle-orm/pg-core/session";
|
||||
import type {DBQueryConfig, ExtractTablesWithRelations, TablesRelationalConfig} from "drizzle-orm/relations";
|
||||
|
@ -7,6 +7,13 @@ import type {KnownKeysOnly} from "drizzle-orm/utils";
|
|||
import {DrizzleExtension} from "./Drizzle";
|
||||
import {inArray} from "drizzle-orm/sql/expressions/conditions";
|
||||
|
||||
/**
|
||||
* Serialized values converters for database.
|
||||
*/
|
||||
export const serializedToDatabaseTypes: Record<string, (serializedValue: any) => any> = {
|
||||
"date": (serializedValue: string) => new Date(serializedValue),
|
||||
};
|
||||
|
||||
/**
|
||||
* Model query manager.
|
||||
*/
|
||||
|
@ -33,6 +40,62 @@ export class ModelQuery<
|
|||
return (new this.modelClass()).deserialize(rawModel) as ModelType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a model in database.
|
||||
* @param model The model to save.
|
||||
*/
|
||||
async save(model: ModelType): Promise<boolean>
|
||||
{
|
||||
// Get serialized model update.
|
||||
const serializedModel = model.patch();
|
||||
|
||||
// Get table columns of the model.
|
||||
const tableColumns = getTableColumns(this.table);
|
||||
|
||||
// Create model data for the database.
|
||||
const databaseModelData = Object.fromEntries(
|
||||
Object.entries(serializedModel).map(
|
||||
// Only keep table column values and convert them into database types, if it is required.
|
||||
([key, value]) => [key, tableColumns?.[key] ? (serializedToDatabaseTypes?.[tableColumns?.[key].dataType]?.(value) ?? value) : undefined]
|
||||
)
|
||||
) as Partial<SerializedModel<Shape>>;
|
||||
|
||||
// Initialize query result variable.
|
||||
let result: any;
|
||||
|
||||
if (model.isNew())
|
||||
{ // Insert the new model in database and get the inserted row data.
|
||||
result = (await (this.database.insert(this.table)).values(databaseModelData as any).returning() as any)?.[0];
|
||||
}
|
||||
else
|
||||
{ // Update model data in database, and get the updated row data.
|
||||
result = (await (this.database.update(this.table)
|
||||
.set(databaseModelData)
|
||||
.where(eq((this.table as any)?.[model.getIdentifierName()], model.getIdentifier())))
|
||||
.returning() as any)?.[0];
|
||||
}
|
||||
|
||||
// Update model from inserted or updated row data.
|
||||
model.deserialize(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh given model data from database.
|
||||
* @param model The model to refresh.
|
||||
*/
|
||||
async refresh(model: ModelType): Promise<void>
|
||||
{
|
||||
// Update model from up-to-date row data.
|
||||
model.deserialize(
|
||||
(( // Retrieve model data from database.
|
||||
await this.database.select().from(this.table)
|
||||
.where(eq((this.table as any)?.[model.getIdentifierName()], model.getIdentifier()))
|
||||
) as any)[0]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find models matching the given configuration.
|
||||
* @param config Request configuration.
|
||||
|
|
Loading…
Reference in a new issue