ts-patch-mongoose 2.9.1 → 2.9.3
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/biome.json +24 -4
- package/dist/index.cjs +39 -40
- package/dist/index.d.cts +7 -20
- package/dist/index.d.mts +7 -20
- package/dist/index.mjs +39 -40
- package/package.json +14 -14
- package/src/helpers.ts +0 -1
- package/src/hooks/delete-hooks.ts +4 -5
- package/src/hooks/update-hooks.ts +10 -11
- package/src/index.ts +5 -10
- package/src/model.ts +1 -1
- package/src/patch.ts +13 -14
- package/tests/helpers.test.ts +2 -3
- package/tests/mongo/server.ts +1 -2
- package/tests/patch.test.ts +4 -7
- package/tests/plugin-event-created.test.ts +4 -6
- package/tests/plugin-event-deleted.test.ts +2 -4
- package/tests/plugin-event-updated.test.ts +3 -5
- package/tests/plugin-global.test.ts +4 -6
- package/tests/plugin-omit-all.test.ts +3 -5
- package/tests/plugin-patch-history-disabled.test.ts +3 -5
- package/tests/plugin-pre-delete.test.ts +2 -4
- package/tests/plugin-pre-save.test.ts +2 -5
- package/tests/plugin.test.ts +3 -5
- package/vite.config.mts +11 -1
package/biome.json
CHANGED
|
@@ -1,16 +1,36 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.2.7/schema.json",
|
|
3
3
|
"vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false },
|
|
4
4
|
"files": {
|
|
5
5
|
"ignoreUnknown": false,
|
|
6
|
-
"
|
|
6
|
+
"includes": ["src/**/*.ts", "tests/**/*.ts"]
|
|
7
7
|
},
|
|
8
8
|
"formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
|
|
9
|
-
"
|
|
9
|
+
"assist": {
|
|
10
|
+
"actions": {
|
|
11
|
+
"source": {
|
|
12
|
+
"organizeImports": {
|
|
13
|
+
"level": "on",
|
|
14
|
+
"options": {
|
|
15
|
+
"groups": [
|
|
16
|
+
"vitest",
|
|
17
|
+
":BLANK_LINE:",
|
|
18
|
+
":NODE:",
|
|
19
|
+
{ "type": false },
|
|
20
|
+
":BLANK_LINE:"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
10
27
|
"linter": {
|
|
11
28
|
"enabled": true,
|
|
12
29
|
"rules": {
|
|
13
|
-
"recommended": true
|
|
30
|
+
"recommended": true,
|
|
31
|
+
"correctness": {
|
|
32
|
+
"noUnusedVariables": "off"
|
|
33
|
+
}
|
|
14
34
|
}
|
|
15
35
|
},
|
|
16
36
|
"javascript": {
|
package/dist/index.cjs
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var EventEmitter = require('node:events');
|
|
3
|
+
var lodashEs = require('lodash-es');
|
|
5
4
|
var ms = require('ms');
|
|
6
5
|
var mongoose = require('mongoose');
|
|
7
6
|
var jsonpatch = require('fast-json-patch');
|
|
8
7
|
var omit = require('omit-deep');
|
|
9
|
-
var
|
|
8
|
+
var EventEmitter = require('node:events');
|
|
10
9
|
var powerAssign = require('power-assign');
|
|
11
|
-
|
|
12
|
-
class PatchEventEmitter extends EventEmitter {
|
|
13
|
-
}
|
|
14
|
-
const em = new PatchEventEmitter();
|
|
10
|
+
var semver = require('semver');
|
|
15
11
|
|
|
16
12
|
const HistorySchema = new mongoose.Schema(
|
|
17
13
|
{
|
|
@@ -92,6 +88,10 @@ const setPatchHistoryTTL = async (ttl) => {
|
|
|
92
88
|
}
|
|
93
89
|
};
|
|
94
90
|
|
|
91
|
+
class PatchEventEmitter extends EventEmitter {
|
|
92
|
+
}
|
|
93
|
+
const em = new PatchEventEmitter();
|
|
94
|
+
|
|
95
95
|
function isPatchHistoryEnabled(opts, context) {
|
|
96
96
|
return !opts.patchHistoryDisabled && !context.ignorePatchHistory;
|
|
97
97
|
}
|
|
@@ -104,24 +104,24 @@ function getJsonOmit(opts, doc) {
|
|
|
104
104
|
}
|
|
105
105
|
function getObjectOmit(opts, doc) {
|
|
106
106
|
if (opts.omit) {
|
|
107
|
-
return omit(
|
|
107
|
+
return omit(lodashEs.isFunction(doc?.toObject) ? doc.toObject() : doc, opts.omit);
|
|
108
108
|
}
|
|
109
109
|
return doc;
|
|
110
110
|
}
|
|
111
111
|
async function getUser(opts, doc) {
|
|
112
|
-
if (
|
|
112
|
+
if (lodashEs.isFunction(opts.getUser)) {
|
|
113
113
|
return await opts.getUser(doc);
|
|
114
114
|
}
|
|
115
115
|
return void 0;
|
|
116
116
|
}
|
|
117
117
|
async function getReason(opts, doc) {
|
|
118
|
-
if (
|
|
118
|
+
if (lodashEs.isFunction(opts.getReason)) {
|
|
119
119
|
return await opts.getReason(doc);
|
|
120
120
|
}
|
|
121
121
|
return void 0;
|
|
122
122
|
}
|
|
123
123
|
async function getMetadata(opts, doc) {
|
|
124
|
-
if (
|
|
124
|
+
if (lodashEs.isFunction(opts.getMetadata)) {
|
|
125
125
|
return await opts.getMetadata(doc);
|
|
126
126
|
}
|
|
127
127
|
return void 0;
|
|
@@ -144,11 +144,11 @@ async function bulkPatch(opts, context, eventKey, docsKey) {
|
|
|
144
144
|
const event = opts[eventKey];
|
|
145
145
|
const docs = context[docsKey];
|
|
146
146
|
const key = eventKey === "eventCreated" ? "doc" : "oldDoc";
|
|
147
|
-
if (
|
|
148
|
-
const chunks =
|
|
149
|
-
for
|
|
147
|
+
if (lodashEs.isEmpty(docs) || !event && !history) return;
|
|
148
|
+
const chunks = lodashEs.chunk(docs, 1e3);
|
|
149
|
+
for (const chunk2 of chunks) {
|
|
150
150
|
const bulk = [];
|
|
151
|
-
for (const doc of
|
|
151
|
+
for (const doc of chunk2) {
|
|
152
152
|
emitEvent(context, event, { [key]: doc });
|
|
153
153
|
if (history) {
|
|
154
154
|
const [user, reason, metadata] = await getData(opts, doc);
|
|
@@ -169,7 +169,7 @@ async function bulkPatch(opts, context, eventKey, docsKey) {
|
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
|
-
if (history && !
|
|
172
|
+
if (history && !lodashEs.isEmpty(bulk)) {
|
|
173
173
|
await HistoryModel.bulkWrite(bulk, { ordered: false }).catch((error) => {
|
|
174
174
|
console.error(error.message);
|
|
175
175
|
});
|
|
@@ -183,9 +183,9 @@ async function updatePatch(opts, context, current, original) {
|
|
|
183
183
|
const history = isPatchHistoryEnabled(opts, context);
|
|
184
184
|
const currentObject = getJsonOmit(opts, current);
|
|
185
185
|
const originalObject = getJsonOmit(opts, original);
|
|
186
|
-
if (
|
|
186
|
+
if (lodashEs.isEmpty(originalObject) || lodashEs.isEmpty(currentObject)) return;
|
|
187
187
|
const patch = jsonpatch.compare(originalObject, currentObject, true);
|
|
188
|
-
if (
|
|
188
|
+
if (lodashEs.isEmpty(patch)) return;
|
|
189
189
|
emitEvent(context, opts.eventUpdated, { oldDoc: original, doc: current, patch });
|
|
190
190
|
if (history) {
|
|
191
191
|
let version = 0;
|
|
@@ -211,13 +211,6 @@ async function deletePatch(opts, context) {
|
|
|
211
211
|
await bulkPatch(opts, context, "eventDeleted", "deletedDocs");
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
const isMongooseLessThan8 = semver.satisfies(mongoose.version, "<8");
|
|
215
|
-
const isMongooseLessThan7 = semver.satisfies(mongoose.version, "<7");
|
|
216
|
-
const isMongoose6 = semver.satisfies(mongoose.version, "6");
|
|
217
|
-
if (isMongoose6) {
|
|
218
|
-
mongoose.set("strictQuery", false);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
214
|
const deleteMethods = ["remove", "findOneAndDelete", "findOneAndRemove", "findByIdAndDelete", "findByIdAndRemove", "deleteOne", "deleteMany"];
|
|
222
215
|
const deleteHooksInitialize = (schema, opts) => {
|
|
223
216
|
schema.pre(deleteMethods, { document: false, query: true }, async function() {
|
|
@@ -234,16 +227,16 @@ const deleteHooksInitialize = (schema, opts) => {
|
|
|
234
227
|
};
|
|
235
228
|
if (["remove", "deleteMany"].includes(this._context.op) && !options.single) {
|
|
236
229
|
const docs = await model.find(filter).lean().exec();
|
|
237
|
-
if (!
|
|
230
|
+
if (!lodashEs.isEmpty(docs)) {
|
|
238
231
|
this._context.deletedDocs = docs;
|
|
239
232
|
}
|
|
240
233
|
} else {
|
|
241
234
|
const doc = await model.findOne(filter).lean().exec();
|
|
242
|
-
if (!
|
|
235
|
+
if (!lodashEs.isEmpty(doc)) {
|
|
243
236
|
this._context.deletedDocs = [doc];
|
|
244
237
|
}
|
|
245
238
|
}
|
|
246
|
-
if (opts.preDelete &&
|
|
239
|
+
if (opts.preDelete && lodashEs.isArray(this._context.deletedDocs) && !lodashEs.isEmpty(this._context.deletedDocs)) {
|
|
247
240
|
await opts.preDelete(this._context.deletedDocs);
|
|
248
241
|
}
|
|
249
242
|
});
|
|
@@ -279,7 +272,7 @@ const saveHooksInitialize = (schema, opts) => {
|
|
|
279
272
|
const updateMethods = ["update", "updateOne", "replaceOne", "updateMany", "findOneAndUpdate", "findOneAndReplace", "findByIdAndUpdate"];
|
|
280
273
|
const assignUpdate = (document, update, commands) => {
|
|
281
274
|
let updated = powerAssign.assign(document.toObject(toObjectOptions), update);
|
|
282
|
-
|
|
275
|
+
lodashEs.forEach(commands, (command) => {
|
|
283
276
|
try {
|
|
284
277
|
updated = powerAssign.assign(updated, command);
|
|
285
278
|
} catch {
|
|
@@ -292,11 +285,11 @@ const assignUpdate = (document, update, commands) => {
|
|
|
292
285
|
const splitUpdateAndCommands = (updateQuery) => {
|
|
293
286
|
let update = {};
|
|
294
287
|
const commands = [];
|
|
295
|
-
if (!
|
|
296
|
-
update =
|
|
297
|
-
const keysWithDollarSign =
|
|
298
|
-
if (!
|
|
299
|
-
|
|
288
|
+
if (!lodashEs.isEmpty(updateQuery) && !lodashEs.isArray(updateQuery) && lodashEs.isObjectLike(updateQuery)) {
|
|
289
|
+
update = lodashEs.cloneDeep(updateQuery);
|
|
290
|
+
const keysWithDollarSign = lodashEs.keys(update).filter((key) => key.startsWith("$"));
|
|
291
|
+
if (!lodashEs.isEmpty(keysWithDollarSign)) {
|
|
292
|
+
lodashEs.forEach(keysWithDollarSign, (key) => {
|
|
300
293
|
commands.push({ [key]: update[key] });
|
|
301
294
|
delete update[key];
|
|
302
295
|
});
|
|
@@ -337,13 +330,13 @@ const updateHooksInitialize = (schema, opts) => {
|
|
|
337
330
|
let current = null;
|
|
338
331
|
const filter = this.getFilter();
|
|
339
332
|
const combined = assignUpdate(model.hydrate({}), update, commands);
|
|
340
|
-
if (!
|
|
333
|
+
if (!lodashEs.isEmpty(update) && !current) {
|
|
341
334
|
current = await model.findOne(update).sort("desc").lean().exec();
|
|
342
335
|
}
|
|
343
|
-
if (!
|
|
336
|
+
if (!lodashEs.isEmpty(combined) && !current) {
|
|
344
337
|
current = await model.findOne(combined).sort("desc").lean().exec();
|
|
345
338
|
}
|
|
346
|
-
if (!
|
|
339
|
+
if (!lodashEs.isEmpty(filter) && !current) {
|
|
347
340
|
console.log("filter", filter);
|
|
348
341
|
current = await model.findOne(filter).sort("desc").lean().exec();
|
|
349
342
|
}
|
|
@@ -354,8 +347,14 @@ const updateHooksInitialize = (schema, opts) => {
|
|
|
354
347
|
});
|
|
355
348
|
};
|
|
356
349
|
|
|
350
|
+
const isMongooseLessThan8 = semver.satisfies(mongoose.version, "<8");
|
|
351
|
+
const isMongooseLessThan7 = semver.satisfies(mongoose.version, "<7");
|
|
352
|
+
const isMongoose6 = semver.satisfies(mongoose.version, "6");
|
|
353
|
+
if (isMongoose6) {
|
|
354
|
+
mongoose.set("strictQuery", false);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
357
|
const remove = isMongooseLessThan7 ? "remove" : "deleteOne";
|
|
358
|
-
const patchEventEmitter = em;
|
|
359
358
|
const patchHistoryPlugin = function plugin(schema, opts) {
|
|
360
359
|
saveHooksInitialize(schema, opts);
|
|
361
360
|
updateHooksInitialize(schema, opts);
|
|
@@ -372,7 +371,7 @@ const patchHistoryPlugin = function plugin(schema, opts) {
|
|
|
372
371
|
if (isMongooseLessThan8) {
|
|
373
372
|
schema.pre(remove, { document: true, query: false }, async function() {
|
|
374
373
|
const original = this.toObject(toObjectOptions);
|
|
375
|
-
if (opts.preDelete && !
|
|
374
|
+
if (opts.preDelete && !lodashEs.isEmpty(original)) {
|
|
376
375
|
await opts.preDelete([original]);
|
|
377
376
|
}
|
|
378
377
|
});
|
|
@@ -390,6 +389,6 @@ const patchHistoryPlugin = function plugin(schema, opts) {
|
|
|
390
389
|
}
|
|
391
390
|
};
|
|
392
391
|
|
|
393
|
-
exports.patchEventEmitter =
|
|
392
|
+
exports.patchEventEmitter = em;
|
|
394
393
|
exports.patchHistoryPlugin = patchHistoryPlugin;
|
|
395
394
|
exports.setPatchHistoryTTL = setPatchHistoryTTL;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HydratedDocument, Types, Query, Schema } from 'mongoose';
|
|
2
2
|
import { Operation } from 'fast-json-patch';
|
|
3
|
+
import EventEmitter from 'node:events';
|
|
3
4
|
import ms from 'ms';
|
|
4
5
|
|
|
5
6
|
interface History {
|
|
@@ -49,27 +50,13 @@ interface PluginOptions<T> {
|
|
|
49
50
|
preDelete?: (docs: HydratedDocument<T>[]) => Promise<void>;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
declare
|
|
53
|
+
declare class PatchEventEmitter extends EventEmitter {
|
|
54
|
+
}
|
|
55
|
+
declare const em: PatchEventEmitter;
|
|
53
56
|
|
|
54
|
-
declare const
|
|
55
|
-
[EventEmitter.captureRejectionSymbol]?<K>(error: Error, event: string | symbol, ...args: any[]): void;
|
|
56
|
-
addListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
57
|
-
on<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
58
|
-
once<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
59
|
-
removeListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
60
|
-
off<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
61
|
-
removeAllListeners(eventName?: string | symbol | undefined): any;
|
|
62
|
-
setMaxListeners(n: number): any;
|
|
63
|
-
getMaxListeners(): number;
|
|
64
|
-
listeners<K>(eventName: string | symbol): Function[];
|
|
65
|
-
rawListeners<K>(eventName: string | symbol): Function[];
|
|
66
|
-
emit<K>(eventName: string | symbol, ...args: any[]): boolean;
|
|
67
|
-
listenerCount<K>(eventName: string | symbol, listener?: Function | undefined): number;
|
|
68
|
-
prependListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
69
|
-
prependOnceListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
70
|
-
eventNames(): (string | symbol)[];
|
|
71
|
-
};
|
|
57
|
+
declare const setPatchHistoryTTL: (ttl: number | ms.StringValue) => Promise<void>;
|
|
72
58
|
|
|
73
59
|
declare const patchHistoryPlugin: <T>(schema: Schema<T>, opts: PluginOptions<T>) => void;
|
|
74
60
|
|
|
75
|
-
export {
|
|
61
|
+
export { em as patchEventEmitter, patchHistoryPlugin, setPatchHistoryTTL };
|
|
62
|
+
export type { History, HookContext, Metadata, PatchContext, PatchEvent, PluginOptions, User };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HydratedDocument, Types, Query, Schema } from 'mongoose';
|
|
2
2
|
import { Operation } from 'fast-json-patch';
|
|
3
|
+
import EventEmitter from 'node:events';
|
|
3
4
|
import ms from 'ms';
|
|
4
5
|
|
|
5
6
|
interface History {
|
|
@@ -49,27 +50,13 @@ interface PluginOptions<T> {
|
|
|
49
50
|
preDelete?: (docs: HydratedDocument<T>[]) => Promise<void>;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
declare
|
|
53
|
+
declare class PatchEventEmitter extends EventEmitter {
|
|
54
|
+
}
|
|
55
|
+
declare const em: PatchEventEmitter;
|
|
53
56
|
|
|
54
|
-
declare const
|
|
55
|
-
[EventEmitter.captureRejectionSymbol]?<K>(error: Error, event: string | symbol, ...args: any[]): void;
|
|
56
|
-
addListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
57
|
-
on<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
58
|
-
once<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
59
|
-
removeListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
60
|
-
off<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
61
|
-
removeAllListeners(eventName?: string | symbol | undefined): any;
|
|
62
|
-
setMaxListeners(n: number): any;
|
|
63
|
-
getMaxListeners(): number;
|
|
64
|
-
listeners<K>(eventName: string | symbol): Function[];
|
|
65
|
-
rawListeners<K>(eventName: string | symbol): Function[];
|
|
66
|
-
emit<K>(eventName: string | symbol, ...args: any[]): boolean;
|
|
67
|
-
listenerCount<K>(eventName: string | symbol, listener?: Function | undefined): number;
|
|
68
|
-
prependListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
69
|
-
prependOnceListener<K>(eventName: string | symbol, listener: (...args: any[]) => void): any;
|
|
70
|
-
eventNames(): (string | symbol)[];
|
|
71
|
-
};
|
|
57
|
+
declare const setPatchHistoryTTL: (ttl: number | ms.StringValue) => Promise<void>;
|
|
72
58
|
|
|
73
59
|
declare const patchHistoryPlugin: <T>(schema: Schema<T>, opts: PluginOptions<T>) => void;
|
|
74
60
|
|
|
75
|
-
export {
|
|
61
|
+
export { em as patchEventEmitter, patchHistoryPlugin, setPatchHistoryTTL };
|
|
62
|
+
export type { History, HookContext, Metadata, PatchContext, PatchEvent, PluginOptions, User };
|
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import EventEmitter from 'node:events';
|
|
1
|
+
import { isEmpty, chunk, isFunction, isArray, isObjectLike, cloneDeep, keys, forEach } from 'lodash-es';
|
|
3
2
|
import ms from 'ms';
|
|
4
3
|
import mongoose, { Schema, model } from 'mongoose';
|
|
5
4
|
import jsonpatch from 'fast-json-patch';
|
|
6
5
|
import omit from 'omit-deep';
|
|
7
|
-
import
|
|
6
|
+
import EventEmitter from 'node:events';
|
|
8
7
|
import { assign } from 'power-assign';
|
|
9
|
-
|
|
10
|
-
class PatchEventEmitter extends EventEmitter {
|
|
11
|
-
}
|
|
12
|
-
const em = new PatchEventEmitter();
|
|
8
|
+
import { satisfies } from 'semver';
|
|
13
9
|
|
|
14
10
|
const HistorySchema = new Schema(
|
|
15
11
|
{
|
|
@@ -90,6 +86,10 @@ const setPatchHistoryTTL = async (ttl) => {
|
|
|
90
86
|
}
|
|
91
87
|
};
|
|
92
88
|
|
|
89
|
+
class PatchEventEmitter extends EventEmitter {
|
|
90
|
+
}
|
|
91
|
+
const em = new PatchEventEmitter();
|
|
92
|
+
|
|
93
93
|
function isPatchHistoryEnabled(opts, context) {
|
|
94
94
|
return !opts.patchHistoryDisabled && !context.ignorePatchHistory;
|
|
95
95
|
}
|
|
@@ -102,24 +102,24 @@ function getJsonOmit(opts, doc) {
|
|
|
102
102
|
}
|
|
103
103
|
function getObjectOmit(opts, doc) {
|
|
104
104
|
if (opts.omit) {
|
|
105
|
-
return omit(
|
|
105
|
+
return omit(isFunction(doc?.toObject) ? doc.toObject() : doc, opts.omit);
|
|
106
106
|
}
|
|
107
107
|
return doc;
|
|
108
108
|
}
|
|
109
109
|
async function getUser(opts, doc) {
|
|
110
|
-
if (
|
|
110
|
+
if (isFunction(opts.getUser)) {
|
|
111
111
|
return await opts.getUser(doc);
|
|
112
112
|
}
|
|
113
113
|
return void 0;
|
|
114
114
|
}
|
|
115
115
|
async function getReason(opts, doc) {
|
|
116
|
-
if (
|
|
116
|
+
if (isFunction(opts.getReason)) {
|
|
117
117
|
return await opts.getReason(doc);
|
|
118
118
|
}
|
|
119
119
|
return void 0;
|
|
120
120
|
}
|
|
121
121
|
async function getMetadata(opts, doc) {
|
|
122
|
-
if (
|
|
122
|
+
if (isFunction(opts.getMetadata)) {
|
|
123
123
|
return await opts.getMetadata(doc);
|
|
124
124
|
}
|
|
125
125
|
return void 0;
|
|
@@ -142,11 +142,11 @@ async function bulkPatch(opts, context, eventKey, docsKey) {
|
|
|
142
142
|
const event = opts[eventKey];
|
|
143
143
|
const docs = context[docsKey];
|
|
144
144
|
const key = eventKey === "eventCreated" ? "doc" : "oldDoc";
|
|
145
|
-
if (
|
|
146
|
-
const chunks =
|
|
147
|
-
for
|
|
145
|
+
if (isEmpty(docs) || !event && !history) return;
|
|
146
|
+
const chunks = chunk(docs, 1e3);
|
|
147
|
+
for (const chunk2 of chunks) {
|
|
148
148
|
const bulk = [];
|
|
149
|
-
for (const doc of
|
|
149
|
+
for (const doc of chunk2) {
|
|
150
150
|
emitEvent(context, event, { [key]: doc });
|
|
151
151
|
if (history) {
|
|
152
152
|
const [user, reason, metadata] = await getData(opts, doc);
|
|
@@ -167,7 +167,7 @@ async function bulkPatch(opts, context, eventKey, docsKey) {
|
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
-
if (history && !
|
|
170
|
+
if (history && !isEmpty(bulk)) {
|
|
171
171
|
await HistoryModel.bulkWrite(bulk, { ordered: false }).catch((error) => {
|
|
172
172
|
console.error(error.message);
|
|
173
173
|
});
|
|
@@ -181,9 +181,9 @@ async function updatePatch(opts, context, current, original) {
|
|
|
181
181
|
const history = isPatchHistoryEnabled(opts, context);
|
|
182
182
|
const currentObject = getJsonOmit(opts, current);
|
|
183
183
|
const originalObject = getJsonOmit(opts, original);
|
|
184
|
-
if (
|
|
184
|
+
if (isEmpty(originalObject) || isEmpty(currentObject)) return;
|
|
185
185
|
const patch = jsonpatch.compare(originalObject, currentObject, true);
|
|
186
|
-
if (
|
|
186
|
+
if (isEmpty(patch)) return;
|
|
187
187
|
emitEvent(context, opts.eventUpdated, { oldDoc: original, doc: current, patch });
|
|
188
188
|
if (history) {
|
|
189
189
|
let version = 0;
|
|
@@ -209,13 +209,6 @@ async function deletePatch(opts, context) {
|
|
|
209
209
|
await bulkPatch(opts, context, "eventDeleted", "deletedDocs");
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
const isMongooseLessThan8 = satisfies(mongoose.version, "<8");
|
|
213
|
-
const isMongooseLessThan7 = satisfies(mongoose.version, "<7");
|
|
214
|
-
const isMongoose6 = satisfies(mongoose.version, "6");
|
|
215
|
-
if (isMongoose6) {
|
|
216
|
-
mongoose.set("strictQuery", false);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
212
|
const deleteMethods = ["remove", "findOneAndDelete", "findOneAndRemove", "findByIdAndDelete", "findByIdAndRemove", "deleteOne", "deleteMany"];
|
|
220
213
|
const deleteHooksInitialize = (schema, opts) => {
|
|
221
214
|
schema.pre(deleteMethods, { document: false, query: true }, async function() {
|
|
@@ -232,16 +225,16 @@ const deleteHooksInitialize = (schema, opts) => {
|
|
|
232
225
|
};
|
|
233
226
|
if (["remove", "deleteMany"].includes(this._context.op) && !options.single) {
|
|
234
227
|
const docs = await model.find(filter).lean().exec();
|
|
235
|
-
if (!
|
|
228
|
+
if (!isEmpty(docs)) {
|
|
236
229
|
this._context.deletedDocs = docs;
|
|
237
230
|
}
|
|
238
231
|
} else {
|
|
239
232
|
const doc = await model.findOne(filter).lean().exec();
|
|
240
|
-
if (!
|
|
233
|
+
if (!isEmpty(doc)) {
|
|
241
234
|
this._context.deletedDocs = [doc];
|
|
242
235
|
}
|
|
243
236
|
}
|
|
244
|
-
if (opts.preDelete &&
|
|
237
|
+
if (opts.preDelete && isArray(this._context.deletedDocs) && !isEmpty(this._context.deletedDocs)) {
|
|
245
238
|
await opts.preDelete(this._context.deletedDocs);
|
|
246
239
|
}
|
|
247
240
|
});
|
|
@@ -277,7 +270,7 @@ const saveHooksInitialize = (schema, opts) => {
|
|
|
277
270
|
const updateMethods = ["update", "updateOne", "replaceOne", "updateMany", "findOneAndUpdate", "findOneAndReplace", "findByIdAndUpdate"];
|
|
278
271
|
const assignUpdate = (document, update, commands) => {
|
|
279
272
|
let updated = assign(document.toObject(toObjectOptions), update);
|
|
280
|
-
|
|
273
|
+
forEach(commands, (command) => {
|
|
281
274
|
try {
|
|
282
275
|
updated = assign(updated, command);
|
|
283
276
|
} catch {
|
|
@@ -290,11 +283,11 @@ const assignUpdate = (document, update, commands) => {
|
|
|
290
283
|
const splitUpdateAndCommands = (updateQuery) => {
|
|
291
284
|
let update = {};
|
|
292
285
|
const commands = [];
|
|
293
|
-
if (!
|
|
294
|
-
update =
|
|
295
|
-
const keysWithDollarSign =
|
|
296
|
-
if (!
|
|
297
|
-
|
|
286
|
+
if (!isEmpty(updateQuery) && !isArray(updateQuery) && isObjectLike(updateQuery)) {
|
|
287
|
+
update = cloneDeep(updateQuery);
|
|
288
|
+
const keysWithDollarSign = keys(update).filter((key) => key.startsWith("$"));
|
|
289
|
+
if (!isEmpty(keysWithDollarSign)) {
|
|
290
|
+
forEach(keysWithDollarSign, (key) => {
|
|
298
291
|
commands.push({ [key]: update[key] });
|
|
299
292
|
delete update[key];
|
|
300
293
|
});
|
|
@@ -335,13 +328,13 @@ const updateHooksInitialize = (schema, opts) => {
|
|
|
335
328
|
let current = null;
|
|
336
329
|
const filter = this.getFilter();
|
|
337
330
|
const combined = assignUpdate(model.hydrate({}), update, commands);
|
|
338
|
-
if (!
|
|
331
|
+
if (!isEmpty(update) && !current) {
|
|
339
332
|
current = await model.findOne(update).sort("desc").lean().exec();
|
|
340
333
|
}
|
|
341
|
-
if (!
|
|
334
|
+
if (!isEmpty(combined) && !current) {
|
|
342
335
|
current = await model.findOne(combined).sort("desc").lean().exec();
|
|
343
336
|
}
|
|
344
|
-
if (!
|
|
337
|
+
if (!isEmpty(filter) && !current) {
|
|
345
338
|
console.log("filter", filter);
|
|
346
339
|
current = await model.findOne(filter).sort("desc").lean().exec();
|
|
347
340
|
}
|
|
@@ -352,8 +345,14 @@ const updateHooksInitialize = (schema, opts) => {
|
|
|
352
345
|
});
|
|
353
346
|
};
|
|
354
347
|
|
|
348
|
+
const isMongooseLessThan8 = satisfies(mongoose.version, "<8");
|
|
349
|
+
const isMongooseLessThan7 = satisfies(mongoose.version, "<7");
|
|
350
|
+
const isMongoose6 = satisfies(mongoose.version, "6");
|
|
351
|
+
if (isMongoose6) {
|
|
352
|
+
mongoose.set("strictQuery", false);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
355
|
const remove = isMongooseLessThan7 ? "remove" : "deleteOne";
|
|
356
|
-
const patchEventEmitter = em;
|
|
357
356
|
const patchHistoryPlugin = function plugin(schema, opts) {
|
|
358
357
|
saveHooksInitialize(schema, opts);
|
|
359
358
|
updateHooksInitialize(schema, opts);
|
|
@@ -370,7 +369,7 @@ const patchHistoryPlugin = function plugin(schema, opts) {
|
|
|
370
369
|
if (isMongooseLessThan8) {
|
|
371
370
|
schema.pre(remove, { document: true, query: false }, async function() {
|
|
372
371
|
const original = this.toObject(toObjectOptions);
|
|
373
|
-
if (opts.preDelete && !
|
|
372
|
+
if (opts.preDelete && !isEmpty(original)) {
|
|
374
373
|
await opts.preDelete([original]);
|
|
375
374
|
}
|
|
376
375
|
});
|
|
@@ -388,4 +387,4 @@ const patchHistoryPlugin = function plugin(schema, opts) {
|
|
|
388
387
|
}
|
|
389
388
|
};
|
|
390
389
|
|
|
391
|
-
export { patchEventEmitter, patchHistoryPlugin, setPatchHistoryTTL };
|
|
390
|
+
export { em as patchEventEmitter, patchHistoryPlugin, setPatchHistoryTTL };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-patch-mongoose",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.3",
|
|
4
4
|
"description": "Patch history & events for mongoose models",
|
|
5
5
|
"author": "ilovepixelart",
|
|
6
6
|
"license": "MIT",
|
|
@@ -71,27 +71,27 @@
|
|
|
71
71
|
"release": "npm install && npm run biome && npm run type:check && npm run build && np"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@types/lodash": "4.17.
|
|
74
|
+
"@types/lodash-es": "4.17.12",
|
|
75
75
|
"@types/ms": "2.1.0",
|
|
76
|
-
"@types/semver": "7.7.
|
|
76
|
+
"@types/semver": "7.7.1",
|
|
77
77
|
"fast-json-patch": "3.1.1",
|
|
78
|
-
"lodash": "4.17.21",
|
|
78
|
+
"lodash-es": "4.17.21",
|
|
79
79
|
"ms": "2.1.3",
|
|
80
80
|
"omit-deep": "0.3.0",
|
|
81
81
|
"power-assign": "0.2.10",
|
|
82
|
-
"semver": "7.7.
|
|
82
|
+
"semver": "7.7.3"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@biomejs/biome": "
|
|
86
|
-
"@types/node": "24.
|
|
87
|
-
"@vitest/coverage-v8": "
|
|
88
|
-
"mongodb-memory-server": "10.
|
|
89
|
-
"mongoose": "8.
|
|
85
|
+
"@biomejs/biome": "2.2.7",
|
|
86
|
+
"@types/node": "24.9.1",
|
|
87
|
+
"@vitest/coverage-v8": "4.0.2",
|
|
88
|
+
"mongodb-memory-server": "10.2.3",
|
|
89
|
+
"mongoose": "8.19.2",
|
|
90
90
|
"open-cli": "8.0.0",
|
|
91
|
-
"pkgroll": "2.
|
|
92
|
-
"simple-git-hooks": "2.13.
|
|
93
|
-
"typescript": "5.
|
|
94
|
-
"vitest": "
|
|
91
|
+
"pkgroll": "2.20.1",
|
|
92
|
+
"simple-git-hooks": "2.13.1",
|
|
93
|
+
"typescript": "5.9.3",
|
|
94
|
+
"vitest": "4.0.2"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|
|
97
97
|
"mongoose": ">=6.6.0 < 9"
|
package/src/helpers.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { isArray, isEmpty } from 'lodash-es'
|
|
3
2
|
import { isHookIgnored } from '../helpers'
|
|
4
3
|
import { deletePatch } from '../patch'
|
|
5
4
|
|
|
@@ -26,17 +25,17 @@ export const deleteHooksInitialize = <T>(schema: Schema<T>, opts: PluginOptions<
|
|
|
26
25
|
|
|
27
26
|
if (['remove', 'deleteMany'].includes(this._context.op) && !options.single) {
|
|
28
27
|
const docs = await model.find<T>(filter).lean().exec()
|
|
29
|
-
if (!
|
|
28
|
+
if (!isEmpty(docs)) {
|
|
30
29
|
this._context.deletedDocs = docs as HydratedDocument<T>[]
|
|
31
30
|
}
|
|
32
31
|
} else {
|
|
33
32
|
const doc = await model.findOne<T>(filter).lean().exec()
|
|
34
|
-
if (!
|
|
33
|
+
if (!isEmpty(doc)) {
|
|
35
34
|
this._context.deletedDocs = [doc] as HydratedDocument<T>[]
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
if (opts.preDelete &&
|
|
38
|
+
if (opts.preDelete && isArray(this._context.deletedDocs) && !isEmpty(this._context.deletedDocs)) {
|
|
40
39
|
await opts.preDelete(this._context.deletedDocs)
|
|
41
40
|
}
|
|
42
41
|
})
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { cloneDeep, forEach, isArray, isEmpty, isObjectLike, keys } from 'lodash-es'
|
|
2
2
|
import { assign } from 'power-assign'
|
|
3
|
-
|
|
4
3
|
import { isHookIgnored, toObjectOptions } from '../helpers'
|
|
5
4
|
import { createPatch, updatePatch } from '../patch'
|
|
6
5
|
|
|
@@ -12,7 +11,7 @@ const updateMethods = ['update', 'updateOne', 'replaceOne', 'updateMany', 'findO
|
|
|
12
11
|
export const assignUpdate = <T>(document: HydratedDocument<T>, update: UpdateQuery<T>, commands: Record<string, unknown>[]): HydratedDocument<T> => {
|
|
13
12
|
let updated = assign(document.toObject(toObjectOptions), update)
|
|
14
13
|
// Try catch not working for of loop, keep it as is
|
|
15
|
-
|
|
14
|
+
forEach(commands, (command) => {
|
|
16
15
|
try {
|
|
17
16
|
updated = assign(updated, command)
|
|
18
17
|
} catch {
|
|
@@ -29,11 +28,11 @@ export const splitUpdateAndCommands = <T>(updateQuery: UpdateWithAggregationPipe
|
|
|
29
28
|
let update: UpdateQuery<T> = {}
|
|
30
29
|
const commands: Record<string, unknown>[] = []
|
|
31
30
|
|
|
32
|
-
if (!
|
|
33
|
-
update =
|
|
34
|
-
const keysWithDollarSign =
|
|
35
|
-
if (!
|
|
36
|
-
|
|
31
|
+
if (!isEmpty(updateQuery) && !isArray(updateQuery) && isObjectLike(updateQuery)) {
|
|
32
|
+
update = cloneDeep(updateQuery)
|
|
33
|
+
const keysWithDollarSign = keys(update).filter((key) => key.startsWith('$'))
|
|
34
|
+
if (!isEmpty(keysWithDollarSign)) {
|
|
35
|
+
forEach(keysWithDollarSign, (key) => {
|
|
37
36
|
commands.push({ [key]: update[key] as unknown })
|
|
38
37
|
delete update[key]
|
|
39
38
|
})
|
|
@@ -84,15 +83,15 @@ export const updateHooksInitialize = <T>(schema: Schema<T>, opts: PluginOptions<
|
|
|
84
83
|
let current: HydratedDocument<T> | null = null
|
|
85
84
|
const filter = this.getFilter()
|
|
86
85
|
const combined = assignUpdate(model.hydrate({}), update, commands)
|
|
87
|
-
if (!
|
|
86
|
+
if (!isEmpty(update) && !current) {
|
|
88
87
|
current = (await model.findOne(update).sort('desc').lean().exec()) as HydratedDocument<T>
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
if (!
|
|
90
|
+
if (!isEmpty(combined) && !current) {
|
|
92
91
|
current = (await model.findOne(combined).sort('desc').lean().exec()) as HydratedDocument<T>
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
if (!
|
|
94
|
+
if (!isEmpty(filter) && !current) {
|
|
96
95
|
console.log('filter', filter)
|
|
97
96
|
current = (await model.findOne(filter).sort('desc').lean().exec()) as HydratedDocument<T>
|
|
98
97
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import em from './em'
|
|
3
|
-
|
|
1
|
+
import { isEmpty } from 'lodash-es'
|
|
4
2
|
import { toObjectOptions } from './helpers'
|
|
5
|
-
import { createPatch, deletePatch } from './patch'
|
|
6
|
-
import { isMongooseLessThan7, isMongooseLessThan8 } from './version'
|
|
7
|
-
|
|
8
3
|
import { deleteHooksInitialize } from './hooks/delete-hooks'
|
|
9
4
|
import { saveHooksInitialize } from './hooks/save-hooks'
|
|
10
5
|
import { updateHooksInitialize } from './hooks/update-hooks'
|
|
6
|
+
import { createPatch, deletePatch } from './patch'
|
|
7
|
+
import { isMongooseLessThan7, isMongooseLessThan8 } from './version'
|
|
11
8
|
|
|
12
9
|
import type { HydratedDocument, Model, Schema } from 'mongoose'
|
|
13
10
|
import type { PatchContext, PluginOptions } from './types'
|
|
@@ -17,10 +14,8 @@ const remove = isMongooseLessThan7 ? 'remove' : 'deleteOne'
|
|
|
17
14
|
/**
|
|
18
15
|
* @description Event emitter for patch operations.
|
|
19
16
|
*/
|
|
20
|
-
export
|
|
21
|
-
|
|
17
|
+
export { default as patchEventEmitter } from './em'
|
|
22
18
|
export { setPatchHistoryTTL } from './helpers'
|
|
23
|
-
|
|
24
19
|
export * from './types'
|
|
25
20
|
|
|
26
21
|
/**
|
|
@@ -68,7 +63,7 @@ export const patchHistoryPlugin = function plugin<T>(schema: Schema<T>, opts: Pl
|
|
|
68
63
|
// @ts-expect-error - Mongoose 7 and below
|
|
69
64
|
const original = this.toObject(toObjectOptions) as HydratedDocument<T>
|
|
70
65
|
|
|
71
|
-
if (opts.preDelete && !
|
|
66
|
+
if (opts.preDelete && !isEmpty(original)) {
|
|
72
67
|
await opts.preDelete([original])
|
|
73
68
|
}
|
|
74
69
|
})
|
package/src/model.ts
CHANGED
package/src/patch.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import jsonpatch from 'fast-json-patch'
|
|
2
|
-
import
|
|
2
|
+
import { chunk, isEmpty, isFunction } from 'lodash-es'
|
|
3
3
|
import omit from 'omit-deep'
|
|
4
|
+
import em from './em'
|
|
5
|
+
import { HistoryModel } from './model'
|
|
4
6
|
|
|
5
7
|
import type { HydratedDocument, MongooseError, Types } from 'mongoose'
|
|
6
8
|
import type { Metadata, PatchContext, PatchEvent, PluginOptions, User } from './types'
|
|
7
9
|
|
|
8
|
-
import em from './em'
|
|
9
|
-
import { HistoryModel } from './model'
|
|
10
|
-
|
|
11
10
|
function isPatchHistoryEnabled<T>(opts: PluginOptions<T>, context: PatchContext<T>): boolean {
|
|
12
11
|
return !opts.patchHistoryDisabled && !context.ignorePatchHistory
|
|
13
12
|
}
|
|
@@ -24,28 +23,28 @@ export function getJsonOmit<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>)
|
|
|
24
23
|
|
|
25
24
|
export function getObjectOmit<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>): Partial<T> {
|
|
26
25
|
if (opts.omit) {
|
|
27
|
-
return omit(
|
|
26
|
+
return omit(isFunction(doc?.toObject) ? doc.toObject() : doc, opts.omit)
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
return doc
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
export async function getUser<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>): Promise<User | undefined> {
|
|
34
|
-
if (
|
|
33
|
+
if (isFunction(opts.getUser)) {
|
|
35
34
|
return await opts.getUser(doc)
|
|
36
35
|
}
|
|
37
36
|
return undefined
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
export async function getReason<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>): Promise<string | undefined> {
|
|
41
|
-
if (
|
|
40
|
+
if (isFunction(opts.getReason)) {
|
|
42
41
|
return await opts.getReason(doc)
|
|
43
42
|
}
|
|
44
43
|
return undefined
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
export async function getMetadata<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>): Promise<Metadata | undefined> {
|
|
48
|
-
if (
|
|
47
|
+
if (isFunction(opts.getMetadata)) {
|
|
49
48
|
return await opts.getMetadata(doc)
|
|
50
49
|
}
|
|
51
50
|
return undefined
|
|
@@ -73,10 +72,10 @@ export async function bulkPatch<T>(opts: PluginOptions<T>, context: PatchContext
|
|
|
73
72
|
const docs = context[docsKey]
|
|
74
73
|
const key = eventKey === 'eventCreated' ? 'doc' : 'oldDoc'
|
|
75
74
|
|
|
76
|
-
if (
|
|
75
|
+
if (isEmpty(docs) || (!event && !history)) return
|
|
77
76
|
|
|
78
|
-
const chunks =
|
|
79
|
-
for
|
|
77
|
+
const chunks = chunk(docs, 1000)
|
|
78
|
+
for (const chunk of chunks) {
|
|
80
79
|
const bulk = []
|
|
81
80
|
|
|
82
81
|
for (const doc of chunk) {
|
|
@@ -102,7 +101,7 @@ export async function bulkPatch<T>(opts: PluginOptions<T>, context: PatchContext
|
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
if (history && !
|
|
104
|
+
if (history && !isEmpty(bulk)) {
|
|
106
105
|
await HistoryModel.bulkWrite(bulk, { ordered: false }).catch((error: MongooseError) => {
|
|
107
106
|
console.error(error.message)
|
|
108
107
|
})
|
|
@@ -119,10 +118,10 @@ export async function updatePatch<T>(opts: PluginOptions<T>, context: PatchConte
|
|
|
119
118
|
|
|
120
119
|
const currentObject = getJsonOmit(opts, current)
|
|
121
120
|
const originalObject = getJsonOmit(opts, original)
|
|
122
|
-
if (
|
|
121
|
+
if (isEmpty(originalObject) || isEmpty(currentObject)) return
|
|
123
122
|
|
|
124
123
|
const patch = jsonpatch.compare(originalObject, currentObject, true)
|
|
125
|
-
if (
|
|
124
|
+
if (isEmpty(patch)) return
|
|
126
125
|
|
|
127
126
|
emitEvent(context, opts.eventUpdated, { oldDoc: original, doc: current, patch })
|
|
128
127
|
|
package/tests/helpers.test.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Mock, MockInstance } from 'vitest'
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
3
|
|
|
4
|
+
import ms from 'ms'
|
|
4
5
|
import { setPatchHistoryTTL } from '../src/helpers'
|
|
5
6
|
import { HistoryModel } from '../src/model'
|
|
6
7
|
|
|
7
|
-
import type { Mock, MockInstance } from 'vitest'
|
|
8
|
-
|
|
9
8
|
vi.mock('../src/model', () => ({
|
|
10
9
|
HistoryModel: {
|
|
11
10
|
collection: {
|
package/tests/mongo/server.ts
CHANGED
package/tests/patch.test.ts
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
|
|
3
|
+
import { afterEach } from 'node:test'
|
|
3
4
|
import mongoose from 'mongoose'
|
|
4
|
-
|
|
5
|
+
import em from '../src/em'
|
|
5
6
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
7
|
import { bulkPatch, getData, getJsonOmit, getMetadata, getReason, getUser, getValue, updatePatch } from '../src/patch'
|
|
7
|
-
|
|
8
8
|
import { USER_DELETED } from './constants/events'
|
|
9
|
+
import server from './mongo/server'
|
|
9
10
|
import { type User, UserSchema } from './schemas/User'
|
|
10
11
|
|
|
11
12
|
import type { HydratedDocument } from 'mongoose'
|
|
12
|
-
|
|
13
|
-
import { afterEach } from 'node:test'
|
|
14
|
-
import em from '../src/em'
|
|
15
13
|
import type { PatchContext, PluginOptions } from '../src/types'
|
|
16
|
-
import server from './mongo/server'
|
|
17
14
|
|
|
18
15
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
19
16
|
|
|
@@ -41,7 +38,7 @@ describe('patch tests', () => {
|
|
|
41
38
|
})
|
|
42
39
|
|
|
43
40
|
afterEach(async () => {
|
|
44
|
-
vi.
|
|
41
|
+
vi.clearAllMocks()
|
|
45
42
|
})
|
|
46
43
|
|
|
47
44
|
describe('getObjects', () => {
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import mongoose, { Types, model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model, Types } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
|
+
import { HistoryModel } from '../src/model'
|
|
5
7
|
import { isMongooseLessThan7 } from '../src/version'
|
|
6
|
-
|
|
7
|
-
import em from '../src/em'
|
|
8
8
|
import { USER_CREATED } from './constants/events'
|
|
9
9
|
import server from './mongo/server'
|
|
10
|
-
|
|
11
|
-
import { HistoryModel } from '../src/model'
|
|
12
10
|
import { type User, UserSchema } from './schemas/User'
|
|
13
11
|
|
|
14
12
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn((event: string, data: Record<string, unknown>) => console.log(event, data)) } }))
|
|
@@ -37,7 +35,7 @@ describe('plugin - event created & patch history disabled', () => {
|
|
|
37
35
|
})
|
|
38
36
|
|
|
39
37
|
afterEach(() => {
|
|
40
|
-
vi.
|
|
38
|
+
vi.clearAllMocks()
|
|
41
39
|
})
|
|
42
40
|
|
|
43
41
|
describe('normal cases', () => {
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import mongoose, { model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { toObjectOptions } from '../src/helpers'
|
|
5
6
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
7
|
import { HistoryModel } from '../src/model'
|
|
7
8
|
import { isMongooseLessThan7 } from '../src/version'
|
|
8
|
-
|
|
9
|
-
import em from '../src/em'
|
|
10
9
|
import { USER_DELETED } from './constants/events'
|
|
11
10
|
import server from './mongo/server'
|
|
12
|
-
|
|
13
11
|
import { type User, UserSchema } from './schemas/User'
|
|
14
12
|
|
|
15
13
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import mongoose, { Types, model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model, Types } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
|
+
import { HistoryModel } from '../src/model'
|
|
5
7
|
import { isMongooseLessThan7 } from '../src/version'
|
|
6
|
-
|
|
7
|
-
import em from '../src/em'
|
|
8
8
|
import { USER_UPDATED } from './constants/events'
|
|
9
9
|
import server from './mongo/server'
|
|
10
|
-
|
|
11
|
-
import { HistoryModel } from '../src/model'
|
|
12
10
|
import { type User, UserSchema } from './schemas/User'
|
|
13
11
|
|
|
14
12
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import mongoose, { model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import mongoose, { model } from 'mongoose'
|
|
6
4
|
import em from '../src/em'
|
|
5
|
+
import { patchHistoryPlugin } from '../src/index'
|
|
6
|
+
import { HistoryModel } from '../src/model'
|
|
7
7
|
import { GLOBAL_CREATED, GLOBAL_DELETED, GLOBAL_UPDATED } from './constants/events'
|
|
8
8
|
import server from './mongo/server'
|
|
9
|
-
|
|
10
|
-
import { HistoryModel } from '../src/model'
|
|
11
9
|
import { type Product, ProductSchema } from './schemas/Product'
|
|
12
10
|
import { type User, UserSchema } from './schemas/User'
|
|
13
11
|
|
|
@@ -41,7 +39,7 @@ describe('plugin - global', () => {
|
|
|
41
39
|
})
|
|
42
40
|
|
|
43
41
|
afterEach(async () => {
|
|
44
|
-
vi.
|
|
42
|
+
vi.clearAllMocks()
|
|
45
43
|
})
|
|
46
44
|
|
|
47
45
|
it('should save array', async () => {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import mongoose, { Types, model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model, Types } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
|
+
import { HistoryModel } from '../src/model'
|
|
5
7
|
import { isMongooseLessThan7 } from '../src/version'
|
|
6
|
-
|
|
7
|
-
import em from '../src/em'
|
|
8
8
|
import server from './mongo/server'
|
|
9
|
-
|
|
10
|
-
import { HistoryModel } from '../src/model'
|
|
11
9
|
import { type User, UserSchema } from './schemas/User'
|
|
12
10
|
|
|
13
11
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import mongoose, { model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
|
+
import { HistoryModel } from '../src/model'
|
|
5
7
|
import { isMongooseLessThan7 } from '../src/version'
|
|
6
|
-
|
|
7
|
-
import em from '../src/em'
|
|
8
8
|
import server from './mongo/server'
|
|
9
|
-
|
|
10
|
-
import { HistoryModel } from '../src/model'
|
|
11
9
|
import { type User, UserSchema } from './schemas/User'
|
|
12
10
|
|
|
13
11
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import mongoose, { model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { patchHistoryPlugin } from '../src/index'
|
|
5
6
|
import { isMongooseLessThan7 } from '../src/version'
|
|
6
|
-
|
|
7
|
-
import em from '../src/em'
|
|
8
7
|
import { USER_DELETED } from './constants/events'
|
|
9
8
|
import server from './mongo/server'
|
|
10
|
-
|
|
11
9
|
import { type User, UserSchema } from './schemas/User'
|
|
12
10
|
|
|
13
11
|
const preDeleteMock = vi.fn()
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import mongoose, { model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import mongoose, { model } from 'mongoose'
|
|
6
4
|
import em from '../src/em'
|
|
5
|
+
import { patchHistoryPlugin } from '../src/index'
|
|
7
6
|
import { USER_CREATED } from './constants/events'
|
|
8
7
|
import server from './mongo/server'
|
|
9
|
-
|
|
10
8
|
import { type User, UserSchema } from './schemas/User'
|
|
11
9
|
|
|
12
10
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
@@ -40,7 +38,6 @@ describe('plugin - preSave test', () => {
|
|
|
40
38
|
|
|
41
39
|
it('should create a User and execute save, and omit User role in history', async () => {
|
|
42
40
|
const john = await UserModel.create({ name: 'John', role: 'user' })
|
|
43
|
-
// @ts-expect-error __v is a hidden field in Mongoose model
|
|
44
41
|
const { __v, role, ...doc } = john.toJSON()
|
|
45
42
|
|
|
46
43
|
expect(em.emit).toHaveBeenCalledTimes(1)
|
package/tests/plugin.test.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import mongoose, { model } from 'mongoose'
|
|
2
1
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
2
|
|
|
3
|
+
import mongoose, { model } from 'mongoose'
|
|
4
|
+
import em from '../src/em'
|
|
4
5
|
import { patchHistoryPlugin } from '../src/index'
|
|
6
|
+
import { HistoryModel } from '../src/model'
|
|
5
7
|
import { isMongooseLessThan7 } from '../src/version'
|
|
6
|
-
|
|
7
|
-
import em from '../src/em'
|
|
8
8
|
import { USER_CREATED, USER_DELETED, USER_UPDATED } from './constants/events'
|
|
9
9
|
import server from './mongo/server'
|
|
10
|
-
|
|
11
|
-
import { HistoryModel } from '../src/model'
|
|
12
10
|
import { type User, UserSchema } from './schemas/User'
|
|
13
11
|
|
|
14
12
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
package/vite.config.mts
CHANGED
|
@@ -6,8 +6,18 @@ export default defineConfig({
|
|
|
6
6
|
name: 'node',
|
|
7
7
|
environment: 'node',
|
|
8
8
|
coverage: {
|
|
9
|
-
|
|
9
|
+
provider: 'v8',
|
|
10
|
+
reporter: ['text', 'json', 'html', 'lcov'],
|
|
10
11
|
include: ['src/**/*.ts'],
|
|
12
|
+
exclude: [
|
|
13
|
+
'node_modules/**',
|
|
14
|
+
'dist/**',
|
|
15
|
+
'coverage/**',
|
|
16
|
+
'**/*.d.ts',
|
|
17
|
+
'**/*.config.*',
|
|
18
|
+
'**/tests/**',
|
|
19
|
+
'examples/**',
|
|
20
|
+
],
|
|
11
21
|
},
|
|
12
22
|
},
|
|
13
23
|
})
|