Untitled

mail@pastecode.io avatar
unknown
plain_text
10 days ago
2.6 kB
4
Indexable
Never
import { Model, Document, FilterQuery, UpdateQuery, PopulateOptions } from 'mongoose';

interface PaginationOptions {
  page?: number;
  limit?: number;
}

interface ReadAllOptions<T> {
  query?: FilterQuery<T>;
  projection?: Record<string, unknown>;
  sort?: Record<string, 1 | -1>;
  filter?: FilterQuery<T>;
  pagination?: PaginationOptions;
  includes?: string[] | PopulateOptions[];
}

interface PaginatedResult<T> {
  docs: T[];
  totalDocs: number;
  totalPages: number;
  currentPage: number;
  hasNextPage: boolean;
  hasPrevPage: boolean;
  nextPage: number | null;
  prevPage: number | null;
}

interface DbOperation<T extends Document> {
  create: (model: Model<T>, data: Partial<T>) => Promise<T>;
  read: (model: Model<T>, options: { query?: FilterQuery<T>; includes?: string[] | PopulateOptions[] }) => Promise<T | null>;
  readAll: (model: Model<T>, options: ReadAllOptions<T>) => Promise<PaginatedResult<T>>;
  update: (model: Model<T>, options: { query: FilterQuery<T>; update: UpdateQuery<T> }) => Promise<T | null>;
  delete: (model: Model<T>, options: { query: FilterQuery<T> }) => Promise<T | null>;
}

export const dbOperation: DbOperation<any> = {
  async create(model, data) {
    return await model.create(data);
  },

  async read(model, { query = {}, includes = [] }) {
    return await model.findOne(query).populate(includes).exec();
  },

  async readAll(model, { query = {}, projection = {}, sort = {}, filter = {}, pagination = {}, includes = [] }) {
    const { page = 1, limit = 10 } = pagination;

    // Combine query and filter for better optimization
    const combinedQuery = { ...query, ...filter };

    // Total document count for pagination
    const totalDocs = await model.countDocuments(combinedQuery).exec();
    const totalPages = Math.ceil(totalDocs / limit);
    const hasNextPage = page < totalPages;
    const hasPrevPage = page > 1;
    const nextPage = hasNextPage ? page + 1 : null;
    const prevPage = hasPrevPage ? page - 1 : null;

    // Query MongoDB
    const docs = await model.find(combinedQuery)
      .select(projection)
      .sort(sort)
      .skip((page - 1) * limit)
      .limit(limit)
      .populate(includes)
      .exec();

    return {
      docs,
      totalDocs,
      totalPages,
      currentPage: page,
      hasNextPage,
      hasPrevPage,
      nextPage,
      prevPage,
    };
  },

  async update(model, { query, update }) {
    return await model.findOneAndUpdate(query, update, { new: true }).exec();
  },

  async delete(model, { query }) {
    return await model.findOneAndDelete(query).exec();
  },
};
Leave a Comment