forked from weisjohn/mongoose-deleted
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
85 lines (67 loc) · 2.34 KB
/
index.js
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
module.exports = function(schema, options) {
// default options
if (typeof options !== "object")
options = { select : false, history : false, toJSON : false };
// add the schema path
schema.add({
deleted: {
type: Boolean,
default: false,
select: options.select
}
});
// generate methods on schema
function action(name, bool) {
schema.methods[name] = function(fn) {
this.deleted = bool;
// integration with mongoose-history
if (options.history && Array.isArray(this.history))
this.history.push({ status: name + 'd' });
this.save(fn);
};
}
action('delete', true);
action('restore', false);
// allow finds to be simple
schema.pre('find', soft_delete_middleware);
schema.pre('findOne', soft_delete_middleware);
schema.pre('findOneAndUpdate', soft_delete_middleware);
schema.pre('count', soft_delete_middleware);
// hide the deleted field on toJSON calls
if (!schema.options.toJSON) schema.options.toJSON = {};
// store reference to previous transform
var fn = schema.options.toJSON.transform || function() { };
schema.options.toJSON.transform = function (doc, ret, opts) {
// allow overrides in the toJSON call
var del = options.toJSON;
if (typeof opts.deleted !== 'undefined') del = opts.deleted;
if (!del) { delete ret.deleted; }
// call next transform
fn(doc, ret, opts);
};
};
// detect if a "deleted" key is on the object
function detect_deleted(obj) {
var detected = false;
Object.keys(obj).forEach(function(key) {
if (key === "deleted") detected = true;
});
return detected;
}
// middleware to faciliate soft-delete finds
function soft_delete_middleware(next) {
var cons = this._conditions, add_clause = true;
// if the supplied query has specified any type of deleted, don't add
if (detect_deleted(cons)) {
add_clause = false;
} else {
["$or", "$and"].forEach(function(key) {
if (!cons[key] || !Array.isArray(cons[key])) return;
cons[key].forEach(function(con) {
if (detect_deleted(con)) add_clause = false;
});
});
}
if (add_clause) this.find({ deleted : false });
next();
}