/
base_repository.ts
132 lines (121 loc) · 4.24 KB
/
base_repository.ts
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { injectable, unmanaged } from "inversify";
import { Document, Model } from "mongoose";
import {
IBaseRepository,
Query
} from "../../../domain/interfaces/repositories";
import BaseEntity from "../../../domain/model/base";
@injectable()
export class BaseRepository<
TEntity extends BaseEntity<TEntity>,
TModel extends Document
> implements IBaseRepository<TEntity> {
protected Model: Model<TModel>;
public constructor(@unmanaged() model: Model<TModel>) {
this.Model = model;
}
// We wrap the mongoose API here so we can use async / await
public async findAll() {
return new Promise<TEntity[]>((resolve, reject) => {
this.Model.find((err, res) => {
if (err) return reject(err);
let results = res.map(r => this.readMapper(r));
results = results.filter(r => !r.isDeleted);
resolve(results);
});
});
}
public async findById(id: string) {
return new Promise<TEntity>((resolve, reject) => {
this.Model.findById(id, (err, res) => {
if (err) return reject(err);
if (!res) return reject();
const result = this.readMapper(res);
resolve(result.isDeleted ? undefined : result);
});
});
}
public async save(doc: TEntity): Promise<TEntity> {
return new Promise<TEntity>((resolve, reject) => {
if (doc.id) {
this.Model.findByIdAndUpdate(
doc.id,
doc,
{ new: true },
(err, res) => {
if (err) return reject(err);
resolve(this.readMapper(res as TModel));
}
);
} else {
const instance = new this.Model(doc);
instance.save((err, res) => {
if (err) return reject(err);
resolve(this.readMapper(res));
});
}
});
}
public findManyById(ids: string[]) {
return new Promise<TEntity[]>((resolve, reject) => {
const query = { _id: { $in: ids } };
this.Model.find(query, (err, res) => {
if (err) return reject(err);
let results = res.map(r => this.readMapper(r));
results = results.filter(r => !r.isDeleted);
resolve(results);
});
});
}
public findManyByQuery(query: Query<TEntity>) {
return new Promise<TEntity[]>((resolve, reject) => {
this.Model.find(query as any, (err, res) => {
if (err) return reject(err);
if (!res) return resolve();
let result = res.map(r => this.readMapper(r));
result = result.filter(r => !r.isDeleted);
resolve(result);
});
});
}
public findOneByQuery(query: Query<TEntity>) {
return new Promise<TEntity>((resolve, reject) => {
this.Model.findOne(query as any, (err, res) => {
if (err) return reject(err);
if (!res) return resolve();
else {
const result = this.readMapper(res);
resolve(result.isDeleted ? undefined : result);
}
});
});
}
/**
* Maps '_id' from mongodb to 'id' of TEntity
*
* @private
* @param {TModel} model
* @returns {TEntity}
* @memberof BaseRepository
*/
private readMapper(model: TModel): TEntity {
const obj: any = model.toJSON();
const propDesc = Object.getOwnPropertyDescriptor(
obj,
"_id"
) as PropertyDescriptor;
Object.defineProperty(obj, "id", propDesc);
delete obj["_id"];
return obj as TEntity;
}
// private writeMapper(doc: TEntity): TEntity {
// const obj: any = JSON.parse(JSON.stringify(doc));
// const propDesc = Object.getOwnPropertyDescriptor(
// obj,
// "id"
// ) as PropertyDescriptor;
// Object.defineProperty(obj, "_id", propDesc);
// delete obj["id"];
// return obj as TEntity;
// }
}