ts-patch-mongoose 2.7.0 → 2.8.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/biome.json +1 -1
- package/dist/cjs/helpers.js +7 -7
- package/dist/cjs/helpers.js.map +1 -1
- package/dist/cjs/hooks/delete-hooks.js.map +1 -1
- package/dist/cjs/hooks/save-hooks.js.map +1 -1
- package/dist/cjs/hooks/update-hooks.js.map +1 -1
- package/dist/cjs/models/History.js +5 -5
- package/dist/cjs/models/History.js.map +1 -1
- package/dist/cjs/patch.js +4 -4
- package/dist/cjs/patch.js.map +1 -1
- package/dist/cjs/plugin.js.map +1 -1
- package/dist/cjs/types/helpers.d.ts +2 -1
- package/dist/cjs/types/helpers.d.ts.map +1 -1
- package/dist/cjs/types/hooks/delete-hooks.d.ts +2 -2
- package/dist/cjs/types/hooks/delete-hooks.d.ts.map +1 -1
- package/dist/cjs/types/hooks/save-hooks.d.ts +2 -2
- package/dist/cjs/types/hooks/save-hooks.d.ts.map +1 -1
- package/dist/cjs/types/hooks/update-hooks.d.ts +2 -2
- package/dist/cjs/types/hooks/update-hooks.d.ts.map +1 -1
- package/dist/cjs/types/models/History.d.ts +6 -6
- package/dist/cjs/types/models/History.d.ts.map +1 -1
- package/dist/cjs/types/patch.d.ts +12 -15
- package/dist/cjs/types/patch.d.ts.map +1 -1
- package/dist/cjs/types/plugin.d.ts +2 -2
- package/dist/cjs/types/plugin.d.ts.map +1 -1
- package/dist/cjs/types/types.d.ts +49 -0
- package/dist/cjs/types/types.d.ts.map +1 -0
- package/dist/cjs/{interfaces/IEvent.js → types.js} +1 -1
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/helpers.js +7 -7
- package/dist/esm/helpers.js.map +1 -1
- package/dist/esm/hooks/delete-hooks.js.map +1 -1
- package/dist/esm/hooks/save-hooks.js.map +1 -1
- package/dist/esm/hooks/update-hooks.js.map +1 -1
- package/dist/esm/models/History.js +2 -3
- package/dist/esm/models/History.js.map +1 -1
- package/dist/esm/patch.js +4 -4
- package/dist/esm/patch.js.map +1 -1
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/types/helpers.d.ts +2 -1
- package/dist/esm/types/helpers.d.ts.map +1 -1
- package/dist/esm/types/hooks/delete-hooks.d.ts +2 -2
- package/dist/esm/types/hooks/delete-hooks.d.ts.map +1 -1
- package/dist/esm/types/hooks/save-hooks.d.ts +2 -2
- package/dist/esm/types/hooks/save-hooks.d.ts.map +1 -1
- package/dist/esm/types/hooks/update-hooks.d.ts +2 -2
- package/dist/esm/types/hooks/update-hooks.d.ts.map +1 -1
- package/dist/esm/types/models/History.d.ts +6 -6
- package/dist/esm/types/models/History.d.ts.map +1 -1
- package/dist/esm/types/patch.d.ts +12 -15
- package/dist/esm/types/patch.d.ts.map +1 -1
- package/dist/esm/types/plugin.d.ts +2 -2
- package/dist/esm/types/plugin.d.ts.map +1 -1
- package/dist/esm/types/types.d.ts +49 -0
- package/dist/esm/types/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +7 -10
- package/src/helpers.ts +8 -8
- package/src/hooks/delete-hooks.ts +4 -5
- package/src/hooks/save-hooks.ts +3 -4
- package/src/hooks/update-hooks.ts +4 -5
- package/src/models/History.ts +3 -5
- package/src/patch.ts +17 -21
- package/src/plugin.ts +25 -9
- package/src/types.ts +52 -0
- package/tests/helpers.test.ts +5 -6
- package/tests/patch.test.ts +21 -26
- package/tests/plugin-event-created.test.ts +50 -51
- package/tests/plugin-event-deleted.test.ts +76 -77
- package/tests/plugin-event-updated.test.ts +65 -67
- package/tests/plugin-global.test.ts +24 -25
- package/tests/plugin-omit-all.test.ts +36 -37
- package/tests/plugin-patch-history-disabled.test.ts +36 -37
- package/tests/plugin-pre-delete.test.ts +17 -18
- package/tests/plugin-pre-save.test.ts +6 -7
- package/tests/plugin.test.ts +37 -39
- package/tests/schemas/{DescriptionSchema.ts → Description.ts} +4 -4
- package/tests/schemas/{ProductSchema.ts → Product.ts} +12 -5
- package/tests/schemas/{UserSchema.ts → User.ts} +7 -4
- package/.swcrc +0 -17
- package/dist/cjs/interfaces/IContext.js +0 -3
- package/dist/cjs/interfaces/IContext.js.map +0 -1
- package/dist/cjs/interfaces/IEvent.js.map +0 -1
- package/dist/cjs/interfaces/IHistory.js +0 -3
- package/dist/cjs/interfaces/IHistory.js.map +0 -1
- package/dist/cjs/interfaces/IHookContext.js +0 -3
- package/dist/cjs/interfaces/IHookContext.js.map +0 -1
- package/dist/cjs/interfaces/IPluginOptions.js +0 -3
- package/dist/cjs/interfaces/IPluginOptions.js.map +0 -1
- package/dist/cjs/types/interfaces/IContext.d.ts +0 -13
- package/dist/cjs/types/interfaces/IContext.d.ts.map +0 -1
- package/dist/cjs/types/interfaces/IEvent.d.ts +0 -9
- package/dist/cjs/types/interfaces/IEvent.d.ts.map +0 -1
- package/dist/cjs/types/interfaces/IHistory.d.ts +0 -16
- package/dist/cjs/types/interfaces/IHistory.d.ts.map +0 -1
- package/dist/cjs/types/interfaces/IHookContext.d.ts +0 -8
- package/dist/cjs/types/interfaces/IHookContext.d.ts.map +0 -1
- package/dist/cjs/types/interfaces/IPluginOptions.d.ts +0 -18
- package/dist/cjs/types/interfaces/IPluginOptions.d.ts.map +0 -1
- package/dist/esm/interfaces/IContext.js +0 -2
- package/dist/esm/interfaces/IContext.js.map +0 -1
- package/dist/esm/interfaces/IEvent.js +0 -2
- package/dist/esm/interfaces/IEvent.js.map +0 -1
- package/dist/esm/interfaces/IHistory.js +0 -2
- package/dist/esm/interfaces/IHistory.js.map +0 -1
- package/dist/esm/interfaces/IHookContext.js +0 -2
- package/dist/esm/interfaces/IHookContext.js.map +0 -1
- package/dist/esm/interfaces/IPluginOptions.js +0 -2
- package/dist/esm/interfaces/IPluginOptions.js.map +0 -1
- package/dist/esm/types/interfaces/IContext.d.ts +0 -13
- package/dist/esm/types/interfaces/IContext.d.ts.map +0 -1
- package/dist/esm/types/interfaces/IEvent.d.ts +0 -9
- package/dist/esm/types/interfaces/IEvent.d.ts.map +0 -1
- package/dist/esm/types/interfaces/IHistory.d.ts +0 -16
- package/dist/esm/types/interfaces/IHistory.d.ts.map +0 -1
- package/dist/esm/types/interfaces/IHookContext.d.ts +0 -8
- package/dist/esm/types/interfaces/IHookContext.d.ts.map +0 -1
- package/dist/esm/types/interfaces/IPluginOptions.d.ts +0 -18
- package/dist/esm/types/interfaces/IPluginOptions.d.ts.map +0 -1
- package/src/interfaces/IContext.ts +0 -14
- package/src/interfaces/IEvent.ts +0 -10
- package/src/interfaces/IHistory.ts +0 -17
- package/src/interfaces/IHookContext.ts +0 -6
- package/src/interfaces/IPluginOptions.ts +0 -20
- package/tests/interfaces/IDescription.ts +0 -5
- package/tests/interfaces/IProduct.ts +0 -14
- package/tests/interfaces/IUser.ts +0 -8
package/src/patch.ts
CHANGED
|
@@ -3,20 +3,16 @@ import { chunk, isEmpty, isFunction } from 'lodash'
|
|
|
3
3
|
import omit from 'omit-deep'
|
|
4
4
|
|
|
5
5
|
import type { HydratedDocument, MongooseError, Types } from 'mongoose'
|
|
6
|
-
|
|
7
|
-
import type IContext from './interfaces/IContext'
|
|
8
|
-
import type IEvent from './interfaces/IEvent'
|
|
9
|
-
import type IPluginOptions from './interfaces/IPluginOptions'
|
|
10
|
-
import type { Metadata, User } from './interfaces/IPluginOptions'
|
|
6
|
+
import type { Metadata, PatchContext, PatchEvent, PluginOptions, User } from './types'
|
|
11
7
|
|
|
12
8
|
import em from './em'
|
|
13
|
-
import
|
|
9
|
+
import { HistoryModel } from './models/History'
|
|
14
10
|
|
|
15
|
-
function isPatchHistoryEnabled<T>(opts:
|
|
11
|
+
function isPatchHistoryEnabled<T>(opts: PluginOptions<T>, context: PatchContext<T>): boolean {
|
|
16
12
|
return !opts.patchHistoryDisabled && !context.ignorePatchHistory
|
|
17
13
|
}
|
|
18
14
|
|
|
19
|
-
export function getJsonOmit<T>(opts:
|
|
15
|
+
export function getJsonOmit<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>): Partial<T> {
|
|
20
16
|
const object = JSON.parse(JSON.stringify(doc)) as Partial<T>
|
|
21
17
|
|
|
22
18
|
if (opts.omit) {
|
|
@@ -26,7 +22,7 @@ export function getJsonOmit<T>(opts: IPluginOptions<T>, doc: HydratedDocument<T>
|
|
|
26
22
|
return object
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
export function getObjectOmit<T>(opts:
|
|
25
|
+
export function getObjectOmit<T>(opts: PluginOptions<T>, doc: HydratedDocument<T>): Partial<T> {
|
|
30
26
|
if (opts.omit) {
|
|
31
27
|
return omit(isFunction(doc?.toObject) ? doc.toObject() : doc, opts.omit)
|
|
32
28
|
}
|
|
@@ -34,21 +30,21 @@ export function getObjectOmit<T>(opts: IPluginOptions<T>, doc: HydratedDocument<
|
|
|
34
30
|
return doc
|
|
35
31
|
}
|
|
36
32
|
|
|
37
|
-
export async function getUser<T>(opts:
|
|
33
|
+
export async function getUser<T>(opts: PluginOptions<T>): Promise<User | undefined> {
|
|
38
34
|
if (isFunction(opts.getUser)) {
|
|
39
35
|
return await opts.getUser()
|
|
40
36
|
}
|
|
41
37
|
return undefined
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
export async function getReason<T>(opts:
|
|
40
|
+
export async function getReason<T>(opts: PluginOptions<T>): Promise<string | undefined> {
|
|
45
41
|
if (isFunction(opts.getReason)) {
|
|
46
42
|
return await opts.getReason()
|
|
47
43
|
}
|
|
48
44
|
return undefined
|
|
49
45
|
}
|
|
50
46
|
|
|
51
|
-
export async function getMetadata<T>(opts:
|
|
47
|
+
export async function getMetadata<T>(opts: PluginOptions<T>): Promise<Metadata | undefined> {
|
|
52
48
|
if (isFunction(opts.getMetadata)) {
|
|
53
49
|
return await opts.getMetadata()
|
|
54
50
|
}
|
|
@@ -59,19 +55,19 @@ export function getValue<T>(item: PromiseSettledResult<T>): T | undefined {
|
|
|
59
55
|
return item.status === 'fulfilled' ? item.value : undefined
|
|
60
56
|
}
|
|
61
57
|
|
|
62
|
-
export async function getData<T>(opts:
|
|
58
|
+
export async function getData<T>(opts: PluginOptions<T>): Promise<[User | undefined, string | undefined, Metadata | undefined]> {
|
|
63
59
|
return Promise.allSettled([getUser(opts), getReason(opts), getMetadata(opts)]).then(([user, reason, metadata]) => {
|
|
64
60
|
return [getValue(user), getValue(reason), getValue(metadata)]
|
|
65
61
|
})
|
|
66
62
|
}
|
|
67
63
|
|
|
68
|
-
export function emitEvent<T>(context:
|
|
64
|
+
export function emitEvent<T>(context: PatchContext<T>, event: string | undefined, data: PatchEvent<T>): void {
|
|
69
65
|
if (event && !context.ignoreEvent) {
|
|
70
66
|
em.emit(event, data)
|
|
71
67
|
}
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
export async function bulkPatch<T>(opts:
|
|
70
|
+
export async function bulkPatch<T>(opts: PluginOptions<T>, context: PatchContext<T>, eventKey: 'eventCreated' | 'eventDeleted', docsKey: 'createdDocs' | 'deletedDocs'): Promise<void> {
|
|
75
71
|
const history = isPatchHistoryEnabled(opts, context)
|
|
76
72
|
const event = opts[eventKey]
|
|
77
73
|
const docs = context[docsKey]
|
|
@@ -108,18 +104,18 @@ export async function bulkPatch<T>(opts: IPluginOptions<T>, context: IContext<T>
|
|
|
108
104
|
}
|
|
109
105
|
|
|
110
106
|
if (history && !isEmpty(bulk)) {
|
|
111
|
-
await
|
|
107
|
+
await HistoryModel.bulkWrite(bulk, { ordered: false }).catch((error: MongooseError) => {
|
|
112
108
|
console.error(error.message)
|
|
113
109
|
})
|
|
114
110
|
}
|
|
115
111
|
}
|
|
116
112
|
}
|
|
117
113
|
|
|
118
|
-
export async function createPatch<T>(opts:
|
|
114
|
+
export async function createPatch<T>(opts: PluginOptions<T>, context: PatchContext<T>): Promise<void> {
|
|
119
115
|
await bulkPatch(opts, context, 'eventCreated', 'createdDocs')
|
|
120
116
|
}
|
|
121
117
|
|
|
122
|
-
export async function updatePatch<T>(opts:
|
|
118
|
+
export async function updatePatch<T>(opts: PluginOptions<T>, context: PatchContext<T>, current: HydratedDocument<T>, original: HydratedDocument<T>): Promise<void> {
|
|
123
119
|
const history = isPatchHistoryEnabled(opts, context)
|
|
124
120
|
|
|
125
121
|
const currentObject = getJsonOmit(opts, current)
|
|
@@ -134,7 +130,7 @@ export async function updatePatch<T>(opts: IPluginOptions<T>, context: IContext<
|
|
|
134
130
|
if (history) {
|
|
135
131
|
let version = 0
|
|
136
132
|
|
|
137
|
-
const lastHistory = await
|
|
133
|
+
const lastHistory = await HistoryModel.findOne({ collectionId: original._id as Types.ObjectId })
|
|
138
134
|
.sort('-version')
|
|
139
135
|
.exec()
|
|
140
136
|
|
|
@@ -144,7 +140,7 @@ export async function updatePatch<T>(opts: IPluginOptions<T>, context: IContext<
|
|
|
144
140
|
|
|
145
141
|
const [user, reason, metadata] = await getData(opts)
|
|
146
142
|
|
|
147
|
-
await
|
|
143
|
+
await HistoryModel.create({
|
|
148
144
|
op: context.op,
|
|
149
145
|
modelName: context.modelName,
|
|
150
146
|
collectionName: context.collectionName,
|
|
@@ -158,6 +154,6 @@ export async function updatePatch<T>(opts: IPluginOptions<T>, context: IContext<
|
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
|
|
161
|
-
export async function deletePatch<T>(opts:
|
|
157
|
+
export async function deletePatch<T>(opts: PluginOptions<T>, context: PatchContext<T>): Promise<void> {
|
|
162
158
|
await bulkPatch(opts, context, 'eventDeleted', 'deletedDocs')
|
|
163
159
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -10,31 +10,38 @@ import { saveHooksInitialize } from './hooks/save-hooks'
|
|
|
10
10
|
import { updateHooksInitialize } from './hooks/update-hooks'
|
|
11
11
|
|
|
12
12
|
import type { HydratedDocument, Model, Schema } from 'mongoose'
|
|
13
|
-
import type
|
|
14
|
-
import type IPluginOptions from './interfaces/IPluginOptions'
|
|
13
|
+
import type { PatchContext, PluginOptions } from './types'
|
|
15
14
|
|
|
16
15
|
const remove = isMongooseLessThan7 ? 'remove' : 'deleteOne'
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
|
-
* @description
|
|
18
|
+
* @description Event emitter for patch operations.
|
|
20
19
|
*/
|
|
21
20
|
export const patchEventEmitter = em
|
|
22
21
|
|
|
23
22
|
export { setPatchHistoryTTL } from './helpers'
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
|
-
* @description
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* @description Mongoose plugin to track and manage patch history for documents.
|
|
26
|
+
* This plugin initializes hooks for save, update, and delete operations to create
|
|
27
|
+
* and manage patches.
|
|
28
|
+
*
|
|
29
|
+
* @template T
|
|
30
|
+
* @param {Schema<T>} schema - The Mongoose schema to apply the plugin to.
|
|
31
|
+
* @param {PluginOptions<T>} opts - Options for configuring the plugin.
|
|
29
32
|
* @returns {void}
|
|
30
33
|
*/
|
|
31
|
-
export const patchHistoryPlugin = function plugin<T>(schema: Schema<T>, opts:
|
|
34
|
+
export const patchHistoryPlugin = function plugin<T>(schema: Schema<T>, opts: PluginOptions<T>): void {
|
|
32
35
|
// Initialize hooks
|
|
33
36
|
saveHooksInitialize(schema, opts)
|
|
34
37
|
updateHooksInitialize(schema, opts)
|
|
35
38
|
deleteHooksInitialize(schema, opts)
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
/**
|
|
41
|
+
* @description Corner case for insertMany()
|
|
42
|
+
* @param {Array<HydratedDocument<T>>} docs - The documents being inserted.
|
|
43
|
+
* @returns {Promise<void>}
|
|
44
|
+
*/
|
|
38
45
|
schema.post('insertMany', async function (docs) {
|
|
39
46
|
const context = {
|
|
40
47
|
op: 'create',
|
|
@@ -49,6 +56,10 @@ export const patchHistoryPlugin = function plugin<T>(schema: Schema<T>, opts: IP
|
|
|
49
56
|
// In Mongoose 7, doc.deleteOne() returned a promise that resolved to doc.
|
|
50
57
|
// In Mongoose 8, doc.deleteOne() returns a query for easier chaining, as well as consistency with doc.updateOne().
|
|
51
58
|
if (isMongooseLessThan8) {
|
|
59
|
+
/**
|
|
60
|
+
* @description Pre-delete hook for Mongoose 7 and below
|
|
61
|
+
* @returns {Promise<void>}
|
|
62
|
+
*/
|
|
52
63
|
// @ts-expect-error - Mongoose 7 and below
|
|
53
64
|
schema.pre(remove, { document: true, query: false }, async function () {
|
|
54
65
|
// @ts-expect-error - Mongoose 7 and below
|
|
@@ -59,12 +70,17 @@ export const patchHistoryPlugin = function plugin<T>(schema: Schema<T>, opts: IP
|
|
|
59
70
|
}
|
|
60
71
|
})
|
|
61
72
|
|
|
73
|
+
/**
|
|
74
|
+
* @description Post-delete hook for Mongoose 7 and below
|
|
75
|
+
* @param {HydratedDocument<T>} this - The document being deleted.
|
|
76
|
+
* @returns {Promise<void>}
|
|
77
|
+
*/
|
|
62
78
|
// @ts-expect-error - Mongoose 7 and below
|
|
63
79
|
schema.post(remove, { document: true, query: false }, async function (this: HydratedDocument<T>) {
|
|
64
80
|
const original = this.toObject(toObjectOptions) as HydratedDocument<T>
|
|
65
81
|
const model = this.constructor as Model<T>
|
|
66
82
|
|
|
67
|
-
const context:
|
|
83
|
+
const context: PatchContext<T> = {
|
|
68
84
|
op: 'delete',
|
|
69
85
|
modelName: opts.modelName ?? model.modelName,
|
|
70
86
|
collectionName: opts.collectionName ?? model.collection.collectionName,
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Operation } from 'fast-json-patch'
|
|
2
|
+
import type { HydratedDocument, Query, Types } from 'mongoose'
|
|
3
|
+
|
|
4
|
+
export interface History {
|
|
5
|
+
op: string
|
|
6
|
+
modelName: string
|
|
7
|
+
collectionName: string
|
|
8
|
+
collectionId: Types.ObjectId
|
|
9
|
+
version: number
|
|
10
|
+
doc?: object
|
|
11
|
+
user?: object
|
|
12
|
+
reason?: string
|
|
13
|
+
metadata?: object
|
|
14
|
+
patch?: Operation[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PatchEvent<T> {
|
|
18
|
+
oldDoc?: HydratedDocument<T>
|
|
19
|
+
doc?: HydratedDocument<T>
|
|
20
|
+
patch?: Operation[]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PatchContext<T> {
|
|
24
|
+
op: string
|
|
25
|
+
modelName: string
|
|
26
|
+
collectionName: string
|
|
27
|
+
isNew?: boolean
|
|
28
|
+
createdDocs?: HydratedDocument<T>[]
|
|
29
|
+
deletedDocs?: HydratedDocument<T>[]
|
|
30
|
+
ignoreEvent?: boolean
|
|
31
|
+
ignorePatchHistory?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type HookContext<T> = Query<T, T> & { op: string; _context: PatchContext<T> }
|
|
35
|
+
|
|
36
|
+
export type User = Record<string, unknown>
|
|
37
|
+
|
|
38
|
+
export type Metadata = Record<string, unknown>
|
|
39
|
+
|
|
40
|
+
export interface PluginOptions<T> {
|
|
41
|
+
modelName?: string
|
|
42
|
+
collectionName?: string
|
|
43
|
+
eventUpdated?: string
|
|
44
|
+
eventCreated?: string
|
|
45
|
+
eventDeleted?: string
|
|
46
|
+
getUser?: () => Promise<User> | User
|
|
47
|
+
getReason?: () => Promise<string> | string
|
|
48
|
+
getMetadata?: () => Promise<Metadata> | Metadata
|
|
49
|
+
omit?: string[]
|
|
50
|
+
patchHistoryDisabled?: boolean
|
|
51
|
+
preDelete?: (docs: HydratedDocument<T>[]) => Promise<void>
|
|
52
|
+
}
|
package/tests/helpers.test.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import ms from 'ms'
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
3
|
|
|
4
|
-
import History from '../src/models/History'
|
|
5
|
-
|
|
6
4
|
import { setPatchHistoryTTL } from '../src/helpers'
|
|
5
|
+
import { HistoryModel } from '../src/models/History'
|
|
7
6
|
|
|
8
7
|
import type { Mock, MockInstance } from 'vitest'
|
|
9
8
|
|
|
10
9
|
vi.mock('../src/models/History', () => ({
|
|
11
|
-
|
|
10
|
+
HistoryModel: {
|
|
12
11
|
collection: {
|
|
13
12
|
indexes: vi.fn(),
|
|
14
13
|
dropIndex: vi.fn(),
|
|
@@ -22,12 +21,12 @@ const name = 'createdAt_1_TTL'
|
|
|
22
21
|
describe('useTTL', () => {
|
|
23
22
|
let dropIndexSpy: MockInstance
|
|
24
23
|
let createIndexSpy: MockInstance
|
|
25
|
-
const indexes =
|
|
24
|
+
const indexes = HistoryModel.collection.indexes as Mock
|
|
26
25
|
|
|
27
26
|
beforeEach(() => {
|
|
28
27
|
vi.clearAllMocks()
|
|
29
|
-
dropIndexSpy = vi.spyOn(
|
|
30
|
-
createIndexSpy = vi.spyOn(
|
|
28
|
+
dropIndexSpy = vi.spyOn(HistoryModel.collection, 'dropIndex')
|
|
29
|
+
createIndexSpy = vi.spyOn(HistoryModel.collection, 'createIndex')
|
|
31
30
|
})
|
|
32
31
|
|
|
33
32
|
afterEach(() => {
|
package/tests/patch.test.ts
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import mongoose
|
|
3
|
+
import mongoose from 'mongoose'
|
|
4
4
|
|
|
5
5
|
import { bulkPatch, getData, getJsonOmit, getMetadata, getReason, getUser, getValue, updatePatch } from '../src/patch'
|
|
6
6
|
import { patchHistoryPlugin } from '../src/plugin'
|
|
7
7
|
|
|
8
|
-
import UserSchema from './schemas/UserSchema'
|
|
9
|
-
|
|
10
8
|
import { USER_DELETED } from './constants/events'
|
|
9
|
+
import { type User, UserSchema } from './schemas/User'
|
|
11
10
|
|
|
12
11
|
import type { HydratedDocument } from 'mongoose'
|
|
13
|
-
import type IContext from '../src/interfaces/IContext'
|
|
14
|
-
import type { User } from '../src/interfaces/IPluginOptions'
|
|
15
|
-
import type IPluginOptions from '../src/interfaces/IPluginOptions'
|
|
16
|
-
import type IUser from './interfaces/IUser'
|
|
17
12
|
|
|
18
13
|
import { afterEach } from 'node:test'
|
|
19
|
-
import { update } from 'lodash'
|
|
20
14
|
import em from '../src/em'
|
|
15
|
+
import type { PatchContext, PluginOptions } from '../src/types'
|
|
21
16
|
import server from './mongo/server'
|
|
22
17
|
|
|
23
18
|
vi.mock('../src/em', () => ({ default: { emit: vi.fn() } }))
|
|
@@ -30,7 +25,7 @@ describe('patch tests', () => {
|
|
|
30
25
|
patchHistoryDisabled: true,
|
|
31
26
|
})
|
|
32
27
|
|
|
33
|
-
const
|
|
28
|
+
const UserModel = mongoose.model<User>('User', UserSchema)
|
|
34
29
|
|
|
35
30
|
beforeAll(async () => {
|
|
36
31
|
await instance.create()
|
|
@@ -51,8 +46,8 @@ describe('patch tests', () => {
|
|
|
51
46
|
|
|
52
47
|
describe('getObjects', () => {
|
|
53
48
|
it('should omit properties from currentObject and originalObject based on the opts', async () => {
|
|
54
|
-
const original = await
|
|
55
|
-
const current = await
|
|
49
|
+
const original = await UserModel.create({ name: 'John', role: 'user' })
|
|
50
|
+
const current = await UserModel.create({ name: 'John', role: 'admin' })
|
|
56
51
|
|
|
57
52
|
const pluginOptions = {
|
|
58
53
|
omit: ['createdAt'],
|
|
@@ -71,8 +66,8 @@ describe('patch tests', () => {
|
|
|
71
66
|
})
|
|
72
67
|
|
|
73
68
|
it('should not omit properties from currentObject and originalObject if opts is empty', async () => {
|
|
74
|
-
const original = await
|
|
75
|
-
const current = await
|
|
69
|
+
const original = await UserModel.create({ name: 'John', role: 'user' })
|
|
70
|
+
const current = await UserModel.create({ name: 'John', role: 'admin' })
|
|
76
71
|
|
|
77
72
|
const pluginOptions = {}
|
|
78
73
|
|
|
@@ -91,14 +86,14 @@ describe('patch tests', () => {
|
|
|
91
86
|
|
|
92
87
|
describe('bulkPatch', () => {
|
|
93
88
|
it('should emit eventDeleted if opts.patchHistoryDisabled is false', async () => {
|
|
94
|
-
const doc = new
|
|
89
|
+
const doc = new UserModel({ name: 'John', role: 'user' })
|
|
95
90
|
|
|
96
|
-
const pluginOptions:
|
|
91
|
+
const pluginOptions: PluginOptions<User> = {
|
|
97
92
|
eventDeleted: USER_DELETED,
|
|
98
93
|
patchHistoryDisabled: false,
|
|
99
94
|
}
|
|
100
95
|
|
|
101
|
-
const context:
|
|
96
|
+
const context: PatchContext<User> = {
|
|
102
97
|
op: 'deleteOne',
|
|
103
98
|
modelName: 'User',
|
|
104
99
|
collectionName: 'users',
|
|
@@ -110,14 +105,14 @@ describe('patch tests', () => {
|
|
|
110
105
|
})
|
|
111
106
|
|
|
112
107
|
it('should emit eventDeleted if opts.patchHistoryDisabled is true', async () => {
|
|
113
|
-
const doc = new
|
|
108
|
+
const doc = new UserModel({ name: 'John', role: 'user' })
|
|
114
109
|
|
|
115
|
-
const pluginOptions:
|
|
110
|
+
const pluginOptions: PluginOptions<User> = {
|
|
116
111
|
eventDeleted: USER_DELETED,
|
|
117
112
|
patchHistoryDisabled: true,
|
|
118
113
|
}
|
|
119
114
|
|
|
120
|
-
const context:
|
|
115
|
+
const context: PatchContext<User> = {
|
|
121
116
|
op: 'deleteOne',
|
|
122
117
|
modelName: 'User',
|
|
123
118
|
collectionName: 'users',
|
|
@@ -131,27 +126,27 @@ describe('patch tests', () => {
|
|
|
131
126
|
|
|
132
127
|
describe('updatePatch', () => {
|
|
133
128
|
it('should return if one object is empty', async () => {
|
|
134
|
-
const current = await
|
|
129
|
+
const current = await UserModel.create({ name: 'John', role: 'user' })
|
|
135
130
|
|
|
136
|
-
const pluginOptions:
|
|
131
|
+
const pluginOptions: PluginOptions<User> = {
|
|
137
132
|
eventDeleted: USER_DELETED,
|
|
138
133
|
patchHistoryDisabled: true,
|
|
139
134
|
}
|
|
140
135
|
|
|
141
|
-
const context:
|
|
136
|
+
const context: PatchContext<User> = {
|
|
142
137
|
op: 'updateOne',
|
|
143
138
|
modelName: 'User',
|
|
144
139
|
collectionName: 'users',
|
|
145
140
|
}
|
|
146
141
|
|
|
147
|
-
await updatePatch(pluginOptions, context, current, {} as HydratedDocument<
|
|
142
|
+
await updatePatch(pluginOptions, context, current, {} as HydratedDocument<User>)
|
|
148
143
|
expect(em.emit).toHaveBeenCalled()
|
|
149
144
|
})
|
|
150
145
|
})
|
|
151
146
|
|
|
152
147
|
describe('should getUser()', () => {
|
|
153
148
|
it('should return user, reason, metadata', async () => {
|
|
154
|
-
const opts:
|
|
149
|
+
const opts: PluginOptions<User> = {
|
|
155
150
|
getUser: () => ({ name: 'test' }),
|
|
156
151
|
getReason: () => 'test',
|
|
157
152
|
getMetadata: () => ({ test: 'test' }),
|
|
@@ -165,7 +160,7 @@ describe('patch tests', () => {
|
|
|
165
160
|
|
|
166
161
|
describe('should getData()', () => {
|
|
167
162
|
it('should return user, reason, metadata', async () => {
|
|
168
|
-
const opts:
|
|
163
|
+
const opts: PluginOptions<User> = {
|
|
169
164
|
getUser: () => ({ name: 'test' }),
|
|
170
165
|
getReason: () => 'test',
|
|
171
166
|
getMetadata: () => ({ test: 'test' }),
|
|
@@ -175,7 +170,7 @@ describe('patch tests', () => {
|
|
|
175
170
|
})
|
|
176
171
|
|
|
177
172
|
it('should return user, reason, metadata undefined', async () => {
|
|
178
|
-
const opts:
|
|
173
|
+
const opts: PluginOptions<User> = {
|
|
179
174
|
getUser: () => ({ name: 'test' }),
|
|
180
175
|
getReason: () => 'test',
|
|
181
176
|
getMetadata: () => {
|