ts-patch-mongoose 3.1.0 → 4.0.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.
Files changed (46) hide show
  1. package/README.md +39 -27
  2. package/dist/index.cjs +287 -32
  3. package/dist/index.d.cts +23 -1
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +23 -1
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +287 -32
  8. package/package.json +19 -24
  9. package/biome.json +0 -47
  10. package/src/em.ts +0 -6
  11. package/src/helpers.ts +0 -174
  12. package/src/hooks/delete-hooks.ts +0 -49
  13. package/src/hooks/save-hooks.ts +0 -30
  14. package/src/hooks/update-hooks.ts +0 -125
  15. package/src/index.ts +0 -65
  16. package/src/model.ts +0 -50
  17. package/src/modules/power-assign.d.ts +0 -3
  18. package/src/ms.ts +0 -66
  19. package/src/omit-deep.ts +0 -56
  20. package/src/patch.ts +0 -154
  21. package/src/types.ts +0 -53
  22. package/src/version.ts +0 -13
  23. package/tests/constants/events.ts +0 -7
  24. package/tests/em.test.ts +0 -70
  25. package/tests/helpers.test.ts +0 -373
  26. package/tests/mongo/.gitignore +0 -3
  27. package/tests/mongo/server.ts +0 -31
  28. package/tests/ms.test.ts +0 -113
  29. package/tests/omit-deep.test.ts +0 -235
  30. package/tests/patch.test.ts +0 -200
  31. package/tests/plugin-all-features.test.ts +0 -844
  32. package/tests/plugin-complex-data.test.ts +0 -2647
  33. package/tests/plugin-event-created.test.ts +0 -371
  34. package/tests/plugin-event-deleted.test.ts +0 -400
  35. package/tests/plugin-event-updated.test.ts +0 -503
  36. package/tests/plugin-global.test.ts +0 -545
  37. package/tests/plugin-omit-all.test.ts +0 -349
  38. package/tests/plugin-patch-history-disabled.test.ts +0 -162
  39. package/tests/plugin-pre-delete.test.ts +0 -160
  40. package/tests/plugin-pre-save.test.ts +0 -54
  41. package/tests/plugin.test.ts +0 -576
  42. package/tests/schemas/Description.ts +0 -15
  43. package/tests/schemas/Product.ts +0 -38
  44. package/tests/schemas/User.ts +0 -22
  45. package/tsconfig.json +0 -32
  46. package/vite.config.mts +0 -24
@@ -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(() => {
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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).toHaveBeenCalledOnce()
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
- })