Generic base repository abstract class

So, I’m trying to create a base repository class to extend based on my schema definitions, thing is I’m having trouble getting the types to work, here is my example

import type { InferSelectModel, SQL } from 'drizzle-orm';
import type { AnyPgTable } from 'drizzle-orm/pg-core';

import type { DB, DBTransaction } from './client';

export interface RepositoryOptions {
  db?: DB;
  tx?: DBTransaction;
}

/**
 * A generic base repository class for Drizzle ORM
 *
 * Note: This implementation uses type assertions in some places to work
 * around limitations in TypeScript's ability to fully type the Drizzle ORM.
 * The public API is fully typed, but internal implementations may use 'any'.
 */
export class BaseRepository<
  TTable extends AnyPgTable,
  TSelect = InferSelectModel<TTable>,
> {
  protected table: TTable;
  protected db: DB | DBTransaction;
  constructor(table: TTable, db: DB | DBTransaction) {
    this.table = table;
    this.db = db;
  }

  /**
   * Find all records matching the given criteria
   */
  async findAll(
    options: {
      limit?: number;
      offset?: number;
      orderBy?: SQL<unknown>;
      where?: SQL<unknown>;
    } = {},
  ): Promise<TSelect[]> {
    const { limit, offset, orderBy, where } = options;

    // Using any to avoid complex type issues with the query builder
    let query = this.db.select().from(this.table).$dynamic();

    if (where) {
      query = query.where(where);
    }

    if (orderBy) {
      query = query.orderBy(orderBy);
    }

    if (limit) {
      query = query.limit(limit);
    }

    if (offset) {
      query = query.offset(offset);
    }

    return query;
  }
}
Was this page helpful?