ts-patch-mongoose 3.0.0 → 3.1.2

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.
Files changed (41) hide show
  1. package/README.md +31 -25
  2. package/dist/index.cjs +112 -115
  3. package/dist/index.d.cts +4 -1
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +4 -1
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +112 -115
  8. package/package.json +14 -15
  9. package/src/helpers.ts +16 -3
  10. package/src/hooks/delete-hooks.ts +5 -4
  11. package/src/hooks/update-hooks.ts +47 -19
  12. package/src/index.ts +8 -5
  13. package/src/ms.ts +4 -3
  14. package/src/omit-deep.ts +24 -63
  15. package/src/patch.ts +30 -33
  16. package/src/types.ts +3 -0
  17. package/biome.json +0 -50
  18. package/tests/constants/events.ts +0 -7
  19. package/tests/em.test.ts +0 -54
  20. package/tests/helpers.test.ts +0 -311
  21. package/tests/mongo/.gitignore +0 -3
  22. package/tests/mongo/server.ts +0 -31
  23. package/tests/ms.test.ts +0 -113
  24. package/tests/omit-deep.test.ts +0 -220
  25. package/tests/patch.test.ts +0 -199
  26. package/tests/plugin-all-features.test.ts +0 -741
  27. package/tests/plugin-complex-data.test.ts +0 -1332
  28. package/tests/plugin-event-created.test.ts +0 -371
  29. package/tests/plugin-event-deleted.test.ts +0 -400
  30. package/tests/plugin-event-updated.test.ts +0 -503
  31. package/tests/plugin-global.test.ts +0 -545
  32. package/tests/plugin-omit-all.test.ts +0 -349
  33. package/tests/plugin-patch-history-disabled.test.ts +0 -162
  34. package/tests/plugin-pre-delete.test.ts +0 -160
  35. package/tests/plugin-pre-save.test.ts +0 -54
  36. package/tests/plugin.test.ts +0 -576
  37. package/tests/schemas/Description.ts +0 -15
  38. package/tests/schemas/Product.ts +0 -38
  39. package/tests/schemas/User.ts +0 -22
  40. package/tsconfig.json +0 -32
  41. package/vite.config.mts +0 -23
@@ -1,503 +0,0 @@
1
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
2
-
3
- import mongoose, { model, Types } from 'mongoose'
4
- import em from '../src/em'
5
- import { patchHistoryPlugin } from '../src/index'
6
- import { HistoryModel } from '../src/model'
7
- import { isMongooseLessThan7 } from '../src/version'
8
- import { USER_UPDATED } from './constants/events'
9
- import server from './mongo/server'
10
- import { type User, UserSchema } from './schemas/User'
11
-
12
- vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
13
-
14
- describe('plugin - event updated & patch history disabled', () => {
15
- const instance = server('plugin-event-updated')
16
-
17
- UserSchema.plugin(patchHistoryPlugin, {
18
- eventUpdated: USER_UPDATED,
19
- patchHistoryDisabled: true,
20
- omit: ['createdAt', 'updatedAt'],
21
- })
22
-
23
- const UserModel = model<User>('User', UserSchema)
24
-
25
- beforeAll(async () => {
26
- await instance.create()
27
- })
28
-
29
- afterAll(async () => {
30
- await instance.destroy()
31
- })
32
-
33
- beforeEach(async () => {
34
- await mongoose.connection.collection('users').deleteMany({})
35
- await mongoose.connection.collection('history').deleteMany({})
36
- })
37
-
38
- afterEach(async () => {
39
- vi.resetAllMocks()
40
- })
41
-
42
- it('should save() and emit one update event', async () => {
43
- await UserModel.create({ name: 'Bob', role: 'user' })
44
- const user = new UserModel({ name: 'John', role: 'user' })
45
- const created = await user.save()
46
-
47
- user.name = 'John Doe'
48
- const updated = await user.save()
49
-
50
- const history = await HistoryModel.find({})
51
- expect(history).toHaveLength(0)
52
-
53
- expect(em.emit).toHaveBeenCalledTimes(1)
54
-
55
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
56
- oldDoc: expect.objectContaining({
57
- __v: 0,
58
- _id: created._id,
59
- name: 'John',
60
- role: 'user',
61
- createdAt: created.createdAt,
62
- updatedAt: created.createdAt,
63
- }),
64
- doc: expect.objectContaining({
65
- __v: 0,
66
- _id: updated._id,
67
- name: 'John Doe',
68
- role: 'user',
69
- createdAt: created.createdAt,
70
- updatedAt: updated.updatedAt,
71
- }),
72
- patch: expect.arrayContaining([
73
- { op: 'test', path: '/name', value: 'John' },
74
- { op: 'replace', path: '/name', value: 'John Doe' },
75
- ]),
76
- })
77
-
78
- // Confirm that the document is updated
79
- const users = await UserModel.find({})
80
- expect(users).toHaveLength(2)
81
- const [bob, john] = users
82
- expect(bob.name).toBe('Bob')
83
- expect(john.name).toBe('John Doe')
84
- })
85
-
86
- it('should update() and emit three update event', async () => {
87
- await UserModel.create(
88
- [
89
- { name: 'Alice', role: 'user' },
90
- { name: 'Bob', role: 'user' },
91
- { name: 'John', role: 'user' },
92
- ],
93
- { ordered: true },
94
- )
95
-
96
- if (isMongooseLessThan7) {
97
- // @ts-expect-error not available in Mongoose 6 and below
98
- await UserModel.update({ role: 'user' }, { role: 'manager' })
99
- } else {
100
- await UserModel.updateMany({ role: 'user' }, { role: 'manager' })
101
- }
102
-
103
- const users = await UserModel.find({ role: 'manager' })
104
- expect(users).toHaveLength(3)
105
-
106
- const history = await HistoryModel.find({})
107
- expect(history).toHaveLength(0)
108
-
109
- expect(em.emit).toHaveBeenCalledTimes(3)
110
-
111
- // Confirm that the document is updated
112
- const updated = await UserModel.find({}).sort({ name: 1 })
113
- expect(updated).toHaveLength(3)
114
- const [alice, bob, john] = updated
115
- expect(alice.role).toBe('manager')
116
- expect(bob.role).toBe('manager')
117
- expect(john.role).toBe('manager')
118
- })
119
-
120
- it('should updateOne() and emit one update event', async () => {
121
- await UserModel.create(
122
- [
123
- { name: 'Alice', role: 'user' },
124
- { name: 'Bob', role: 'user' },
125
- { name: 'John', role: 'user' },
126
- ],
127
- { ordered: true },
128
- )
129
-
130
- await UserModel.updateOne({ name: 'Bob' }, { role: 'manager' })
131
- const users = await UserModel.find({ role: 'manager' })
132
- expect(users).toHaveLength(1)
133
-
134
- const history = await HistoryModel.find({})
135
- expect(history).toHaveLength(0)
136
-
137
- expect(em.emit).toHaveBeenCalledTimes(1)
138
-
139
- // Confirm that the document is updated
140
- const updated = await UserModel.find({}).sort({ name: 1 })
141
- expect(updated).toHaveLength(3)
142
- const [alice, bob, john] = updated
143
- expect(alice.role).toBe('user')
144
- expect(bob.role).toBe('manager')
145
- expect(john.role).toBe('user')
146
- })
147
-
148
- it('should replaceOne() and emit two update event', async () => {
149
- await UserModel.create(
150
- [
151
- { name: 'Alice', role: 'user' },
152
- { name: 'Bob', role: 'user' },
153
- { name: 'John', role: 'user' },
154
- ],
155
- { ordered: true },
156
- )
157
-
158
- await UserModel.replaceOne({ name: 'Bob' }, { name: 'Bob Doe', role: 'manager' })
159
- const users = await UserModel.find({ role: 'manager' })
160
- expect(users).toHaveLength(1)
161
-
162
- const history = await HistoryModel.find({})
163
- expect(history).toHaveLength(0)
164
-
165
- expect(em.emit).toHaveBeenCalledTimes(1)
166
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
167
- oldDoc: expect.objectContaining({
168
- __v: 0,
169
- _id: expect.any(Types.ObjectId),
170
- name: 'Bob',
171
- role: 'user',
172
- createdAt: expect.any(Date),
173
- updatedAt: expect.any(Date),
174
- }),
175
- doc: expect.objectContaining({
176
- __v: 0,
177
- _id: expect.any(Types.ObjectId),
178
- name: 'Bob Doe',
179
- role: 'manager',
180
- createdAt: expect.any(Date),
181
- updatedAt: expect.any(Date),
182
- }),
183
- patch: expect.arrayContaining([
184
- { op: 'test', path: '/name', value: 'Bob' },
185
- { op: 'replace', path: '/name', value: 'Bob Doe' },
186
- { op: 'test', path: '/role', value: 'user' },
187
- { op: 'replace', path: '/role', value: 'manager' },
188
- ]),
189
- })
190
-
191
- // Confirm that the document is updated
192
- const updated = await UserModel.find({}).sort({ name: 1 })
193
- expect(updated).toHaveLength(3)
194
- const [alice, bob, john] = updated
195
- expect(alice.role).toBe('user')
196
- expect(bob.role).toBe('manager')
197
- expect(john.role).toBe('user')
198
- })
199
-
200
- it('should updateMany() and emit two update event', async () => {
201
- await UserModel.create(
202
- [
203
- { name: 'Alice', role: 'user' },
204
- { name: 'Bob', role: 'user' },
205
- { name: 'John', role: 'user' },
206
- ],
207
- { ordered: true },
208
- )
209
-
210
- await UserModel.updateMany({ role: 'user' }, { role: 'manager' })
211
- const users = await UserModel.find({ role: 'manager' })
212
- expect(users).toHaveLength(3)
213
-
214
- const history = await HistoryModel.find({})
215
- expect(history).toHaveLength(0)
216
-
217
- expect(em.emit).toHaveBeenCalledTimes(3)
218
-
219
- // Confirm that the document is updated
220
- const updated = await UserModel.find({}).sort({ name: 1 })
221
- expect(updated).toHaveLength(3)
222
- const [alice, bob, john] = updated
223
- expect(alice.role).toBe('manager')
224
- expect(bob.role).toBe('manager')
225
- expect(john.role).toBe('manager')
226
- })
227
-
228
- it('should findOneAndUpdate() and emit one update event', async () => {
229
- await UserModel.create({ name: 'Bob', role: 'user' })
230
- const created = await UserModel.create({ name: 'John', role: 'user' })
231
- await UserModel.findOneAndUpdate({ _id: created._id }, { name: 'John Doe', role: 'manager' })
232
- const updated = await UserModel.findById(created._id).exec()
233
- expect(updated).not.toBeNull()
234
-
235
- const history = await HistoryModel.find({})
236
- expect(history).toHaveLength(0)
237
-
238
- expect(em.emit).toHaveBeenCalledTimes(1)
239
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
240
- oldDoc: expect.objectContaining({
241
- __v: 0,
242
- _id: created._id,
243
- name: created.name,
244
- role: created.role,
245
- createdAt: created.createdAt,
246
- }),
247
- doc: expect.objectContaining({
248
- __v: 0,
249
- _id: updated?._id,
250
- name: updated?.name,
251
- role: updated?.role,
252
- createdAt: created.createdAt,
253
- }),
254
- patch: expect.arrayContaining([
255
- { op: 'test', path: '/role', value: 'user' },
256
- { op: 'replace', path: '/role', value: 'manager' },
257
- { op: 'test', path: '/name', value: 'John' },
258
- { op: 'replace', path: '/name', value: 'John Doe' },
259
- ]),
260
- })
261
-
262
- // Confirm that the document is updated
263
- expect(updated?.name).toBe('John Doe')
264
- expect(updated?.role).toBe('manager')
265
- })
266
-
267
- it('should findOneAndReplace() and emit one update event', async () => {
268
- await UserModel.create({ name: 'Bob', role: 'user' })
269
- const created = await UserModel.create({ name: 'John', role: 'user' })
270
- await UserModel.findOneAndReplace({ _id: created._id }, { name: 'John Doe', role: 'manager' })
271
- const updated = await UserModel.findById(created._id).exec()
272
- expect(updated).not.toBeNull()
273
-
274
- const history = await HistoryModel.find({})
275
- expect(history).toHaveLength(0)
276
-
277
- expect(em.emit).toHaveBeenCalledTimes(1)
278
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
279
- oldDoc: expect.objectContaining({
280
- __v: 0,
281
- _id: created._id,
282
- name: created.name,
283
- role: created.role,
284
- createdAt: created.createdAt,
285
- updatedAt: created.createdAt,
286
- }),
287
- doc: expect.objectContaining({
288
- __v: 0,
289
- _id: updated?._id,
290
- name: updated?.name,
291
- role: updated?.role,
292
- createdAt: updated?.createdAt,
293
- updatedAt: updated?.updatedAt,
294
- }),
295
- patch: expect.arrayContaining([
296
- { op: 'test', path: '/name', value: 'John' },
297
- { op: 'replace', path: '/name', value: 'John Doe' },
298
- { op: 'test', path: '/role', value: 'user' },
299
- { op: 'replace', path: '/role', value: 'manager' },
300
- ]),
301
- })
302
-
303
- // Confirm that the document is updated
304
- expect(updated?.name).toBe('John Doe')
305
- expect(updated?.role).toBe('manager')
306
- })
307
-
308
- it('should findByIdAndUpdate() and emit one update event', async () => {
309
- const created = await UserModel.create({ name: 'Bob', role: 'user' })
310
- await UserModel.findByIdAndUpdate(created._id, { name: 'John Doe', role: 'manager' })
311
-
312
- const history = await HistoryModel.find({})
313
- expect(history).toHaveLength(0)
314
-
315
- expect(em.emit).toHaveBeenCalledTimes(1)
316
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
317
- oldDoc: expect.objectContaining({
318
- __v: 0,
319
- _id: created._id,
320
- name: created.name,
321
- role: created.role,
322
- createdAt: created.createdAt,
323
- }),
324
- doc: expect.objectContaining({
325
- __v: 0,
326
- _id: created._id,
327
- name: 'John Doe',
328
- role: 'manager',
329
- createdAt: created.createdAt,
330
- }),
331
- patch: expect.arrayContaining([
332
- { op: 'test', path: '/name', value: 'Bob' },
333
- { op: 'replace', path: '/name', value: 'John Doe' },
334
- { op: 'test', path: '/role', value: 'user' },
335
- { op: 'replace', path: '/role', value: 'manager' },
336
- ]),
337
- })
338
-
339
- // Confirm that the document is updated
340
- const updated = await UserModel.findById(created._id).exec()
341
- expect(updated?.name).toBe('John Doe')
342
- expect(updated?.role).toBe('manager')
343
- })
344
-
345
- it('should update and emit one update event', async () => {
346
- await UserModel.create({ name: 'Bob', role: 'user' })
347
- const created = await UserModel.create({ name: 'John', role: 'user' })
348
- await UserModel.updateOne({ _id: created._id }, { name: 'John Doe', role: 'manager' })
349
- const updated = await UserModel.findById(created._id).exec()
350
- expect(updated).not.toBeNull()
351
-
352
- const history = await HistoryModel.find({})
353
- expect(history).toHaveLength(0)
354
-
355
- expect(em.emit).toHaveBeenCalledTimes(1)
356
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
357
- oldDoc: expect.objectContaining({
358
- __v: 0,
359
- _id: created._id,
360
- name: created.name,
361
- role: created.role,
362
- createdAt: created.createdAt,
363
- }),
364
- doc: expect.objectContaining({
365
- __v: 0,
366
- _id: updated?._id,
367
- name: updated?.name,
368
- role: updated?.role,
369
- createdAt: created.createdAt,
370
- }),
371
- patch: expect.arrayContaining([
372
- { op: 'test', path: '/role', value: 'user' },
373
- { op: 'replace', path: '/role', value: 'manager' },
374
- { op: 'test', path: '/name', value: 'John' },
375
- { op: 'replace', path: '/name', value: 'John Doe' },
376
- ]),
377
- })
378
-
379
- // Confirm that the document is updated
380
- expect(updated?.name).toBe('John Doe')
381
- expect(updated?.role).toBe('manager')
382
- })
383
-
384
- it('should updateMany and emit two update events', async () => {
385
- const created1 = await UserModel.create({ name: 'John', role: 'user' })
386
- const created2 = await UserModel.create({ name: 'Bob', role: 'user' })
387
- await UserModel.updateMany({}, { name: 'John Doe', role: 'manager' })
388
- const updated1 = await UserModel.findById(created1._id).exec()
389
- expect(updated1).not.toBeNull()
390
- const updated2 = await UserModel.findById(created2._id).exec()
391
- expect(updated2).not.toBeNull()
392
-
393
- const history = await HistoryModel.find({})
394
- expect(history).toHaveLength(0)
395
-
396
- expect(em.emit).toHaveBeenCalledTimes(2)
397
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
398
- oldDoc: expect.objectContaining({
399
- __v: 0,
400
- _id: created1._id,
401
- name: created1.name,
402
- role: created1.role,
403
- createdAt: created1.createdAt,
404
- }),
405
- doc: expect.objectContaining({
406
- __v: 0,
407
- _id: updated1?._id,
408
- name: updated1?.name,
409
- role: updated1?.role,
410
- createdAt: created1.createdAt,
411
- }),
412
- patch: expect.arrayContaining([
413
- { op: 'test', path: '/role', value: 'user' },
414
- { op: 'replace', path: '/role', value: 'manager' },
415
- { op: 'test', path: '/name', value: 'John' },
416
- { op: 'replace', path: '/name', value: 'John Doe' },
417
- ]),
418
- })
419
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
420
- oldDoc: expect.objectContaining({
421
- __v: 0,
422
- _id: created2._id,
423
- name: created2.name,
424
- role: created2.role,
425
- createdAt: created2.createdAt,
426
- }),
427
- doc: expect.objectContaining({
428
- __v: 0,
429
- _id: updated2?._id,
430
- name: updated2?.name,
431
- role: updated2?.role,
432
- createdAt: created2.createdAt,
433
- }),
434
- patch: expect.arrayContaining([
435
- { op: 'test', path: '/role', value: 'user' },
436
- { op: 'replace', path: '/role', value: 'manager' },
437
- { op: 'test', path: '/name', value: 'Bob' },
438
- { op: 'replace', path: '/name', value: 'John Doe' },
439
- ]),
440
- })
441
-
442
- // Confirm that the documents are updated
443
- expect(updated1?.name).toBe('John Doe')
444
- expect(updated1?.role).toBe('manager')
445
-
446
- expect(updated2?.name).toBe('John Doe')
447
- expect(updated2?.role).toBe('manager')
448
- })
449
-
450
- it('should findOneAndUpdate $set and emit one update event', async () => {
451
- const created = await UserModel.create({ name: 'Bob', role: 'user' })
452
- await UserModel.findOneAndUpdate({ _id: created._id }, { $set: { name: 'John Doe', role: 'manager' } })
453
- const updated = await UserModel.findById(created._id).exec()
454
- expect(updated).not.toBeNull()
455
- expect(updated?.name).toBe('John Doe')
456
- expect(updated?.role).toBe('manager')
457
-
458
- const history = await HistoryModel.find({})
459
- expect(history).toHaveLength(0)
460
-
461
- expect(em.emit).toHaveBeenCalledTimes(1)
462
- expect(em.emit).toHaveBeenCalledWith(USER_UPDATED, {
463
- oldDoc: expect.objectContaining({
464
- __v: 0,
465
- _id: created._id,
466
- name: created.name,
467
- role: created.role,
468
- createdAt: created.createdAt,
469
- }),
470
- doc: expect.objectContaining({
471
- __v: 0,
472
- _id: updated?._id,
473
- name: updated?.name,
474
- role: updated?.role,
475
- createdAt: created.createdAt,
476
- }),
477
- patch: expect.arrayContaining([
478
- { op: 'test', path: '/name', value: 'Bob' },
479
- { op: 'replace', path: '/name', value: 'John Doe' },
480
- { op: 'test', path: '/role', value: 'user' },
481
- { op: 'replace', path: '/role', value: 'manager' },
482
- ]),
483
- })
484
-
485
- // Confirm that the document is updated
486
- expect(updated?.name).toBe('John Doe')
487
- expect(updated?.role).toBe('manager')
488
- })
489
-
490
- it('should ignoreHook option on updateMany', async () => {
491
- const john = await UserModel.create({ name: 'John', role: 'user' })
492
- await UserModel.updateMany({ role: 'user' }, { role: 'admin' }, { ignoreHook: true }).exec()
493
-
494
- const history = await HistoryModel.find({})
495
- expect(history).toHaveLength(0)
496
-
497
- expect(em.emit).toHaveBeenCalledTimes(0)
498
-
499
- // Confirm that the document is updated
500
- const updated = await UserModel.findById(john._id).exec()
501
- expect(updated?.role).toBe('admin')
502
- })
503
- })