ts-patch-mongoose 2.9.6 → 3.1.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/dist/index.mjs CHANGED
@@ -1,18 +1,7 @@
1
- import isEmpty from 'lodash/isEmpty.js';
2
- import ms from 'ms';
3
1
  import mongoose, { Schema, model } from 'mongoose';
4
- import isArray from 'lodash/isArray.js';
5
2
  import jsonpatch from 'fast-json-patch';
6
- import chunk from 'lodash/chunk.js';
7
- import isFunction from 'lodash/isFunction.js';
8
- import omit from 'omit-deep';
9
3
  import EventEmitter from 'node:events';
10
- import cloneDeep from 'lodash/cloneDeep.js';
11
- import forEach from 'lodash/forEach.js';
12
- import isObjectLike from 'lodash/isObjectLike.js';
13
- import keys from 'lodash/keys.js';
14
4
  import { assign } from 'power-assign';
15
- import { satisfies } from 'semver';
16
5
 
17
6
  const HistorySchema = new Schema(
18
7
  {
@@ -59,6 +48,166 @@ HistorySchema.index({ collectionId: 1, version: -1 });
59
48
  HistorySchema.index({ op: 1, modelName: 1, collectionName: 1, collectionId: 1, reason: 1, version: 1 });
60
49
  const HistoryModel = model("History", HistorySchema, "history");
61
50
 
51
+ const s = 1e3;
52
+ const m = s * 60;
53
+ const h = m * 60;
54
+ const d = h * 24;
55
+ const w = d * 7;
56
+ const y = d * 365.25;
57
+ const mo = y / 12;
58
+ const UNITS = {
59
+ milliseconds: 1,
60
+ millisecond: 1,
61
+ msecs: 1,
62
+ msec: 1,
63
+ ms: 1,
64
+ seconds: s,
65
+ second: s,
66
+ secs: s,
67
+ sec: s,
68
+ s,
69
+ minutes: m,
70
+ minute: m,
71
+ mins: m,
72
+ min: m,
73
+ m,
74
+ hours: h,
75
+ hour: h,
76
+ hrs: h,
77
+ hr: h,
78
+ h,
79
+ days: d,
80
+ day: d,
81
+ d,
82
+ weeks: w,
83
+ week: w,
84
+ w,
85
+ months: mo,
86
+ month: mo,
87
+ mo,
88
+ years: y,
89
+ year: y,
90
+ yrs: y,
91
+ yr: y,
92
+ y
93
+ };
94
+ const unitPattern = Object.keys(UNITS).sort((a, b) => b.length - a.length).join("|");
95
+ const RE = new RegExp(String.raw`^(-?(?:\d+)?\.?\d+)\s*(${unitPattern})?$`, "i");
96
+ const ms = (val) => {
97
+ const str = String(val);
98
+ if (str.length > 100) return Number.NaN;
99
+ const match = RE.exec(str);
100
+ if (!match) return Number.NaN;
101
+ const n = Number.parseFloat(match[1] ?? "");
102
+ const type = (match[2] ?? "ms").toLowerCase();
103
+ return n * (UNITS[type] ?? 0);
104
+ };
105
+
106
+ const isArray = Array.isArray;
107
+ const isEmpty = (value) => {
108
+ if (value == null) return true;
109
+ if (Array.isArray(value) || typeof value === "string") return value.length === 0;
110
+ if (value instanceof Map || value instanceof Set) return value.size === 0;
111
+ if (typeof value === "object") {
112
+ for (const key in value) {
113
+ if (Object.hasOwn(value, key)) return false;
114
+ }
115
+ return true;
116
+ }
117
+ return true;
118
+ };
119
+ const isFunction = (value) => {
120
+ return typeof value === "function";
121
+ };
122
+ const isObjectLike = (value) => {
123
+ return typeof value === "object" && value !== null;
124
+ };
125
+ const cloneArrayBuffer = (arrayBuffer) => {
126
+ const result = new ArrayBuffer(arrayBuffer.byteLength);
127
+ new Uint8Array(result).set(new Uint8Array(arrayBuffer));
128
+ return result;
129
+ };
130
+ const cloneImmutable = (value) => {
131
+ const tag = Object.prototype.toString.call(value);
132
+ switch (tag) {
133
+ case "[object Date]":
134
+ return /* @__PURE__ */ new Date(+value);
135
+ case "[object RegExp]": {
136
+ const re = value;
137
+ const cloned = new RegExp(re.source, re.flags);
138
+ cloned.lastIndex = re.lastIndex;
139
+ return cloned;
140
+ }
141
+ case "[object Error]": {
142
+ const err = value;
143
+ const cloned = new err.constructor(err.message);
144
+ if (err.stack) cloned.stack = err.stack;
145
+ return cloned;
146
+ }
147
+ case "[object ArrayBuffer]":
148
+ return cloneArrayBuffer(value);
149
+ case "[object DataView]": {
150
+ const dv = value;
151
+ const buffer = cloneArrayBuffer(dv.buffer);
152
+ return new DataView(buffer, dv.byteOffset, dv.byteLength);
153
+ }
154
+ }
155
+ if (ArrayBuffer.isView(value)) {
156
+ const ta = value;
157
+ const buffer = cloneArrayBuffer(ta.buffer);
158
+ return new value.constructor(buffer, ta.byteOffset, ta.length);
159
+ }
160
+ return void 0;
161
+ };
162
+ const cloneCollection = (value, seen) => {
163
+ if (value instanceof Map) {
164
+ const map = /* @__PURE__ */ new Map();
165
+ seen.set(value, map);
166
+ for (const [k, v] of value) map.set(k, cloneDeep(v, seen));
167
+ return map;
168
+ }
169
+ if (value instanceof Set) {
170
+ const set = /* @__PURE__ */ new Set();
171
+ seen.set(value, set);
172
+ for (const v of value) set.add(cloneDeep(v, seen));
173
+ return set;
174
+ }
175
+ if (Array.isArray(value)) {
176
+ const arr = new Array(value.length);
177
+ seen.set(value, arr);
178
+ for (let i = 0; i < value.length; i++) {
179
+ arr[i] = cloneDeep(value[i], seen);
180
+ }
181
+ return arr;
182
+ }
183
+ const result = typeof value.constructor === "function" ? Object.create(Object.getPrototypeOf(value)) : {};
184
+ seen.set(value, result);
185
+ for (const key of Object.keys(value)) {
186
+ result[key] = cloneDeep(value[key], seen);
187
+ }
188
+ return result;
189
+ };
190
+ const cloneDeep = (value, seen = /* @__PURE__ */ new WeakMap()) => {
191
+ if (value === null || typeof value !== "object") return value;
192
+ if (seen.has(value)) return seen.get(value);
193
+ const immutable = cloneImmutable(value);
194
+ if (immutable !== void 0) return immutable;
195
+ const record = value;
196
+ if (typeof record._bsontype === "string" && typeof record.toHexString === "function") {
197
+ return new value.constructor(record.toHexString());
198
+ }
199
+ if (typeof record.toJSON === "function") {
200
+ return JSON.parse(JSON.stringify(value));
201
+ }
202
+ return cloneCollection(value, seen);
203
+ };
204
+ const chunk = (array, size) => {
205
+ const result = [];
206
+ for (let i = 0; i < array.length; i += size) {
207
+ result.push(array.slice(i, i + size));
208
+ }
209
+ return result;
210
+ };
62
211
  const isHookIgnored = (options) => {
63
212
  return options.ignoreHook === true || options.ignoreEvent === true && options.ignorePatchHistory === true;
64
213
  };
@@ -66,7 +215,7 @@ const toObjectOptions = {
66
215
  depopulate: true,
67
216
  virtuals: false
68
217
  };
69
- const setPatchHistoryTTL = async (ttl) => {
218
+ const setPatchHistoryTTL = async (ttl, onError) => {
70
219
  const name = "createdAt_1_TTL";
71
220
  try {
72
221
  const indexes = await HistoryModel.collection.indexes();
@@ -75,7 +224,7 @@ const setPatchHistoryTTL = async (ttl) => {
75
224
  await HistoryModel.collection.dropIndex(name);
76
225
  return;
77
226
  }
78
- const milliseconds = typeof ttl === "string" ? ms(ttl) : ttl;
227
+ const milliseconds = ms(ttl);
79
228
  if (milliseconds < 1e3 && existingIndex) {
80
229
  await HistoryModel.collection.dropIndex(name);
81
230
  return;
@@ -89,7 +238,8 @@ const setPatchHistoryTTL = async (ttl) => {
89
238
  }
90
239
  await HistoryModel.collection.createIndex({ createdAt: 1 }, { expireAfterSeconds, name });
91
240
  } catch (err) {
92
- console.error("Couldn't create or update index for history collection", err);
241
+ const handler = onError ?? console.error;
242
+ handler(err);
93
243
  }
94
244
  };
95
245
 
@@ -97,64 +247,101 @@ class PatchEventEmitter extends EventEmitter {
97
247
  }
98
248
  const em = new PatchEventEmitter();
99
249
 
100
- function isPatchHistoryEnabled(opts, context) {
101
- return !opts.patchHistoryDisabled && !context.ignorePatchHistory;
102
- }
103
- function getJsonOmit(opts, doc) {
104
- const object = JSON.parse(JSON.stringify(doc));
105
- if (opts.omit) {
106
- return omit(object, opts.omit);
107
- }
108
- return object;
109
- }
110
- function getObjectOmit(opts, doc) {
111
- if (opts.omit) {
112
- return omit(isFunction(doc?.toObject) ? doc.toObject() : doc, opts.omit);
250
+ const isPlainObject = (val) => {
251
+ if (Object.prototype.toString.call(val) !== "[object Object]") return false;
252
+ const prot = Object.getPrototypeOf(val);
253
+ return prot === null || prot === Object.prototype;
254
+ };
255
+ const isUnsafeKey = (key) => {
256
+ return key === "__proto__" || key === "constructor" || key === "prototype";
257
+ };
258
+ const classifyKeys = (omitKeys) => {
259
+ const topLevel = /* @__PURE__ */ new Set();
260
+ const nested = /* @__PURE__ */ new Map();
261
+ for (const key of omitKeys) {
262
+ const dotIdx = key.indexOf(".");
263
+ if (dotIdx === -1) {
264
+ topLevel.add(key);
265
+ } else {
266
+ const head = key.slice(0, dotIdx);
267
+ const tail = key.slice(dotIdx + 1);
268
+ if (!isUnsafeKey(head)) {
269
+ const existing = nested.get(head) ?? [];
270
+ existing.push(tail);
271
+ nested.set(head, existing);
272
+ }
273
+ }
113
274
  }
114
- return doc;
115
- }
116
- async function getUser(opts, doc) {
117
- if (isFunction(opts.getUser)) {
118
- return await opts.getUser(doc);
275
+ return { topLevel, nested };
276
+ };
277
+ const omitDeep = (value, keys) => {
278
+ if (value === void 0) return {};
279
+ if (Array.isArray(value)) {
280
+ return value.map((item) => omitDeep(item, keys));
119
281
  }
120
- return void 0;
121
- }
122
- async function getReason(opts, doc) {
123
- if (isFunction(opts.getReason)) {
124
- return await opts.getReason(doc);
282
+ if (!isPlainObject(value)) return value;
283
+ const omitKeys = typeof keys === "string" ? [keys] : keys;
284
+ if (!Array.isArray(omitKeys)) return value;
285
+ const { topLevel, nested } = classifyKeys(omitKeys);
286
+ const result = {};
287
+ for (const key of Object.keys(value)) {
288
+ if (topLevel.has(key)) continue;
289
+ const nestedKeys = nested.get(key);
290
+ result[key] = omitDeep(value[key], nestedKeys ?? omitKeys);
125
291
  }
126
- return void 0;
127
- }
128
- async function getMetadata(opts, doc) {
129
- if (isFunction(opts.getMetadata)) {
130
- return await opts.getMetadata(doc);
292
+ return result;
293
+ };
294
+
295
+ const isPatchHistoryEnabled = (opts, context) => {
296
+ return !opts.patchHistoryDisabled && !context.ignorePatchHistory;
297
+ };
298
+ const applyOmit = (object, opts) => {
299
+ return opts.omit ? omitDeep(object, opts.omit) : object;
300
+ };
301
+ const replacer = (_key, value) => typeof value === "bigint" ? value.toString() : value;
302
+ const getJsonOmit = (opts, doc) => {
303
+ return applyOmit(JSON.parse(JSON.stringify(doc, replacer)), opts);
304
+ };
305
+ const getObjectOmit = (opts, doc) => {
306
+ return applyOmit(isFunction(doc?.toObject) ? doc.toObject() : doc, opts);
307
+ };
308
+ const getOptionalField = async (fn, doc) => {
309
+ if (isFunction(fn)) {
310
+ return await fn(doc);
131
311
  }
132
312
  return void 0;
133
- }
134
- function getValue(item) {
313
+ };
314
+ const getUser = async (opts, doc) => getOptionalField(opts.getUser, doc);
315
+ const getReason = async (opts, doc) => getOptionalField(opts.getReason, doc);
316
+ const getMetadata = async (opts, doc) => getOptionalField(opts.getMetadata, doc);
317
+ const getValue = (item) => {
135
318
  return item.status === "fulfilled" ? item.value : void 0;
136
- }
137
- async function getData(opts, doc) {
319
+ };
320
+ const getData = async (opts, doc) => {
138
321
  return Promise.allSettled([getUser(opts, doc), getReason(opts, doc), getMetadata(opts, doc)]).then(([user, reason, metadata]) => {
139
322
  return [getValue(user), getValue(reason), getValue(metadata)];
140
323
  });
141
- }
142
- function emitEvent(context, event, data) {
324
+ };
325
+ const emitEvent = (context, event, data) => {
143
326
  if (event && !context.ignoreEvent) {
144
- em.emit(event, data);
327
+ try {
328
+ em.emit(event, data);
329
+ } catch {
330
+ }
145
331
  }
146
- }
147
- async function bulkPatch(opts, context, eventKey, docsKey) {
332
+ };
333
+ const bulkPatch = async (opts, context, eventKey, docsKey) => {
148
334
  const history = isPatchHistoryEnabled(opts, context);
149
335
  const event = opts[eventKey];
150
336
  const docs = context[docsKey];
151
337
  const key = eventKey === "eventCreated" ? "doc" : "oldDoc";
152
- if (isEmpty(docs) || !event && !history) return;
338
+ if (isEmpty(docs) || !docs || !event && !history) return;
153
339
  const chunks = chunk(docs, 1e3);
154
- for (const chunk2 of chunks) {
340
+ for (const batch of chunks) {
155
341
  const bulk = [];
156
- for (const doc of chunk2) {
157
- emitEvent(context, event, { [key]: doc });
342
+ for (const doc of batch) {
343
+ const omitted = getObjectOmit(opts, doc);
344
+ emitEvent(context, event, { [key]: omitted });
158
345
  if (history) {
159
346
  const [user, reason, metadata] = await getData(opts, doc);
160
347
  bulk.push({
@@ -164,7 +351,7 @@ async function bulkPatch(opts, context, eventKey, docsKey) {
164
351
  modelName: context.modelName,
165
352
  collectionName: context.collectionName,
166
353
  collectionId: doc._id,
167
- doc: getObjectOmit(opts, doc),
354
+ doc: omitted,
168
355
  version: 0,
169
356
  ...user !== void 0 && { user },
170
357
  ...reason !== void 0 && { reason },
@@ -175,16 +362,17 @@ async function bulkPatch(opts, context, eventKey, docsKey) {
175
362
  }
176
363
  }
177
364
  if (history && !isEmpty(bulk)) {
365
+ const onError = opts.onError ?? console.error;
178
366
  await HistoryModel.bulkWrite(bulk, { ordered: false }).catch((error) => {
179
- console.error(error.message);
367
+ onError(error);
180
368
  });
181
369
  }
182
370
  }
183
- }
184
- async function createPatch(opts, context) {
371
+ };
372
+ const createPatch = async (opts, context) => {
185
373
  await bulkPatch(opts, context, "eventCreated", "createdDocs");
186
- }
187
- async function updatePatch(opts, context, current, original) {
374
+ };
375
+ const updatePatch = async (opts, context, current, original) => {
188
376
  const history = isPatchHistoryEnabled(opts, context);
189
377
  const currentObject = getJsonOmit(opts, current);
190
378
  const originalObject = getJsonOmit(opts, original);
@@ -199,6 +387,7 @@ async function updatePatch(opts, context, current, original) {
199
387
  version = lastHistory.version + 1;
200
388
  }
201
389
  const [user, reason, metadata] = await getData(opts, current);
390
+ const onError = opts.onError ?? console.error;
202
391
  await HistoryModel.create({
203
392
  op: context.op,
204
393
  modelName: context.modelName,
@@ -209,12 +398,14 @@ async function updatePatch(opts, context, current, original) {
209
398
  ...user !== void 0 && { user },
210
399
  ...reason !== void 0 && { reason },
211
400
  ...metadata !== void 0 && { metadata }
401
+ }).catch((error) => {
402
+ onError(error);
212
403
  });
213
404
  }
214
- }
215
- async function deletePatch(opts, context) {
405
+ };
406
+ const deletePatch = async (opts, context) => {
216
407
  await bulkPatch(opts, context, "eventDeleted", "deletedDocs");
217
- }
408
+ };
218
409
 
219
410
  const deleteMethods = ["remove", "findOneAndDelete", "findOneAndRemove", "findByIdAndDelete", "findByIdAndRemove", "deleteOne", "deleteMany"];
220
411
  const deleteHooksInitialize = (schema, opts) => {
@@ -225,8 +416,8 @@ const deleteHooksInitialize = (schema, opts) => {
225
416
  const filter = this.getFilter();
226
417
  this._context = {
227
418
  op: this.op,
228
- modelName: opts.modelName ?? this.model.modelName,
229
- collectionName: opts.collectionName ?? this.model.collection.collectionName,
419
+ modelName: opts.modelName ?? model.modelName,
420
+ collectionName: opts.collectionName ?? model.collection.collectionName,
230
421
  ignoreEvent: options.ignoreEvent,
231
422
  ignorePatchHistory: options.ignorePatchHistory
232
423
  };
@@ -242,12 +433,13 @@ const deleteHooksInitialize = (schema, opts) => {
242
433
  }
243
434
  }
244
435
  if (opts.preDelete && isArray(this._context.deletedDocs) && !isEmpty(this._context.deletedDocs)) {
245
- await opts.preDelete(this._context.deletedDocs);
436
+ await opts.preDelete(cloneDeep(this._context.deletedDocs));
246
437
  }
247
438
  });
248
439
  schema.post(deleteMethods, { document: false, query: true }, async function() {
249
440
  const options = this.getOptions();
250
441
  if (isHookIgnored(options)) return;
442
+ if (!this._context) return;
251
443
  await deletePatch(opts, this._context);
252
444
  });
253
445
  };
@@ -275,15 +467,42 @@ const saveHooksInitialize = (schema, opts) => {
275
467
  };
276
468
 
277
469
  const updateMethods = ["update", "updateOne", "replaceOne", "updateMany", "findOneAndUpdate", "findOneAndReplace", "findByIdAndUpdate"];
470
+ const trackChangedFields = (fields, updated, changed) => {
471
+ if (!fields) return;
472
+ for (const key of Object.keys(fields)) {
473
+ const root = key.split(".")[0];
474
+ changed.set(root, updated[root]);
475
+ }
476
+ };
477
+ const applyPullAll = (updated, fields, changed) => {
478
+ for (const [field, values] of Object.entries(fields)) {
479
+ const arr = updated[field];
480
+ if (Array.isArray(arr)) {
481
+ const filtered = arr.filter((item) => !values.some((v) => JSON.stringify(v) === JSON.stringify(item)));
482
+ updated[field] = filtered;
483
+ changed.set(field, filtered);
484
+ }
485
+ }
486
+ };
278
487
  const assignUpdate = (document, update, commands) => {
279
488
  let updated = assign(document.toObject(toObjectOptions), update);
280
- forEach(commands, (command) => {
489
+ const changedByCommand = /* @__PURE__ */ new Map();
490
+ for (const command of commands) {
491
+ const op = Object.keys(command)[0];
492
+ const fields = command[op];
281
493
  try {
282
494
  updated = assign(updated, command);
495
+ trackChangedFields(fields, updated, changedByCommand);
283
496
  } catch {
497
+ if (op === "$pullAll" && fields) {
498
+ applyPullAll(updated, fields, changedByCommand);
499
+ }
284
500
  }
285
- });
501
+ }
286
502
  const doc = document.set(updated).toObject(toObjectOptions);
503
+ for (const [field, value] of changedByCommand) {
504
+ doc[field] = value;
505
+ }
287
506
  if (update.createdAt) doc.createdAt = update.createdAt;
288
507
  return doc;
289
508
  };
@@ -292,28 +511,27 @@ const splitUpdateAndCommands = (updateQuery) => {
292
511
  const commands = [];
293
512
  if (!isEmpty(updateQuery) && !isArray(updateQuery) && isObjectLike(updateQuery)) {
294
513
  update = cloneDeep(updateQuery);
295
- const keysWithDollarSign = keys(update).filter((key) => key.startsWith("$"));
514
+ const keysWithDollarSign = Object.keys(update).filter((key) => key.startsWith("$"));
296
515
  if (!isEmpty(keysWithDollarSign)) {
297
- forEach(keysWithDollarSign, (key) => {
516
+ for (const key of keysWithDollarSign) {
298
517
  commands.push({ [key]: update[key] });
299
518
  delete update[key];
300
- });
519
+ }
301
520
  }
302
521
  }
303
522
  return { update, commands };
304
523
  };
305
524
  const updateHooksInitialize = (schema, opts) => {
306
- schema.pre(updateMethods, async function() {
525
+ schema.pre(updateMethods, { document: false, query: true }, async function() {
307
526
  const options = this.getOptions();
308
527
  if (isHookIgnored(options)) return;
309
528
  const model = this.model;
310
529
  const filter = this.getFilter();
311
- const count = await this.model.countDocuments(filter).exec();
312
530
  this._context = {
313
531
  op: this.op,
314
- modelName: opts.modelName ?? this.model.modelName,
315
- collectionName: opts.collectionName ?? this.model.collection.collectionName,
316
- isNew: Boolean(options.upsert) && count === 0,
532
+ modelName: opts.modelName ?? model.modelName,
533
+ collectionName: opts.collectionName ?? model.collection.collectionName,
534
+ isNew: Boolean(options.upsert) && await model.countDocuments(filter).exec() === 0,
317
535
  ignoreEvent: options.ignoreEvent,
318
536
  ignorePatchHistory: options.ignorePatchHistory
319
537
  };
@@ -325,25 +543,20 @@ const updateHooksInitialize = (schema, opts) => {
325
543
  await updatePatch(opts, this._context, assignUpdate(doc, update, commands), origDoc);
326
544
  });
327
545
  });
328
- schema.post(updateMethods, async function() {
546
+ schema.post(updateMethods, { document: false, query: true }, async function() {
329
547
  const options = this.getOptions();
330
548
  if (isHookIgnored(options)) return;
549
+ if (!this._context) return;
331
550
  if (!this._context.isNew) return;
332
551
  const model = this.model;
333
552
  const updateQuery = this.getUpdate();
334
553
  const { update, commands } = splitUpdateAndCommands(updateQuery);
335
- let current = null;
336
554
  const filter = this.getFilter();
337
- const combined = assignUpdate(model.hydrate({}), update, commands);
338
- if (!isEmpty(update) && !current) {
339
- current = await model.findOne(update).sort("desc").lean().exec();
340
- }
341
- if (!isEmpty(combined) && !current) {
342
- current = await model.findOne(combined).sort("desc").lean().exec();
343
- }
344
- if (!isEmpty(filter) && !current) {
345
- console.log("filter", filter);
346
- current = await model.findOne(filter).sort("desc").lean().exec();
555
+ const candidates = [update, assignUpdate(model.hydrate({}), update, commands), filter];
556
+ let current = null;
557
+ for (const query of candidates) {
558
+ if (current || isEmpty(query)) continue;
559
+ current = await model.findOne(query).sort({ _id: -1 }).lean().exec();
347
560
  }
348
561
  if (current) {
349
562
  this._context.createdDocs = [current];
@@ -352,15 +565,16 @@ const updateHooksInitialize = (schema, opts) => {
352
565
  });
353
566
  };
354
567
 
355
- const isMongooseLessThan8 = satisfies(mongoose.version, "<8");
356
- const isMongooseLessThan7 = satisfies(mongoose.version, "<7");
357
- const isMongoose6 = satisfies(mongoose.version, "6");
568
+ const major = Number.parseInt(mongoose.version, 10);
569
+ const isMongooseLessThan8 = major < 8;
570
+ const isMongooseLessThan7 = major < 7;
571
+ const isMongoose6 = major === 6;
358
572
  if (isMongoose6) {
359
573
  mongoose.set("strictQuery", false);
360
574
  }
361
575
 
362
576
  const remove = isMongooseLessThan7 ? "remove" : "deleteOne";
363
- const patchHistoryPlugin = function plugin(schema, opts) {
577
+ const patchHistoryPlugin = (schema, opts) => {
364
578
  saveHooksInitialize(schema, opts);
365
579
  updateHooksInitialize(schema, opts);
366
580
  deleteHooksInitialize(schema, opts);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-patch-mongoose",
3
- "version": "2.9.6",
3
+ "version": "3.1.0",
4
4
  "description": "Patch history & events for mongoose models",
5
5
  "author": "ilovepixelart",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "log"
37
37
  ],
38
38
  "engines": {
39
- "node": ">=16"
39
+ "node": ">=18"
40
40
  },
41
41
  "files": [
42
42
  "dist",
@@ -71,28 +71,21 @@
71
71
  "release": "npm install && npm run biome && npm run type:check && npm run build && np --no-publish"
72
72
  },
73
73
  "dependencies": {
74
- "@types/lodash": "4.17.24",
75
- "@types/ms": "2.1.0",
76
- "@types/semver": "7.7.1",
77
74
  "fast-json-patch": "3.1.1",
78
- "lodash": "4.17.23",
79
- "ms": "2.1.3",
80
- "omit-deep": "0.3.0",
81
- "power-assign": "0.2.10",
82
- "semver": "7.7.4"
75
+ "power-assign": "0.2.10"
83
76
  },
84
77
  "devDependencies": {
85
- "@biomejs/biome": "2.4.4",
86
- "@types/node": "25.3.0",
87
- "@vitest/coverage-v8": "4.0.18",
78
+ "@biomejs/biome": "2.4.9",
79
+ "@types/node": "25.5.0",
80
+ "@vitest/coverage-v8": "4.1.2",
88
81
  "mongodb-memory-server": "11.0.1",
89
- "mongoose": "9.2.2",
90
- "open-cli": "8.0.0",
91
- "pkgroll": "2.26.3",
82
+ "mongoose": "9.3.3",
83
+ "np": "11.0.2",
84
+ "open-cli": "9.0.0",
85
+ "pkgroll": "2.27.0",
92
86
  "simple-git-hooks": "2.13.1",
93
87
  "typescript": "5.9.3",
94
- "vitest": "4.0.18",
95
- "np": "11.0.2"
88
+ "vitest": "4.1.2"
96
89
  },
97
90
  "peerDependencies": {
98
91
  "mongoose": ">=6.6.0 < 10"
@@ -105,6 +98,7 @@
105
98
  "publish": false
106
99
  },
107
100
  "overrides": {
108
- "esbuild": "0.25.0"
101
+ "tmp": "0.2.5",
102
+ "file-type": "21.3.2"
109
103
  }
110
104
  }