Ayaz
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