Ayaz
DTDrizzle Team
•Created by Ayaz on 9/2/2023 in #help
Help with types in Repository Pattern
Hello,
I'm trying to set up a crud repository where it can be extended but I'm not sure how to get the typings correct.
Here is what I have and I'm stuck.
The issue that I have is I'm not sure how to actually get the primaryKey in a type safe way.
export interface BaseRepository<T, ID> {
findAll(): Promise<T[]>;
findAll(criteria: QueryCriteria): Promise<T[]>;
findOne(id: ID): Promise<T | null>;
update(id: ID, data: T): Promise<T>;
create(data: T): Promise<T>;
delete(id: ID): Promise<void>;
}
export abstract class CrudRepository<
M extends MySqlTable,
ID extends keyof S,
S extends InferModel<M>,
I extends InferModel<M, "insert">> implements BaseRepository<S, S[ID]> {
protected constructor(protected readonly db: DbConnection,
protected readonly schema: M,
protected readonly primaryKey: ID) {
}
async create(data: S): Promise<S> {
await this.db.insert(this.schema).values([{ ...data }]);
const result = await this.db.select().from(this.schema).where(eq(this.schema[this.primaryKey], "LAST_INSERT_ID()"));
return result[0];
}
async delete(id: S[ID]): Promise<void> {
const result = await this.db.delete(this.schema).where(eq(this.schema[this.primaryKey], id));
}
async findAll(): Promise<S[]> {
return this.db.select().from(this.schema);
}
findOne(id: S[ID]): Promise<S | null> {
return this.db.select().from(this.schema).where(eq(this.schema[this.primaryKey], id));
}
async update(id: S[ID], data: I): Promise<S | null> {
const entity = this.findOne(id);
if (!entity) {
throw new Error("Entity not found");
}
this.db.update(this.schema).set(data).where(eq(this.schema[this.primaryKey], id));
return this.findOne(id);
}
}
export interface BaseRepository<T, ID> {
findAll(): Promise<T[]>;
findAll(criteria: QueryCriteria): Promise<T[]>;
findOne(id: ID): Promise<T | null>;
update(id: ID, data: T): Promise<T>;
create(data: T): Promise<T>;
delete(id: ID): Promise<void>;
}
export abstract class CrudRepository<
M extends MySqlTable,
ID extends keyof S,
S extends InferModel<M>,
I extends InferModel<M, "insert">> implements BaseRepository<S, S[ID]> {
protected constructor(protected readonly db: DbConnection,
protected readonly schema: M,
protected readonly primaryKey: ID) {
}
async create(data: S): Promise<S> {
await this.db.insert(this.schema).values([{ ...data }]);
const result = await this.db.select().from(this.schema).where(eq(this.schema[this.primaryKey], "LAST_INSERT_ID()"));
return result[0];
}
async delete(id: S[ID]): Promise<void> {
const result = await this.db.delete(this.schema).where(eq(this.schema[this.primaryKey], id));
}
async findAll(): Promise<S[]> {
return this.db.select().from(this.schema);
}
findOne(id: S[ID]): Promise<S | null> {
return this.db.select().from(this.schema).where(eq(this.schema[this.primaryKey], id));
}
async update(id: S[ID], data: I): Promise<S | null> {
const entity = this.findOne(id);
if (!entity) {
throw new Error("Entity not found");
}
this.db.update(this.schema).set(data).where(eq(this.schema[this.primaryKey], id));
return this.findOne(id);
}
}
55 replies