mongodb-dynamic-api 4.6.0 → 4.6.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  Changelog
2
2
 
3
+ ## [4.6.1](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v4.6.0...v4.6.1) (2026-03-27)
4
+
3
5
  ## [4.6.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v4.5.0...v4.6.0) (2026-03-26)
4
6
 
5
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb-dynamic-api",
3
- "version": "4.6.0",
3
+ "version": "4.6.1",
4
4
  "description": "Auto generated CRUD API for MongoDB using NestJS",
5
5
  "readmeFilename": "README.md",
6
6
  "main": "index.js",
@@ -36,7 +36,7 @@ type BeforeSaveCallback<Entity extends BaseEntity, Context = Record<string, unkn
36
36
  type BeforeSaveListCallback<Entity extends BaseEntity, Context = Record<string, unknown>, User = unknown> = (entities: Entity[] | undefined, context: Context, methods: CallbackMethods, user?: User) => Promise<Partial<Entity>[]>;
37
37
  type BeforeSaveDeleteCallback<Entity extends BaseEntity, Context = Record<string, unknown>, User = unknown> = (entity: Entity | undefined, context: Context, methods: CallbackMethods, user?: User) => Promise<void>;
38
38
  type BeforeSaveDeleteManyCallback<Entity extends BaseEntity, Context = Record<string, unknown>, User = unknown> = (entities: Entity[], context: Context, methods: CallbackMethods, user?: User) => Promise<void>;
39
- type AnyBeforeSaveCallback<Entity extends BaseEntity, User = unknown> = BeforeSaveCallback<Entity, any, User> | BeforeSaveListCallback<Entity, any, User> | BeforeSaveDeleteCallback<Entity, any, User> | BeforeSaveDeleteManyCallback<Entity, any, User>;
39
+ type AnyBeforeSaveCallback<Entity extends BaseEntity, User = unknown> = BeforeSaveCallback<Entity, unknown, User> | BeforeSaveListCallback<Entity, unknown, User> | BeforeSaveDeleteCallback<Entity, unknown, User> | BeforeSaveDeleteManyCallback<Entity, unknown, User>;
40
40
  type DynamicApiServiceBeforeSaveCreateContext<Entity extends BaseEntity> = BeforeSaveCreateContext<Entity>;
41
41
  type DynamicApiServiceBeforeSaveCreateManyContext<Entity extends BaseEntity> = BeforeSaveCreateManyContext<Entity>;
42
42
  type DynamicApiServiceBeforeSaveUpdateContext<Entity extends BaseEntity> = BeforeSaveUpdateContext<Entity>;
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "4.6.0"
2
+ "version": "4.6.1"
3
3
  }
@@ -15,7 +15,7 @@ const mongoose_2 = require("mongoose");
15
15
  const src_1 = require("../../src");
16
16
  const e2e_setup_1 = require("../e2e.setup");
17
17
  require("dotenv/config");
18
- describe('Callbacks receive authenticated user (e2e)', () => {
18
+ function buildEntities(collectionSuffix) {
19
19
  let UserEntity = class UserEntity extends src_1.BaseEntity {
20
20
  };
21
21
  __decorate([
@@ -27,7 +27,7 @@ describe('Callbacks receive authenticated user (e2e)', () => {
27
27
  __metadata("design:type", String)
28
28
  ], UserEntity.prototype, "password", void 0);
29
29
  UserEntity = __decorate([
30
- (0, mongoose_1.Schema)({ collection: 'users-cb' })
30
+ (0, mongoose_1.Schema)({ collection: `users-${collectionSuffix}` })
31
31
  ], UserEntity);
32
32
  let ItemEntity = class ItemEntity extends src_1.BaseEntity {
33
33
  };
@@ -44,7 +44,7 @@ describe('Callbacks receive authenticated user (e2e)', () => {
44
44
  __metadata("design:type", String)
45
45
  ], ItemEntity.prototype, "updatedBy", void 0);
46
46
  ItemEntity = __decorate([
47
- (0, mongoose_1.Schema)({ collection: 'items-cb' })
47
+ (0, mongoose_1.Schema)({ collection: `items-${collectionSuffix}` })
48
48
  ], ItemEntity);
49
49
  let AuditLogEntity = class AuditLogEntity extends src_1.BaseEntity {
50
50
  };
@@ -61,161 +61,177 @@ describe('Callbacks receive authenticated user (e2e)', () => {
61
61
  __metadata("design:type", String)
62
62
  ], AuditLogEntity.prototype, "performedBy", void 0);
63
63
  AuditLogEntity = __decorate([
64
- (0, mongoose_1.Schema)({ collection: 'audit-logs-cb' })
64
+ (0, mongoose_1.Schema)({ collection: `audit-logs-${collectionSuffix}` })
65
65
  ], AuditLogEntity);
66
+ return { UserEntity, ItemEntity, AuditLogEntity };
67
+ }
68
+ class ItemAggregateQuery {
69
+ static toPipeline(query) {
70
+ return [{ $match: query.name ? { name: query.name } : {} }];
71
+ }
72
+ }
73
+ function buildCallbacks(AuditLogEntity, actionPrefix) {
74
+ const email = (user) => user?.email ?? 'anonymous';
66
75
  const createOneBeforeSave = async (_entity, context, _methods, user) => {
67
- const u = user;
68
- return { ...context.toCreate, createdBy: u?.email ?? 'anonymous' };
76
+ return { ...context.toCreate, createdBy: email(user) };
69
77
  };
70
78
  const createOneAfterSave = async (entity, methods, user) => {
71
- const u = user;
72
79
  await methods.createOneDocument(AuditLogEntity, {
73
- action: 'CreateOne',
80
+ action: `${actionPrefix}CreateOne`,
74
81
  entityId: entity.id,
75
- performedBy: u?.email ?? 'anonymous',
82
+ performedBy: email(user),
76
83
  });
77
84
  };
78
85
  const createManyBeforeSave = async (_entities, context, _methods, user) => {
79
- const u = user;
80
- return context.toCreate.map((item) => ({ ...item, createdBy: u?.email ?? 'anonymous' }));
86
+ return context.toCreate.map((item) => ({ ...item, createdBy: email(user) }));
81
87
  };
82
88
  const createManyAfterSave = async (entity, methods, user) => {
83
- const u = user;
84
89
  await methods.createOneDocument(AuditLogEntity, {
85
- action: 'CreateMany',
90
+ action: `${actionPrefix}CreateMany`,
86
91
  entityId: entity.id,
87
- performedBy: u?.email ?? 'anonymous',
92
+ performedBy: email(user),
88
93
  });
89
94
  };
90
95
  const updateOneBeforeSave = async (_entity, context, _methods, user) => {
91
- const u = user;
92
- return { ...context.update, updatedBy: u?.email ?? 'anonymous' };
96
+ return { ...context.update, updatedBy: email(user) };
93
97
  };
94
98
  const updateOneAfterSave = async (entity, methods, user) => {
95
- const u = user;
96
99
  await methods.createOneDocument(AuditLogEntity, {
97
- action: 'UpdateOne',
100
+ action: `${actionPrefix}UpdateOne`,
98
101
  entityId: entity.id,
99
- performedBy: u?.email ?? 'anonymous',
102
+ performedBy: email(user),
100
103
  });
101
104
  };
102
105
  const updateManyBeforeSave = async (entities, context, _methods, user) => {
103
- const u = user;
104
- return entities.map(() => ({ ...context.update, updatedBy: u?.email ?? 'anonymous' }));
106
+ return entities.map(() => ({ ...context.update, updatedBy: email(user) }));
105
107
  };
106
108
  const updateManyAfterSave = async (entity, methods, user) => {
107
- const u = user;
108
109
  await methods.createOneDocument(AuditLogEntity, {
109
- action: 'UpdateMany',
110
+ action: `${actionPrefix}UpdateMany`,
110
111
  entityId: entity.id,
111
- performedBy: u?.email ?? 'anonymous',
112
+ performedBy: email(user),
112
113
  });
113
114
  };
114
115
  const replaceOneBeforeSave = async (_entity, context, _methods, user) => {
115
- const u = user;
116
- return { ...context.replacement, updatedBy: u?.email ?? 'anonymous' };
116
+ return { ...context.replacement, updatedBy: email(user) };
117
117
  };
118
118
  const replaceOneAfterSave = async (entity, methods, user) => {
119
- const u = user;
120
119
  await methods.createOneDocument(AuditLogEntity, {
121
- action: 'ReplaceOne',
120
+ action: `${actionPrefix}ReplaceOne`,
122
121
  entityId: entity.id,
123
- performedBy: u?.email ?? 'anonymous',
122
+ performedBy: email(user),
124
123
  });
125
124
  };
126
125
  const duplicateOneBeforeSave = async (_entity, context, _methods, user) => {
127
- const u = user;
128
- return { ...(context.override ?? {}), createdBy: u?.email ?? 'anonymous' };
126
+ return { ...(context.override ?? {}), createdBy: email(user) };
129
127
  };
130
128
  const duplicateOneAfterSave = async (entity, methods, user) => {
131
- const u = user;
132
129
  await methods.createOneDocument(AuditLogEntity, {
133
- action: 'DuplicateOne',
130
+ action: `${actionPrefix}DuplicateOne`,
134
131
  entityId: entity.id,
135
- performedBy: u?.email ?? 'anonymous',
132
+ performedBy: email(user),
136
133
  });
137
134
  };
138
135
  const duplicateManyBeforeSave = async (entities, context, _methods, user) => {
139
- const u = user;
140
136
  return entities.map((e) => ({
141
137
  name: e.name,
142
138
  ...(context.override ?? {}),
143
- createdBy: u?.email ?? 'anonymous',
139
+ createdBy: email(user),
144
140
  }));
145
141
  };
146
142
  const duplicateManyAfterSave = async (entity, methods, user) => {
147
- const u = user;
148
143
  await methods.createOneDocument(AuditLogEntity, {
149
- action: 'DuplicateMany',
144
+ action: `${actionPrefix}DuplicateMany`,
150
145
  entityId: entity.id,
151
- performedBy: u?.email ?? 'anonymous',
146
+ performedBy: email(user),
152
147
  });
153
148
  };
154
149
  const deleteOneBeforeSave = async (entity, _context, methods, user) => {
155
- const u = user;
156
150
  if (entity) {
157
151
  await methods.createOneDocument(AuditLogEntity, {
158
- action: 'DeleteOne-before',
152
+ action: `${actionPrefix}DeleteOne-before`,
159
153
  entityId: entity.id,
160
- performedBy: u?.email ?? 'anonymous',
154
+ performedBy: email(user),
161
155
  });
162
156
  }
163
157
  };
164
158
  const deleteOneAfterSave = async (entity, methods, user) => {
165
- const u = user;
166
159
  await methods.createOneDocument(AuditLogEntity, {
167
- action: 'DeleteOne',
160
+ action: `${actionPrefix}DeleteOne`,
168
161
  entityId: entity.id,
169
- performedBy: u?.email ?? 'anonymous',
162
+ performedBy: email(user),
170
163
  });
171
164
  };
172
165
  const deleteManyBeforeSave = async (entities, _context, methods, user) => {
173
- const u = user;
174
- for (const entity of entities) {
175
- await methods.createOneDocument(AuditLogEntity, {
176
- action: 'DeleteMany-before',
177
- entityId: entity._id?.toString() ?? entity.id,
178
- performedBy: u?.email ?? 'anonymous',
179
- });
180
- }
166
+ await Promise.all(entities.map((entity) => methods.createOneDocument(AuditLogEntity, {
167
+ action: `${actionPrefix}DeleteMany-before`,
168
+ entityId: entity._id?.toString() ?? entity.id,
169
+ performedBy: email(user),
170
+ })));
181
171
  };
182
172
  const deleteManyAfterSave = async (entity, methods, user) => {
183
- const u = user;
184
173
  await methods.createOneDocument(AuditLogEntity, {
185
- action: 'DeleteMany',
174
+ action: `${actionPrefix}DeleteMany`,
186
175
  entityId: entity.id,
187
- performedBy: u?.email ?? 'anonymous',
176
+ performedBy: email(user),
188
177
  });
189
178
  };
190
179
  const getOneAfterSave = async (entity, methods, user) => {
191
- const u = user;
192
180
  await methods.createOneDocument(AuditLogEntity, {
193
- action: 'GetOne',
181
+ action: `${actionPrefix}GetOne`,
194
182
  entityId: entity.id,
195
- performedBy: u?.email ?? 'anonymous',
183
+ performedBy: email(user),
196
184
  });
197
185
  };
198
186
  const getManyAfterSave = async (entity, methods, user) => {
199
- const u = user;
200
187
  await methods.createOneDocument(AuditLogEntity, {
201
- action: 'GetMany',
188
+ action: `${actionPrefix}GetMany`,
202
189
  entityId: entity.id,
203
- performedBy: u?.email ?? 'anonymous',
190
+ performedBy: email(user),
204
191
  });
205
192
  };
206
- const routes = [
207
- { type: 'CreateOne', callback: createOneAfterSave, beforeSaveCallback: createOneBeforeSave },
208
- { type: 'CreateMany', callback: createManyAfterSave, beforeSaveCallback: createManyBeforeSave },
209
- { type: 'UpdateOne', callback: updateOneAfterSave, beforeSaveCallback: updateOneBeforeSave },
210
- { type: 'UpdateMany', callback: updateManyAfterSave, beforeSaveCallback: updateManyBeforeSave },
211
- { type: 'ReplaceOne', callback: replaceOneAfterSave, beforeSaveCallback: replaceOneBeforeSave },
212
- { type: 'DuplicateOne', callback: duplicateOneAfterSave, beforeSaveCallback: duplicateOneBeforeSave },
213
- { type: 'DuplicateMany', callback: duplicateManyAfterSave, beforeSaveCallback: duplicateManyBeforeSave },
214
- { type: 'DeleteOne', callback: deleteOneAfterSave, beforeSaveCallback: deleteOneBeforeSave },
215
- { type: 'DeleteMany', callback: deleteManyAfterSave, beforeSaveCallback: deleteManyBeforeSave },
216
- { type: 'GetOne', callback: getOneAfterSave },
217
- { type: 'GetMany', callback: getManyAfterSave },
193
+ const aggregateAfterSave = async (entity, methods, user) => {
194
+ await methods.createOneDocument(AuditLogEntity, {
195
+ action: `${actionPrefix}Aggregate`,
196
+ entityId: entity.id,
197
+ performedBy: email(user),
198
+ });
199
+ };
200
+ return {
201
+ createOneBeforeSave, createOneAfterSave,
202
+ createManyBeforeSave, createManyAfterSave,
203
+ updateOneBeforeSave, updateOneAfterSave,
204
+ updateManyBeforeSave, updateManyAfterSave,
205
+ replaceOneBeforeSave, replaceOneAfterSave,
206
+ duplicateOneBeforeSave, duplicateOneAfterSave,
207
+ duplicateManyBeforeSave, duplicateManyAfterSave,
208
+ deleteOneBeforeSave, deleteOneAfterSave,
209
+ deleteManyBeforeSave, deleteManyAfterSave,
210
+ getOneAfterSave, getManyAfterSave,
211
+ aggregateAfterSave,
212
+ };
213
+ }
214
+ function buildRoutes(cb, opts) {
215
+ const ws = opts?.webSocket ? { webSocket: true } : {};
216
+ return [
217
+ { type: 'CreateOne', ...ws, callback: cb.createOneAfterSave, beforeSaveCallback: cb.createOneBeforeSave },
218
+ { type: 'CreateMany', ...ws, callback: cb.createManyAfterSave, beforeSaveCallback: cb.createManyBeforeSave },
219
+ { type: 'UpdateOne', ...ws, callback: cb.updateOneAfterSave, beforeSaveCallback: cb.updateOneBeforeSave },
220
+ { type: 'UpdateMany', ...ws, callback: cb.updateManyAfterSave, beforeSaveCallback: cb.updateManyBeforeSave },
221
+ { type: 'ReplaceOne', ...ws, callback: cb.replaceOneAfterSave, beforeSaveCallback: cb.replaceOneBeforeSave },
222
+ { type: 'DuplicateOne', ...ws, callback: cb.duplicateOneAfterSave, beforeSaveCallback: cb.duplicateOneBeforeSave },
223
+ { type: 'DuplicateMany', ...ws, callback: cb.duplicateManyAfterSave, beforeSaveCallback: cb.duplicateManyBeforeSave },
224
+ { type: 'DeleteOne', ...ws, callback: cb.deleteOneAfterSave, beforeSaveCallback: cb.deleteOneBeforeSave },
225
+ { type: 'DeleteMany', ...ws, callback: cb.deleteManyAfterSave, beforeSaveCallback: cb.deleteManyBeforeSave },
226
+ { type: 'GetOne', ...ws, callback: cb.getOneAfterSave },
227
+ { type: 'GetMany', ...ws, callback: cb.getManyAfterSave },
228
+ { type: 'Aggregate', ...ws, subPath: 'aggregate', dTOs: { query: ItemAggregateQuery }, callback: cb.aggregateAfterSave },
218
229
  ];
230
+ }
231
+ describe('Callbacks receive authenticated user (e2e)', () => {
232
+ const { UserEntity, ItemEntity, AuditLogEntity } = buildEntities('cb');
233
+ const callbacks = buildCallbacks(AuditLogEntity, '');
234
+ const routes = buildRoutes(callbacks);
219
235
  let accessToken;
220
236
  const userEmail = 'cb-test@test.co';
221
237
  const userPassword = 'test';
@@ -394,208 +410,26 @@ describe('Callbacks receive authenticated user (e2e)', () => {
394
410
  expect(logs.every((l) => l.performedBy === userEmail)).toBe(true);
395
411
  });
396
412
  });
413
+ describe('Aggregate', () => {
414
+ it('afterSave callback should create audit logs with user for each aggregated entity', async () => {
415
+ await e2e_setup_1.server.post('/items/many', { list: [{ name: 'agg-1' }, { name: 'agg-2' }] }, auth());
416
+ const { body: items, status } = await e2e_setup_1.server.get('/items/aggregate', { ...auth(), query: { name: 'agg-1' } });
417
+ expect(status).toBe(200);
418
+ expect(items).toHaveLength(1);
419
+ expect(items[0].name).toBe('agg-1');
420
+ const logs = await getAuditLogs('Aggregate');
421
+ expect(logs).toHaveLength(1);
422
+ expect(logs[0]).toEqual(expect.objectContaining({
423
+ entityId: items[0].id,
424
+ performedBy: userEmail,
425
+ }));
426
+ });
427
+ });
397
428
  });
398
429
  describe('Callbacks receive authenticated user via WebSocket (e2e)', () => {
399
- let UserEntity = class UserEntity extends src_1.BaseEntity {
400
- };
401
- __decorate([
402
- (0, mongoose_1.Prop)({ type: String, required: true }),
403
- __metadata("design:type", String)
404
- ], UserEntity.prototype, "email", void 0);
405
- __decorate([
406
- (0, mongoose_1.Prop)({ type: String, required: true }),
407
- __metadata("design:type", String)
408
- ], UserEntity.prototype, "password", void 0);
409
- UserEntity = __decorate([
410
- (0, mongoose_1.Schema)({ collection: 'users-cb-ws' })
411
- ], UserEntity);
412
- let ItemEntity = class ItemEntity extends src_1.BaseEntity {
413
- };
414
- __decorate([
415
- (0, mongoose_1.Prop)({ type: String, required: true }),
416
- __metadata("design:type", String)
417
- ], ItemEntity.prototype, "name", void 0);
418
- __decorate([
419
- (0, mongoose_1.Prop)({ type: String }),
420
- __metadata("design:type", String)
421
- ], ItemEntity.prototype, "createdBy", void 0);
422
- __decorate([
423
- (0, mongoose_1.Prop)({ type: String }),
424
- __metadata("design:type", String)
425
- ], ItemEntity.prototype, "updatedBy", void 0);
426
- ItemEntity = __decorate([
427
- (0, mongoose_1.Schema)({ collection: 'items-cb-ws' })
428
- ], ItemEntity);
429
- let AuditLogEntity = class AuditLogEntity extends src_1.BaseEntity {
430
- };
431
- __decorate([
432
- (0, mongoose_1.Prop)({ type: String, required: true }),
433
- __metadata("design:type", String)
434
- ], AuditLogEntity.prototype, "action", void 0);
435
- __decorate([
436
- (0, mongoose_1.Prop)({ type: String, required: true }),
437
- __metadata("design:type", String)
438
- ], AuditLogEntity.prototype, "entityId", void 0);
439
- __decorate([
440
- (0, mongoose_1.Prop)({ type: String }),
441
- __metadata("design:type", String)
442
- ], AuditLogEntity.prototype, "performedBy", void 0);
443
- AuditLogEntity = __decorate([
444
- (0, mongoose_1.Schema)({ collection: 'audit-logs-cb-ws' })
445
- ], AuditLogEntity);
446
- const createOneBeforeSave = async (_entity, context, _methods, user) => {
447
- const u = user;
448
- return { ...context.toCreate, createdBy: u?.email ?? 'anonymous' };
449
- };
450
- const createOneAfterSave = async (entity, methods, user) => {
451
- const u = user;
452
- await methods.createOneDocument(AuditLogEntity, {
453
- action: 'WS-CreateOne',
454
- entityId: entity.id,
455
- performedBy: u?.email ?? 'anonymous',
456
- });
457
- };
458
- const createManyBeforeSave = async (_entities, context, _methods, user) => {
459
- const u = user;
460
- return context.toCreate.map((item) => ({ ...item, createdBy: u?.email ?? 'anonymous' }));
461
- };
462
- const createManyAfterSave = async (entity, methods, user) => {
463
- const u = user;
464
- await methods.createOneDocument(AuditLogEntity, {
465
- action: 'WS-CreateMany',
466
- entityId: entity.id,
467
- performedBy: u?.email ?? 'anonymous',
468
- });
469
- };
470
- const updateOneBeforeSave = async (_entity, context, _methods, user) => {
471
- const u = user;
472
- return { ...context.update, updatedBy: u?.email ?? 'anonymous' };
473
- };
474
- const updateOneAfterSave = async (entity, methods, user) => {
475
- const u = user;
476
- await methods.createOneDocument(AuditLogEntity, {
477
- action: 'WS-UpdateOne',
478
- entityId: entity.id,
479
- performedBy: u?.email ?? 'anonymous',
480
- });
481
- };
482
- const updateManyBeforeSave = async (entities, context, _methods, user) => {
483
- const u = user;
484
- return entities.map(() => ({ ...context.update, updatedBy: u?.email ?? 'anonymous' }));
485
- };
486
- const updateManyAfterSave = async (entity, methods, user) => {
487
- const u = user;
488
- await methods.createOneDocument(AuditLogEntity, {
489
- action: 'WS-UpdateMany',
490
- entityId: entity.id,
491
- performedBy: u?.email ?? 'anonymous',
492
- });
493
- };
494
- const replaceOneBeforeSave = async (_entity, context, _methods, user) => {
495
- const u = user;
496
- return { ...context.replacement, updatedBy: u?.email ?? 'anonymous' };
497
- };
498
- const replaceOneAfterSave = async (entity, methods, user) => {
499
- const u = user;
500
- await methods.createOneDocument(AuditLogEntity, {
501
- action: 'WS-ReplaceOne',
502
- entityId: entity.id,
503
- performedBy: u?.email ?? 'anonymous',
504
- });
505
- };
506
- const duplicateOneBeforeSave = async (_entity, context, _methods, user) => {
507
- const u = user;
508
- return { ...(context.override ?? {}), createdBy: u?.email ?? 'anonymous' };
509
- };
510
- const duplicateOneAfterSave = async (entity, methods, user) => {
511
- const u = user;
512
- await methods.createOneDocument(AuditLogEntity, {
513
- action: 'WS-DuplicateOne',
514
- entityId: entity.id,
515
- performedBy: u?.email ?? 'anonymous',
516
- });
517
- };
518
- const duplicateManyBeforeSave = async (entities, context, _methods, user) => {
519
- const u = user;
520
- return entities.map((e) => ({
521
- name: e.name,
522
- ...(context.override ?? {}),
523
- createdBy: u?.email ?? 'anonymous',
524
- }));
525
- };
526
- const duplicateManyAfterSave = async (entity, methods, user) => {
527
- const u = user;
528
- await methods.createOneDocument(AuditLogEntity, {
529
- action: 'WS-DuplicateMany',
530
- entityId: entity.id,
531
- performedBy: u?.email ?? 'anonymous',
532
- });
533
- };
534
- const deleteOneBeforeSave = async (entity, _context, methods, user) => {
535
- const u = user;
536
- if (entity) {
537
- await methods.createOneDocument(AuditLogEntity, {
538
- action: 'WS-DeleteOne-before',
539
- entityId: entity.id,
540
- performedBy: u?.email ?? 'anonymous',
541
- });
542
- }
543
- };
544
- const deleteOneAfterSave = async (entity, methods, user) => {
545
- const u = user;
546
- await methods.createOneDocument(AuditLogEntity, {
547
- action: 'WS-DeleteOne',
548
- entityId: entity.id,
549
- performedBy: u?.email ?? 'anonymous',
550
- });
551
- };
552
- const deleteManyBeforeSave = async (entities, _context, methods, user) => {
553
- const u = user;
554
- for (const entity of entities) {
555
- await methods.createOneDocument(AuditLogEntity, {
556
- action: 'WS-DeleteMany-before',
557
- entityId: entity._id?.toString() ?? entity.id,
558
- performedBy: u?.email ?? 'anonymous',
559
- });
560
- }
561
- };
562
- const deleteManyAfterSave = async (entity, methods, user) => {
563
- const u = user;
564
- await methods.createOneDocument(AuditLogEntity, {
565
- action: 'WS-DeleteMany',
566
- entityId: entity.id,
567
- performedBy: u?.email ?? 'anonymous',
568
- });
569
- };
570
- const getOneAfterSave = async (entity, methods, user) => {
571
- const u = user;
572
- await methods.createOneDocument(AuditLogEntity, {
573
- action: 'WS-GetOne',
574
- entityId: entity.id,
575
- performedBy: u?.email ?? 'anonymous',
576
- });
577
- };
578
- const getManyAfterSave = async (entity, methods, user) => {
579
- const u = user;
580
- await methods.createOneDocument(AuditLogEntity, {
581
- action: 'WS-GetMany',
582
- entityId: entity.id,
583
- performedBy: u?.email ?? 'anonymous',
584
- });
585
- };
586
- const wsRoutes = [
587
- { type: 'CreateOne', webSocket: true, callback: createOneAfterSave, beforeSaveCallback: createOneBeforeSave },
588
- { type: 'CreateMany', webSocket: true, callback: createManyAfterSave, beforeSaveCallback: createManyBeforeSave },
589
- { type: 'UpdateOne', webSocket: true, callback: updateOneAfterSave, beforeSaveCallback: updateOneBeforeSave },
590
- { type: 'UpdateMany', webSocket: true, callback: updateManyAfterSave, beforeSaveCallback: updateManyBeforeSave },
591
- { type: 'ReplaceOne', webSocket: true, callback: replaceOneAfterSave, beforeSaveCallback: replaceOneBeforeSave },
592
- { type: 'DuplicateOne', webSocket: true, callback: duplicateOneAfterSave, beforeSaveCallback: duplicateOneBeforeSave },
593
- { type: 'DuplicateMany', webSocket: true, callback: duplicateManyAfterSave, beforeSaveCallback: duplicateManyBeforeSave },
594
- { type: 'DeleteOne', webSocket: true, callback: deleteOneAfterSave, beforeSaveCallback: deleteOneBeforeSave },
595
- { type: 'DeleteMany', webSocket: true, callback: deleteManyAfterSave, beforeSaveCallback: deleteManyBeforeSave },
596
- { type: 'GetOne', webSocket: true, callback: getOneAfterSave },
597
- { type: 'GetMany', webSocket: true, callback: getManyAfterSave },
598
- ];
430
+ const { UserEntity, ItemEntity, AuditLogEntity } = buildEntities('cb-ws');
431
+ const callbacks = buildCallbacks(AuditLogEntity, 'WS-');
432
+ const wsRoutes = buildRoutes(callbacks, { webSocket: true });
599
433
  let accessToken;
600
434
  const userEmail = 'ws-cb-test@test.co';
601
435
  const userPassword = 'test';
@@ -768,5 +602,19 @@ describe('Callbacks receive authenticated user via WebSocket (e2e)', () => {
768
602
  expect(logs.every((l) => l.performedBy === userEmail)).toBe(true);
769
603
  });
770
604
  });
605
+ describe('Aggregate', () => {
606
+ it('afterSave callback should create audit logs with socket user for each aggregated entity', async () => {
607
+ await e2e_setup_1.server.emit('create-many-item-entity', { list: [{ name: 'ws-agg-1' }, { name: 'ws-agg-2' }] }, wsAuth());
608
+ const result = await e2e_setup_1.server.emit('aggregate-aggregate-item-entity', { name: 'ws-agg-1' }, wsAuth());
609
+ expect(result).toHaveLength(1);
610
+ expect(result[0].name).toBe('ws-agg-1');
611
+ const logs = await getAuditLogs('WS-Aggregate');
612
+ expect(logs).toHaveLength(1);
613
+ expect(logs[0]).toEqual(expect.objectContaining({
614
+ entityId: result[0].id,
615
+ performedBy: userEmail,
616
+ }));
617
+ });
618
+ });
771
619
  });
772
620
  //# sourceMappingURL=callbacks-user.e2e-spec.js.map