@bedrockio/model 0.1.33 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +323 -109
- package/dist/cjs/const.js +2 -4
- package/dist/cjs/delete-hooks.js +351 -0
- package/dist/cjs/disallowed.js +0 -14
- package/dist/cjs/env.js +1 -2
- package/dist/cjs/include.js +1 -2
- package/dist/cjs/query.js +21 -0
- package/dist/cjs/schema.js +6 -3
- package/dist/cjs/search.js +12 -23
- package/dist/cjs/serialization.js +5 -3
- package/dist/cjs/soft-delete.js +226 -51
- package/dist/cjs/validation.js +1 -2
- package/package.json +5 -5
- package/src/delete-hooks.js +343 -0
- package/src/disallowed.js +0 -29
- package/src/query.js +15 -0
- package/src/schema.js +9 -4
- package/src/search.js +15 -27
- package/src/serialization.js +5 -1
- package/src/soft-delete.js +248 -55
- package/types/delete-hooks.d.ts +2 -0
- package/types/delete-hooks.d.ts.map +1 -0
- package/types/disallowed.d.ts.map +1 -1
- package/types/load.d.ts +67 -1
- package/types/load.d.ts.map +1 -1
- package/types/query.d.ts +2 -0
- package/types/query.d.ts.map +1 -0
- package/types/schema.d.ts +15 -9
- package/types/schema.d.ts.map +1 -1
- package/types/search.d.ts.map +1 -1
- package/types/serialization.d.ts.map +1 -1
- package/types/soft-delete.d.ts.map +1 -1
- package/types/testing.d.ts +1 -1
- package/types/testing.d.ts.map +1 -1
- package/dist/cjs/references.js +0 -104
- package/src/references.js +0 -101
package/dist/cjs/soft-delete.js
CHANGED
|
@@ -6,9 +6,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.applySoftDelete = applySoftDelete;
|
|
7
7
|
exports.assertUnique = assertUnique;
|
|
8
8
|
exports.hasUniqueConstraints = hasUniqueConstraints;
|
|
9
|
+
var _lodash = require("lodash");
|
|
10
|
+
var _query = require("./query");
|
|
9
11
|
function applySoftDelete(schema) {
|
|
10
12
|
applyQueries(schema);
|
|
11
13
|
applyUniqueConstraints(schema);
|
|
14
|
+
applyHookPatch(schema);
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
// Soft Delete Querying
|
|
@@ -48,124 +51,142 @@ function applyQueries(schema) {
|
|
|
48
51
|
|
|
49
52
|
// Static Methods
|
|
50
53
|
|
|
51
|
-
schema.static('deleteOne',
|
|
54
|
+
schema.static('deleteOne', function deleteOne(filter, ...rest) {
|
|
52
55
|
const update = getDelete();
|
|
53
|
-
const
|
|
54
|
-
return {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const query = this.updateOne(filter, update, ...omitCallback(rest));
|
|
57
|
+
return (0, _query.wrapQuery)(query, async promise => {
|
|
58
|
+
const res = await promise;
|
|
59
|
+
return {
|
|
60
|
+
acknowledged: res.acknowledged,
|
|
61
|
+
deletedCount: res.modifiedCount
|
|
62
|
+
};
|
|
63
|
+
});
|
|
58
64
|
});
|
|
59
|
-
schema.static('deleteMany',
|
|
65
|
+
schema.static('deleteMany', function deleteMany(filter, ...rest) {
|
|
60
66
|
const update = getDelete();
|
|
61
|
-
const
|
|
62
|
-
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
const query = this.updateMany(filter, update, ...omitCallback(rest));
|
|
68
|
+
return (0, _query.wrapQuery)(query, async promise => {
|
|
69
|
+
const res = await promise;
|
|
70
|
+
return {
|
|
71
|
+
acknowledged: res.acknowledged,
|
|
72
|
+
deletedCount: res.modifiedCount
|
|
73
|
+
};
|
|
74
|
+
});
|
|
66
75
|
});
|
|
67
|
-
schema.static('findOneAndDelete',
|
|
68
|
-
return
|
|
76
|
+
schema.static('findOneAndDelete', function findOneAndDelete(filter, ...rest) {
|
|
77
|
+
return this.findOneAndUpdate(filter, getDelete(), ...omitCallback(rest));
|
|
69
78
|
});
|
|
70
|
-
schema.static('restoreOne',
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
schema.static('restoreOne', function restoreOne(filter, ...rest) {
|
|
80
|
+
const query = this.updateOne(filter, getRestore(), ...omitCallback(rest));
|
|
81
|
+
return (0, _query.wrapQuery)(query, async promise => {
|
|
82
|
+
const res = await promise;
|
|
83
|
+
return {
|
|
84
|
+
acknowledged: res.acknowledged,
|
|
85
|
+
restoredCount: res.modifiedCount
|
|
86
|
+
};
|
|
87
|
+
});
|
|
77
88
|
});
|
|
78
|
-
schema.static('restoreMany',
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
schema.static('restoreMany', function restoreMany(filter, ...rest) {
|
|
90
|
+
const query = this.updateMany(filter, getRestore(), ...omitCallback(rest));
|
|
91
|
+
return (0, _query.wrapQuery)(query, async promise => {
|
|
92
|
+
const res = await promise;
|
|
93
|
+
return {
|
|
94
|
+
acknowledged: res.acknowledged,
|
|
95
|
+
restoredCount: res.modifiedCount
|
|
96
|
+
};
|
|
97
|
+
});
|
|
85
98
|
});
|
|
86
|
-
schema.static('destroyOne',
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
schema.static('destroyOne', function destroyOne(conditions, ...rest) {
|
|
100
|
+
// Following Mongoose patterns here
|
|
101
|
+
const query = new this.Query({}, {}, this, this.collection).deleteOne(conditions, ...omitCallback(rest));
|
|
102
|
+
return (0, _query.wrapQuery)(query, async promise => {
|
|
103
|
+
const res = await promise;
|
|
104
|
+
return {
|
|
105
|
+
acknowledged: res.acknowledged,
|
|
106
|
+
destroyedCount: res.deletedCount
|
|
107
|
+
};
|
|
108
|
+
});
|
|
92
109
|
});
|
|
93
|
-
schema.static('destroyMany',
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
110
|
+
schema.static('destroyMany', function destroyMany(conditions, ...rest) {
|
|
111
|
+
// Following Mongoose patterns here
|
|
112
|
+
const query = new this.Query({}, {}, this, this.collection).deleteMany(conditions, ...omitCallback(rest));
|
|
113
|
+
return (0, _query.wrapQuery)(query, async promise => {
|
|
114
|
+
const res = await promise;
|
|
115
|
+
return {
|
|
116
|
+
acknowledged: res.acknowledged,
|
|
117
|
+
destroyedCount: res.deletedCount
|
|
118
|
+
};
|
|
119
|
+
});
|
|
99
120
|
});
|
|
100
121
|
schema.static('findDeleted', function findDeleted(filter, ...rest) {
|
|
101
122
|
filter = {
|
|
102
123
|
...filter,
|
|
103
124
|
deleted: true
|
|
104
125
|
};
|
|
105
|
-
return this.find(filter, ...rest);
|
|
126
|
+
return this.find(filter, ...omitCallback(rest));
|
|
106
127
|
});
|
|
107
128
|
schema.static('findOneDeleted', function findOneDeleted(filter, ...rest) {
|
|
108
129
|
filter = {
|
|
109
130
|
...filter,
|
|
110
131
|
deleted: true
|
|
111
132
|
};
|
|
112
|
-
return this.findOne(filter, ...rest);
|
|
133
|
+
return this.findOne(filter, ...omitCallback(rest));
|
|
113
134
|
});
|
|
114
135
|
schema.static('findByIdDeleted', function findByIdDeleted(id, ...rest) {
|
|
115
136
|
const filter = {
|
|
116
137
|
_id: id,
|
|
117
138
|
deleted: true
|
|
118
139
|
};
|
|
119
|
-
return this.findOne(filter, ...rest);
|
|
140
|
+
return this.findOne(filter, ...omitCallback(rest));
|
|
120
141
|
});
|
|
121
142
|
schema.static('existsDeleted', function existsDeleted(filter, ...rest) {
|
|
122
143
|
filter = {
|
|
123
144
|
...filter,
|
|
124
145
|
deleted: true
|
|
125
146
|
};
|
|
126
|
-
return this.exists(filter, ...rest);
|
|
147
|
+
return this.exists(filter, ...omitCallback(rest));
|
|
127
148
|
});
|
|
128
149
|
schema.static('countDocumentsDeleted', function countDocumentsDeleted(filter, ...rest) {
|
|
129
150
|
filter = {
|
|
130
151
|
...filter,
|
|
131
152
|
deleted: true
|
|
132
153
|
};
|
|
133
|
-
return this.countDocuments(filter, ...rest);
|
|
154
|
+
return this.countDocuments(filter, ...omitCallback(rest));
|
|
134
155
|
});
|
|
135
156
|
schema.static('findWithDeleted', function findWithDeleted(filter, ...rest) {
|
|
136
157
|
filter = {
|
|
137
158
|
...filter,
|
|
138
159
|
...getWithDeletedQuery()
|
|
139
160
|
};
|
|
140
|
-
return this.find(filter, ...rest);
|
|
161
|
+
return this.find(filter, ...omitCallback(rest));
|
|
141
162
|
});
|
|
142
163
|
schema.static('findOneWithDeleted', function findOneWithDeleted(filter, ...rest) {
|
|
143
164
|
filter = {
|
|
144
165
|
...filter,
|
|
145
166
|
...getWithDeletedQuery()
|
|
146
167
|
};
|
|
147
|
-
return this.findOne(filter, ...rest);
|
|
168
|
+
return this.findOne(filter, ...omitCallback(rest));
|
|
148
169
|
});
|
|
149
170
|
schema.static('findByIdWithDeleted', function findByIdWithDeleted(id, ...rest) {
|
|
150
171
|
const filter = {
|
|
151
172
|
_id: id,
|
|
152
173
|
...getWithDeletedQuery()
|
|
153
174
|
};
|
|
154
|
-
return this.findOne(filter, ...rest);
|
|
175
|
+
return this.findOne(filter, ...omitCallback(rest));
|
|
155
176
|
});
|
|
156
177
|
schema.static('existsWithDeleted', function existsWithDeleted(filter, ...rest) {
|
|
157
178
|
filter = {
|
|
158
179
|
...filter,
|
|
159
180
|
...getWithDeletedQuery()
|
|
160
181
|
};
|
|
161
|
-
return this.exists(filter, ...rest);
|
|
182
|
+
return this.exists(filter, ...omitCallback(rest));
|
|
162
183
|
});
|
|
163
184
|
schema.static('countDocumentsWithDeleted', function countDocumentsWithDeleted(filter, ...rest) {
|
|
164
185
|
filter = {
|
|
165
186
|
...filter,
|
|
166
187
|
...getWithDeletedQuery()
|
|
167
188
|
};
|
|
168
|
-
return this.countDocuments(filter, ...rest);
|
|
189
|
+
return this.countDocuments(filter, ...omitCallback(rest));
|
|
169
190
|
});
|
|
170
191
|
}
|
|
171
192
|
function getDelete() {
|
|
@@ -368,4 +389,158 @@ function getCollisions(obj1, obj2) {
|
|
|
368
389
|
return collisions;
|
|
369
390
|
}
|
|
370
391
|
|
|
371
|
-
//
|
|
392
|
+
// Hook Patch
|
|
393
|
+
|
|
394
|
+
function applyHookPatch(schema) {
|
|
395
|
+
const schemaPre = schema.pre;
|
|
396
|
+
const schemaPost = schema.post;
|
|
397
|
+
schema.pre = function (name, fn) {
|
|
398
|
+
if (name === 'restore') {
|
|
399
|
+
// Document hooks
|
|
400
|
+
schemaPre.call(this, 'save', getPreDocRestore(fn));
|
|
401
|
+
} else if (name === 'deleteOne') {
|
|
402
|
+
// Query Hooks
|
|
403
|
+
schemaPre.call(this, 'updateOne', getPreDelete(fn));
|
|
404
|
+
} else if (name === 'deleteMany') {
|
|
405
|
+
schemaPre.call(this, 'updateMany', getPreDelete(fn));
|
|
406
|
+
} else if (name === 'findOneAndDelete') {
|
|
407
|
+
schemaPre.call(this, 'findOneAndUpdate', getPreDelete(fn));
|
|
408
|
+
} else if (name === 'restoreOne') {
|
|
409
|
+
schemaPre.call(this, 'updateOne', getPreRestore(fn));
|
|
410
|
+
} else if (name === 'restoreMany') {
|
|
411
|
+
schemaPre.call(this, 'updateMany', getPreRestore(fn));
|
|
412
|
+
} else if (name === 'destroyOne') {
|
|
413
|
+
schemaPre.call(this, 'deleteOne', getPre(fn));
|
|
414
|
+
} else if (name === 'destroyMany') {
|
|
415
|
+
schemaPre.call(this, 'deleteMany', getPre(fn));
|
|
416
|
+
} else if (name === 'findDeleted') {
|
|
417
|
+
schemaPre.call(this, 'find', getPreDeleted(fn));
|
|
418
|
+
} else if (name === 'findOneDeleted') {
|
|
419
|
+
schemaPre.call(this, 'findOne', getPreDeleted(fn));
|
|
420
|
+
} else if (name === 'countDocumentsDeleted') {
|
|
421
|
+
schemaPre.call(this, 'countDocuments', getPreDeleted(fn));
|
|
422
|
+
} else if (name === 'findWithDeleted') {
|
|
423
|
+
schemaPre.call(this, 'find', getPreWithDeleted(fn));
|
|
424
|
+
} else if (name === 'findOneWithDeleted') {
|
|
425
|
+
schemaPre.call(this, 'findOne', getPreWithDeleted(fn));
|
|
426
|
+
} else if (name === 'countDocumentsWithDeleted') {
|
|
427
|
+
schemaPre.call(this, 'countDocuments', getPreWithDeleted(fn));
|
|
428
|
+
} else {
|
|
429
|
+
schemaPre.apply(this, arguments);
|
|
430
|
+
}
|
|
431
|
+
return this;
|
|
432
|
+
};
|
|
433
|
+
schema.post = function (name, fn) {
|
|
434
|
+
if (name === 'deleteOne') {
|
|
435
|
+
schemaPost.call(this, 'updateOne', getPostDelete(fn));
|
|
436
|
+
} else if (name === 'deleteMany') {
|
|
437
|
+
schemaPost.call(this, 'updateMany', getPostDelete(fn));
|
|
438
|
+
} else if (name === 'findOneAndDelete') {
|
|
439
|
+
schemaPost.call(this, 'findOneAndUpdate', getPostDelete(fn));
|
|
440
|
+
} else if (name === 'restoreOne') {
|
|
441
|
+
schemaPost.call(this, 'updateOne', getPostRestore(fn));
|
|
442
|
+
} else if (name === 'restoreMany') {
|
|
443
|
+
schemaPost.call(this, 'updateMany', getPostRestore(fn));
|
|
444
|
+
} else if (name === 'destroyOne') {
|
|
445
|
+
schemaPost.call(this, 'deleteOne', getPost(fn));
|
|
446
|
+
} else if (name === 'destroyMany') {
|
|
447
|
+
schemaPost.call(this, 'deleteMany', getPost(fn));
|
|
448
|
+
} else if (name === 'findDeleted') {
|
|
449
|
+
schemaPost.call(this, 'find', getPostDeleted(fn));
|
|
450
|
+
} else if (name === 'findOneDeleted') {
|
|
451
|
+
schemaPost.call(this, 'findOne', getPostDeleted(fn));
|
|
452
|
+
} else if (name === 'countDocumentsDeleted') {
|
|
453
|
+
schemaPost.call(this, 'countDocuments', getPostDeleted(fn));
|
|
454
|
+
} else if (name === 'findWithDeleted') {
|
|
455
|
+
schemaPost.call(this, 'find', getPostWithDeleted(fn));
|
|
456
|
+
} else if (name === 'findOneWithDeleted') {
|
|
457
|
+
schemaPost.call(this, 'findOne', getPostWithDeleted(fn));
|
|
458
|
+
} else if (name === 'countDocumentsWithDeleted') {
|
|
459
|
+
schemaPost.call(this, 'countDocuments', getPostWithDeleted(fn));
|
|
460
|
+
} else {
|
|
461
|
+
schemaPost.apply(this, arguments);
|
|
462
|
+
}
|
|
463
|
+
return this;
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Needs to be separated as hooks check arity to
|
|
468
|
+
// determine the arguments to pass.
|
|
469
|
+
|
|
470
|
+
function getPre(fn, check) {
|
|
471
|
+
return function (next) {
|
|
472
|
+
runHook(this, fn, check, next, arguments);
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function getPost(fn, check) {
|
|
476
|
+
return function (res, next) {
|
|
477
|
+
runHook(this, fn, check, next, arguments);
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
function runHook(query, fn, check, next, args) {
|
|
481
|
+
if (!check || check(query)) {
|
|
482
|
+
const ret = fn.apply(query, args);
|
|
483
|
+
if (ret instanceof Promise) {
|
|
484
|
+
ret.finally(next);
|
|
485
|
+
}
|
|
486
|
+
} else {
|
|
487
|
+
next();
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function getPreDelete(fn) {
|
|
491
|
+
return getPre(fn, query => {
|
|
492
|
+
return query.get('deleted') === true;
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function getPreRestore(fn) {
|
|
496
|
+
return getPre(fn, query => {
|
|
497
|
+
return query.get('deleted') === false;
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
function getPreDeleted(fn) {
|
|
501
|
+
return getPre(fn, query => {
|
|
502
|
+
return query.getFilter().deleted === true;
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
function getPreWithDeleted(fn) {
|
|
506
|
+
return getPre(fn, query => {
|
|
507
|
+
return (0, _lodash.isEqual)(query.getFilter().deleted, getWithDeletedQuery().deleted);
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
function getPreDocRestore(fn) {
|
|
511
|
+
return getPre(fn, doc => {
|
|
512
|
+
return doc.isModified('deleted') && doc.deleted === false;
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
function getPostDelete(fn) {
|
|
516
|
+
return getPost(fn, query => {
|
|
517
|
+
return query.get('deleted') === true;
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
function getPostRestore(fn) {
|
|
521
|
+
return getPost(fn, query => {
|
|
522
|
+
return query.get('deleted') === false;
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
function getPostDeleted(fn) {
|
|
526
|
+
return getPost(fn, query => {
|
|
527
|
+
return query.getFilter().deleted === true;
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function getPostWithDeleted(fn) {
|
|
531
|
+
return getPost(fn, query => {
|
|
532
|
+
return (0, _lodash.isEqual)(query.getFilter().deleted, getWithDeletedQuery().deleted);
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Utils
|
|
537
|
+
|
|
538
|
+
// Mongoose >= v7 no longer accepts a callback for queries,
|
|
539
|
+
// however it still passes post hooks to static methods for
|
|
540
|
+
// some reason (this appears to be a bug), so omit functions
|
|
541
|
+
// here to allow projectsion/options to still be passed.
|
|
542
|
+
function omitCallback(args) {
|
|
543
|
+
return args.filter(arg => {
|
|
544
|
+
return typeof arg !== 'function';
|
|
545
|
+
});
|
|
546
|
+
}
|
package/dist/cjs/validation.js
CHANGED
|
@@ -23,11 +23,10 @@ const DATE_TAGS = {
|
|
|
23
23
|
'x-schema': 'DateTime',
|
|
24
24
|
'x-description': 'A `string` in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.'
|
|
25
25
|
};
|
|
26
|
-
const OBJECT_ID_SCHEMA = _yada.default.string().mongo().message('Must be an ObjectId.').tag({
|
|
26
|
+
const OBJECT_ID_SCHEMA = exports.OBJECT_ID_SCHEMA = _yada.default.string().mongo().message('Must be an ObjectId.').tag({
|
|
27
27
|
'x-schema': 'ObjectId',
|
|
28
28
|
'x-description': 'A 24 character hexadecimal string representing a Mongo [ObjectId](https://bit.ly/3YPtGlU).'
|
|
29
29
|
});
|
|
30
|
-
exports.OBJECT_ID_SCHEMA = OBJECT_ID_SCHEMA;
|
|
31
30
|
const REFERENCE_SCHEMA = _yada.default.allow(OBJECT_ID_SCHEMA, _yada.default.object({
|
|
32
31
|
id: OBJECT_ID_SCHEMA.required()
|
|
33
32
|
}).options({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bedrockio/model",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Bedrock utilities for model creation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"@bedrockio/yada": "^1.0.33",
|
|
33
|
-
"mongoose": "
|
|
33
|
+
"mongoose": "^6.9.0 || ^7.6.4"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@babel/cli": "^7.20.7",
|
|
@@ -38,14 +38,14 @@
|
|
|
38
38
|
"@babel/preset-env": "^7.20.2",
|
|
39
39
|
"@bedrockio/prettier-config": "^1.0.2",
|
|
40
40
|
"@bedrockio/yada": "^1.0.33",
|
|
41
|
-
"@shelf/jest-mongodb": "^4.1.
|
|
41
|
+
"@shelf/jest-mongodb": "^4.1.7",
|
|
42
42
|
"babel-plugin-import-replacement": "^1.0.1",
|
|
43
43
|
"eslint": "^8.33.0",
|
|
44
44
|
"eslint-plugin-bedrock": "^1.0.26",
|
|
45
45
|
"jest": "^29.4.1",
|
|
46
46
|
"jest-environment-node": "^29.4.1",
|
|
47
|
-
"mongodb": "
|
|
48
|
-
"mongoose": "^6.
|
|
47
|
+
"mongodb": "^5.9.1",
|
|
48
|
+
"mongoose": "^7.6.4",
|
|
49
49
|
"prettier-eslint": "^15.0.1",
|
|
50
50
|
"typescript": "^4.9.5"
|
|
51
51
|
},
|