File size: 2,039 Bytes
484fdbc
dd1edf0
484fdbc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd1edf0
 
 
 
 
484fdbc
 
 
 
 
 
 
 
 
dd1edf0
484fdbc
 
dd1edf0
 
484fdbc
dd1edf0
484fdbc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { HttpError } from "@lib/error-handling/http-error";
import { populate } from "dotenv";
import { AnyKeys, Document, FilterQuery, Model } from "mongoose";

export const CrudService = <ModelDoc extends Document>(
  model: Model<ModelDoc>
) => {
  return class CrudServiceClass {
    protected model: Model<ModelDoc> = model;

    async create(data: AnyKeys<ModelDoc>): Promise<ModelDoc> {
      return this.model.create(data);
    }

    async update(
      filter: FilterQuery<ModelDoc>,
      data: AnyKeys<ModelDoc>
    ): Promise<ModelDoc> {
      return this.model.findOneAndUpdate(filter, data, { new: true });
    }

    async delete(filter: FilterQuery<ModelDoc>): Promise<ModelDoc> {
      return this.model.findOneAndDelete(filter);
    }

    async list(
      filter: FilterQuery<ModelDoc>,
      paginationOptions: {
        limit?: number;
        skip?: number;
      } = {
          limit: 10,
          skip: 0,
        },
      options?: {
        populateObject: any
      }
    ): Promise<{
      docs: ModelDoc[];
      paginationData: {
        total: number;
        page: number;
        perPage: number;
      };
    }> {
      const queryInstruction = this.model
        .find(filter)
        .limit(paginationOptions.limit)
        .skip(paginationOptions.skip)
      if (options?.populateObject) queryInstruction.populate(options.populateObject);

      const docs = await queryInstruction
      const total = await this.model.countDocuments(filter);
      const paginationData = {
        total: total,
        page: paginationOptions.skip,
        perPage: paginationOptions.limit,
      };

      return { docs, paginationData };
    }

    async findOne(filter: FilterQuery<ModelDoc>): Promise<ModelDoc | null> {
      return this.model.findOne(filter);
    }

    async findOneOrFail(filter: FilterQuery<ModelDoc>): Promise<ModelDoc> {
      const document = await this.findOne(filter);
      if (!document) throw new HttpError(404, "No Matching Result Found.");

      return document;
    }
  };
};