ts-patch-mongoose 1.1.3 → 1.1.5

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.
@@ -1,94 +1,37 @@
1
1
  import _ from 'lodash';
2
- import omit from 'omit-deep';
3
- import jsonpatch from 'fast-json-patch';
4
2
  import { assign } from 'power-assign';
3
+ import { createPatch, updatePatch, deletePatch } from './patch';
5
4
  import em from './em';
6
- import History from './models/History';
7
5
  const options = {
8
6
  document: false,
9
7
  query: true
10
8
  };
11
- function getObjects(opts, current, original) {
12
- let currentObject = JSON.parse(JSON.stringify(current));
13
- let originalObject = JSON.parse(JSON.stringify(original));
14
- if (opts.omit) {
15
- currentObject = omit(currentObject, opts.omit);
16
- originalObject = omit(originalObject, opts.omit);
17
- }
18
- return { currentObject, originalObject };
19
- }
20
- async function updatePatch(opts, context, current, original) {
21
- const { currentObject, originalObject } = getObjects(opts, current, original);
22
- if (_.isEmpty(originalObject) || _.isEmpty(currentObject))
23
- return;
24
- const patch = jsonpatch.compare(originalObject, currentObject, true);
25
- if (_.isEmpty(patch))
26
- return;
27
- if (opts.eventUpdated) {
28
- em.emit(opts.eventUpdated, { oldDoc: original, doc: current, patch });
29
- }
30
- if (opts.patchHistoryDisabled)
31
- return;
32
- let version = 0;
33
- const lastHistory = await History.findOne({ collectionId: original._id }).sort('-version').exec();
34
- if (lastHistory && lastHistory.version >= 0) {
35
- version = lastHistory.version + 1;
36
- }
37
- await History.create({
38
- op: context.op,
39
- modelName: context.modelName,
40
- collectionName: context.collectionName,
41
- collectionId: original._id,
42
- patch,
43
- version
44
- });
45
- }
46
- async function bulkPatch(opts, context, eventKey, docsKey) {
47
- const event = opts[eventKey];
48
- const docs = context[docsKey];
49
- const key = eventKey === 'eventCreated' ? 'doc' : 'oldDoc';
50
- if (_.isEmpty(docs) || (!event && opts.patchHistoryDisabled))
51
- return;
52
- const chunks = _.chunk(docs, 1000);
53
- for await (const chunk of chunks) {
54
- const bulk = [];
55
- for (const doc of chunk) {
56
- if (event)
57
- em.emit(event, { [key]: doc });
58
- if (!opts.patchHistoryDisabled) {
59
- bulk.push({
60
- insertOne: {
61
- document: {
62
- op: context.op,
63
- modelName: context.modelName,
64
- collectionName: context.collectionName,
65
- collectionId: doc._id,
66
- doc,
67
- version: 0
68
- }
69
- }
70
- });
71
- }
72
- }
73
- if (!opts.patchHistoryDisabled) {
74
- await History
75
- .bulkWrite(bulk, { ordered: false })
76
- .catch((err) => {
77
- console.error(err);
78
- });
79
- }
80
- }
81
- }
82
- async function createPatch(opts, context) {
83
- await bulkPatch(opts, context, 'eventCreated', 'createdDocs');
84
- }
85
- async function deletePatch(opts, context) {
86
- await bulkPatch(opts, context, 'eventDeleted', 'deletedDocs');
87
- }
9
+ const toObjectOptions = {
10
+ depopulate: true,
11
+ virtuals: false
12
+ };
13
+ const updateMethods = [
14
+ 'update',
15
+ 'updateOne',
16
+ 'replaceOne',
17
+ 'updateMany',
18
+ 'findOneAndUpdate',
19
+ 'findOneAndReplace',
20
+ 'findByIdAndUpdate'
21
+ ];
22
+ const deleteMethods = [
23
+ 'remove',
24
+ 'findOneAndDelete',
25
+ 'findOneAndRemove',
26
+ 'findByIdAndDelete',
27
+ 'findByIdAndRemove',
28
+ 'deleteOne',
29
+ 'deleteMany'
30
+ ];
88
31
  export const patchEventEmitter = em;
89
32
  export const patchHistoryPlugin = function plugin(schema, opts) {
90
33
  schema.pre('save', async function (next) {
91
- const current = this.toObject({ depopulate: true });
34
+ const current = this.toObject(toObjectOptions);
92
35
  const model = this.constructor;
93
36
  const context = {
94
37
  op: this.isNew ? 'create' : 'update',
@@ -96,21 +39,16 @@ export const patchHistoryPlugin = function plugin(schema, opts) {
96
39
  collectionName: opts.collectionName ?? model.collection.collectionName,
97
40
  createdDocs: [current]
98
41
  };
99
- try {
100
- if (this.isNew) {
101
- await createPatch(opts, context);
102
- }
103
- else {
104
- const original = await model.findById(current._id).exec();
105
- if (original) {
106
- await updatePatch(opts, context, current, original);
107
- }
108
- }
109
- next();
42
+ if (this.isNew) {
43
+ await createPatch(opts, context);
110
44
  }
111
- catch (error) {
112
- next(error);
45
+ else {
46
+ const original = await model.findById(current._id).exec();
47
+ if (original) {
48
+ await updatePatch(opts, context, current, original);
49
+ }
113
50
  }
51
+ next();
114
52
  });
115
53
  schema.post('insertMany', async function (docs) {
116
54
  const context = {
@@ -121,7 +59,7 @@ export const patchHistoryPlugin = function plugin(schema, opts) {
121
59
  };
122
60
  await createPatch(opts, context);
123
61
  });
124
- schema.pre(['update', 'updateOne', 'updateMany', 'findOneAndUpdate', 'findOneAndReplace'], async function (next) {
62
+ schema.pre(updateMethods, async function (next) {
125
63
  const filter = this.getFilter();
126
64
  const update = this.getUpdate();
127
65
  const options = this.getOptions();
@@ -133,70 +71,54 @@ export const patchHistoryPlugin = function plugin(schema, opts) {
133
71
  collectionName: opts.collectionName ?? this.model.collection.collectionName,
134
72
  isNew: options.upsert && count === 0
135
73
  };
136
- try {
137
- const keys = _.keys(update).filter((key) => key.startsWith('$'));
138
- if (update && !_.isEmpty(keys)) {
139
- _.forEach(keys, (key) => {
140
- commands.push({ [key]: update[key] });
141
- delete update[key];
142
- });
143
- }
144
- const cursor = this.model.find(filter).cursor();
145
- await cursor.eachAsync(async (doc) => {
146
- let current = doc.toObject({ depopulate: true });
147
- const original = doc.toObject({ depopulate: true });
148
- current = assign(current, update);
149
- _.forEach(commands, (command) => {
150
- try {
151
- current = assign(current, command);
152
- }
153
- catch (error) {
154
- }
155
- });
156
- await updatePatch(opts, this._context, current, original);
74
+ const keys = _.keys(update).filter((key) => key.startsWith('$'));
75
+ if (update && !_.isEmpty(keys)) {
76
+ _.forEach(keys, (key) => {
77
+ commands.push({ [key]: update[key] });
78
+ delete update[key];
157
79
  });
158
- next();
159
- }
160
- catch (error) {
161
- next(error);
162
80
  }
163
- });
164
- schema.post(['update', 'updateOne', 'updateMany', 'findOneAndUpdate'], async function () {
165
- const update = this.getUpdate();
166
- if (update && this._context.isNew) {
167
- const cursor = this.model.findOne(update).cursor();
168
- await cursor.eachAsync((doc) => {
169
- const current = doc.toObject({ depopulate: true });
170
- if (this._context.createdDocs) {
171
- this._context.createdDocs.push(current);
81
+ const cursor = this.model.find(filter).cursor();
82
+ await cursor.eachAsync(async (doc) => {
83
+ let current = doc.toObject(toObjectOptions);
84
+ const original = doc.toObject(toObjectOptions);
85
+ current = assign(current, update);
86
+ _.forEach(commands, (command) => {
87
+ try {
88
+ current = assign(current, command);
172
89
  }
173
- else {
174
- this._context.createdDocs = [current];
90
+ catch (error) {
175
91
  }
176
92
  });
93
+ await updatePatch(opts, this._context, current, original);
94
+ });
95
+ next();
96
+ });
97
+ schema.post(updateMethods, async function () {
98
+ const update = this.getUpdate();
99
+ if (!update || !this._context.isNew)
100
+ return;
101
+ const found = await this.model.findOne(update).exec();
102
+ if (found) {
103
+ const current = found.toObject(toObjectOptions);
104
+ this._context.createdDocs = [current];
177
105
  await createPatch(opts, this._context);
178
106
  }
179
107
  });
180
- schema.pre('remove', async function (next) {
181
- const original = this.toObject({ depopulate: true });
108
+ schema.post('remove', async function () {
109
+ const original = this.toObject(toObjectOptions);
182
110
  const model = this.constructor;
183
111
  const context = {
184
112
  op: 'delete',
185
113
  modelName: opts.modelName ?? model.modelName,
186
114
  collectionName: opts.collectionName ?? model.collection.collectionName
187
115
  };
188
- try {
189
- if (opts.eventDeleted) {
190
- em.emit(opts.eventDeleted, { oldDoc: original });
191
- }
192
- await deletePatch(opts, context);
193
- next();
194
- }
195
- catch (error) {
196
- next(error);
116
+ if (opts.eventDeleted) {
117
+ em.emit(opts.eventDeleted, { oldDoc: original });
197
118
  }
119
+ await deletePatch(opts, context);
198
120
  });
199
- schema.pre(['remove', 'findOneAndDelete', 'findOneAndRemove', 'deleteOne', 'deleteMany'], options, async function (next) {
121
+ schema.pre(deleteMethods, options, async function (next) {
200
122
  const filter = this.getFilter();
201
123
  const options = this.getOptions();
202
124
  const ignore = options.__ignore;
@@ -219,12 +141,12 @@ export const patchHistoryPlugin = function plugin(schema, opts) {
219
141
  this._context.deletedDocs = [doc];
220
142
  }
221
143
  }
222
- if (opts.preDeleteManyCallback && _.isArray(this._context.deletedDocs) && !_.isEmpty(this._context.deletedDocs)) {
223
- await opts.preDeleteManyCallback(this._context.deletedDocs);
144
+ if (opts.preDeleteCallback && _.isArray(this._context.deletedDocs) && !_.isEmpty(this._context.deletedDocs)) {
145
+ await opts.preDeleteCallback(this._context.deletedDocs);
224
146
  }
225
147
  next();
226
148
  });
227
- schema.post(['remove', 'findOneAndDelete', 'findOneAndRemove', 'deleteOne', 'deleteMany'], options, async function () {
149
+ schema.post(deleteMethods, options, async function () {
228
150
  await deletePatch(opts, this._context);
229
151
  });
230
152
  };
@@ -6,7 +6,7 @@ interface IPluginOptions<T> {
6
6
  eventCreated?: string;
7
7
  eventDeleted?: string;
8
8
  patchHistoryDisabled?: boolean;
9
- preDeleteManyCallback?: (docs: HydratedDocument<T>[]) => Promise<void>;
9
+ preDeleteCallback?: (docs: HydratedDocument<T>[]) => Promise<void>;
10
10
  omit?: string[];
11
11
  }
12
12
  export default IPluginOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"IPluginOptions.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/IPluginOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAEhD,UAAU,cAAc,CAAC,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"IPluginOptions.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/IPluginOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAEhD,UAAU,cAAc,CAAC,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,eAAe,cAAc,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { HydratedDocument } from 'mongoose';
2
+ import type IPluginOptions from './interfaces/IPluginOptions';
3
+ import type IContext from './interfaces/IContext';
4
+ export declare function getObjects<T>(opts: IPluginOptions<T>, current: HydratedDocument<T>, original: HydratedDocument<T>): {
5
+ currentObject: Partial<T>;
6
+ originalObject: Partial<T>;
7
+ };
8
+ export declare function bulkPatch<T>(opts: IPluginOptions<T>, context: IContext<T>, eventKey: 'eventCreated' | 'eventDeleted', docsKey: 'createdDocs' | 'deletedDocs'): Promise<void>;
9
+ export declare function createPatch<T>(opts: IPluginOptions<T>, context: IContext<T>): Promise<void>;
10
+ export declare function updatePatch<T>(opts: IPluginOptions<T>, context: IContext<T>, current: HydratedDocument<T>, original: HydratedDocument<T>): Promise<void>;
11
+ export declare function deletePatch<T>(opts: IPluginOptions<T>, context: IContext<T>): Promise<void>;
12
+ //# sourceMappingURL=patch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../../src/patch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAS,MAAM,UAAU,CAAA;AAEvD,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAA;AAC7D,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAA;AAKjD,wBAAgB,UAAU,CAAC,CAAC,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CAAE,CAU9K;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,GAAG,cAAc,EAAE,OAAO,EAAE,aAAa,GAAG,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCnL;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAElG;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B/J;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAG,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAElG"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAKA,OAAO,KAAK,EAAmC,KAAK,EAAiB,MAAM,EAAS,MAAM,UAAU,CAAA;AAEpG,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAA;AA2G7D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;CAAK,CAAA;AAQnC,eAAO,MAAM,kBAAkB,oOAAoE,IA2JlG,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAGA,OAAO,KAAK,EAAoB,KAAK,EAA2B,MAAM,EAAmB,MAAM,UAAU,CAAA;AAEzG,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAA;AAwC7D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;CAAK,CAAA;AAQnC,eAAO,MAAM,kBAAkB,oOAAoE,IAgJlG,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-patch-mongoose",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Patch history & events for mongoose models",
5
5
  "author": "Alex Eagle",
6
6
  "license": "MIT",
@@ -83,12 +83,12 @@
83
83
  "devDependencies": {
84
84
  "@shelf/jest-mongodb": "4.1.7",
85
85
  "@swc/cli": "0.1.62",
86
- "@swc/core": "1.3.49",
86
+ "@swc/core": "1.3.50",
87
87
  "@swc/helpers": "0.5.0",
88
- "@swc/jest": "0.2.24",
88
+ "@swc/jest": "0.2.26",
89
89
  "@swc/register": "0.1.10",
90
90
  "@types/jest": "29.5.0",
91
- "@types/lodash": "4.14.192",
91
+ "@types/lodash": "4.14.194",
92
92
  "@types/node": "18.15.11",
93
93
  "@typescript-eslint/eslint-plugin": "5.58.0",
94
94
  "@typescript-eslint/parser": "5.58.0",
@@ -100,6 +100,7 @@
100
100
  "eslint-plugin-n": "15.7.0",
101
101
  "eslint-plugin-node": "11.1.0",
102
102
  "eslint-plugin-promise": "6.1.1",
103
+ "eslint-plugin-sonarjs": "0.19.0",
103
104
  "jest": "29.5.0",
104
105
  "merge": "2.1.1",
105
106
  "mongoose": "6.10.5",
@@ -7,7 +7,7 @@ interface IPluginOptions<T> {
7
7
  eventCreated?: string
8
8
  eventDeleted?: string
9
9
  patchHistoryDisabled?: boolean
10
- preDeleteManyCallback?: (docs: HydratedDocument<T>[]) => Promise<void>
10
+ preDeleteCallback?: (docs: HydratedDocument<T>[]) => Promise<void>
11
11
  omit?: string[]
12
12
  }
13
13
 
package/src/patch.ts ADDED
@@ -0,0 +1,101 @@
1
+ import _ from 'lodash'
2
+ import omit from 'omit-deep'
3
+ import jsonpatch from 'fast-json-patch'
4
+
5
+ import type { HydratedDocument, Types } from 'mongoose'
6
+
7
+ import type IPluginOptions from './interfaces/IPluginOptions'
8
+ import type IContext from './interfaces/IContext'
9
+
10
+ import History from './models/History'
11
+ import em from './em'
12
+
13
+ export function getObjects<T> (opts: IPluginOptions<T>, current: HydratedDocument<T>, original: HydratedDocument<T>): { currentObject: Partial<T>, originalObject: Partial<T> } {
14
+ let currentObject = JSON.parse(JSON.stringify(current)) as Partial<T>
15
+ let originalObject = JSON.parse(JSON.stringify(original)) as Partial<T>
16
+
17
+ if (opts.omit) {
18
+ currentObject = omit(currentObject, opts.omit)
19
+ originalObject = omit(originalObject, opts.omit)
20
+ }
21
+
22
+ return { currentObject, originalObject }
23
+ }
24
+
25
+ export async function bulkPatch<T> (opts: IPluginOptions<T>, context: IContext<T>, eventKey: 'eventCreated' | 'eventDeleted', docsKey: 'createdDocs' | 'deletedDocs'): Promise<void> {
26
+ const event = opts[eventKey]
27
+ const docs = context[docsKey]
28
+ const key = eventKey === 'eventCreated' ? 'doc' : 'oldDoc'
29
+
30
+ if (_.isEmpty(docs) || (!event && opts.patchHistoryDisabled)) return
31
+
32
+ const chunks = _.chunk(docs, 1000)
33
+
34
+ for await (const chunk of chunks) {
35
+ const bulk = []
36
+
37
+ for (const doc of chunk) {
38
+ if (event) em.emit(event, { [key]: doc })
39
+
40
+ if (!opts.patchHistoryDisabled) {
41
+ bulk.push({
42
+ insertOne: {
43
+ document: {
44
+ op: context.op,
45
+ modelName: context.modelName,
46
+ collectionName: context.collectionName,
47
+ collectionId: doc._id as Types.ObjectId,
48
+ doc,
49
+ version: 0
50
+ }
51
+ }
52
+ })
53
+ }
54
+ }
55
+
56
+ if (!opts.patchHistoryDisabled) {
57
+ await History.bulkWrite(bulk, { ordered: false })
58
+ }
59
+ }
60
+ }
61
+
62
+ export async function createPatch<T> (opts: IPluginOptions<T>, context: IContext<T>): Promise<void> {
63
+ await bulkPatch(opts, context, 'eventCreated', 'createdDocs')
64
+ }
65
+
66
+ export async function updatePatch<T> (opts: IPluginOptions<T>, context: IContext<T>, current: HydratedDocument<T>, original: HydratedDocument<T>): Promise<void> {
67
+ const { currentObject, originalObject } = getObjects(opts, current, original)
68
+
69
+ if (_.isEmpty(originalObject) || _.isEmpty(currentObject)) return
70
+
71
+ const patch = jsonpatch.compare(originalObject, currentObject, true)
72
+
73
+ if (_.isEmpty(patch)) return
74
+
75
+ if (opts.eventUpdated) {
76
+ em.emit(opts.eventUpdated, { oldDoc: original, doc: current, patch })
77
+ }
78
+
79
+ if (opts.patchHistoryDisabled) return
80
+
81
+ let version = 0
82
+
83
+ const lastHistory = await History.findOne({ collectionId: original._id as Types.ObjectId }).sort('-version').exec()
84
+
85
+ if (lastHistory && lastHistory.version >= 0) {
86
+ version = lastHistory.version + 1
87
+ }
88
+
89
+ await History.create({
90
+ op: context.op,
91
+ modelName: context.modelName,
92
+ collectionName: context.collectionName,
93
+ collectionId: original._id as Types.ObjectId,
94
+ patch,
95
+ version
96
+ })
97
+ }
98
+
99
+ export async function deletePatch<T> (opts: IPluginOptions<T>, context: IContext<T>): Promise<void> {
100
+ await bulkPatch(opts, context, 'eventDeleted', 'deletedDocs')
101
+ }