@nest-util/nest-crud 1.0.6 → 1.0.8

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/README.md CHANGED
@@ -7,7 +7,7 @@ This library was generated with [Nx](https://nx.dev).
7
7
  We recommend using **pnpm** as your package manager.
8
8
 
9
9
  ```bash
10
- pnpm add @nest-util/nest-crud@^1.0.2 @nest-util/nest-auth@^1.0.2 typeorm@^1.1.0 @nestjs/typeorm @nestjs/swagger @nestjs/jwt @nestjs/passport class-validator class-transformer bcrypt
10
+ pnpm add @nest-util/nest-crud@^1.0.7 @nest-util/nest-auth@^1.1.0 typeorm@^1.1.0 @nestjs/typeorm @nestjs/swagger @nestjs/jwt @nestjs/passport class-validator class-transformer bcrypt
11
11
  ```
12
12
 
13
13
  ## Features
package/dist/index.d.ts CHANGED
@@ -18,4 +18,5 @@ export * from './lib/helpers/exception-filter.helper';
18
18
  export * from './lib/helpers/cursor-pagination.helper';
19
19
  export * from './lib/entities/audit-log.entity';
20
20
  export * from './lib/services/audit-log.service';
21
+ export * from './lib/events';
21
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AACzD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wCAAwC,CAAC;AACvD,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,sCAAsC,CAAC;AACrD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AACzD,cAAc,iCAAiC,CAAC;AAChD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,kCAAkC,CAAC;AACjD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -21,3 +21,4 @@ tslib_1.__exportStar(require("./lib/helpers/exception-filter.helper"), exports);
21
21
  tslib_1.__exportStar(require("./lib/helpers/cursor-pagination.helper"), exports);
22
22
  tslib_1.__exportStar(require("./lib/entities/audit-log.entity"), exports);
23
23
  tslib_1.__exportStar(require("./lib/services/audit-log.service"), exports);
24
+ tslib_1.__exportStar(require("./lib/events"), exports);
@@ -0,0 +1,32 @@
1
+ export interface AuditEvent {
2
+ /** Dot-separated event name, e.g. 'auth.user.login.success' */
3
+ action: string;
4
+ /** Entity type: 'user', 'role', 'post', etc. */
5
+ entity: string;
6
+ /** ID of the affected entity (optional for list/search events) */
7
+ entityId?: string | number;
8
+ /** ID of the user performing the action */
9
+ userId?: string | number;
10
+ /** Client IP address */
11
+ ip?: string;
12
+ /** User-Agent header */
13
+ userAgent?: string;
14
+ /** Multi-tenant ID */
15
+ tenantId?: string;
16
+ /** Event timestamp */
17
+ timestamp: Date;
18
+ /** Arbitrary event-specific data */
19
+ metadata?: Record<string, unknown>;
20
+ }
21
+ export interface AuditEventHandler {
22
+ handle(event: AuditEvent): void | Promise<void>;
23
+ }
24
+ export interface AuditEventModuleOptions {
25
+ /** Handlers to dispatch events to */
26
+ handlers: AuditEventHandler[];
27
+ /** Glob patterns to include (default: ['*']) */
28
+ include?: string[];
29
+ /** Glob patterns to exclude (default: []) */
30
+ exclude?: string[];
31
+ }
32
+ //# sourceMappingURL=audit-event.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-event.interface.d.ts","sourceRoot":"","sources":["../../../src/lib/events/audit-event.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,wBAAwB;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sBAAsB;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,uBAAuB;IACtC,qCAAqC;IACrC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import type { AuditEvent, AuditEventHandler, AuditEventModuleOptions } from './audit-event.interface';
2
+ export declare class AuditEventListener {
3
+ private handlers;
4
+ private options;
5
+ configure(handlers: AuditEventHandler[], options: AuditEventModuleOptions): void;
6
+ handleEvent(event: AuditEvent): Promise<void>;
7
+ }
8
+ //# sourceMappingURL=audit-event.listener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-event.listener.d.ts","sourceRoot":"","sources":["../../../src/lib/events/audit-event.listener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAgCtG,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,OAAO,CAA6C;IAE5D,SAAS,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,OAAO,EAAE,uBAAuB,GAAG,IAAI;IAK1E,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAiBpD"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuditEventListener = void 0;
4
+ const RE_SPECIAL = /[.+?^${}()|[\]\\]/g;
5
+ function matchesGlob(pattern, value) {
6
+ let regexStr = '^';
7
+ for (let i = 0; i < pattern.length; i++) {
8
+ const ch = pattern[i];
9
+ if (ch === '*') {
10
+ if (i + 1 < pattern.length && pattern[i + 1] === '*') {
11
+ regexStr += '.*';
12
+ i++;
13
+ }
14
+ else {
15
+ regexStr += '[^.]*';
16
+ }
17
+ }
18
+ else {
19
+ regexStr += ch.replace(RE_SPECIAL, '\\$&');
20
+ }
21
+ }
22
+ regexStr += '$';
23
+ return new RegExp(regexStr).test(value);
24
+ }
25
+ function shouldDispatch(event, options) {
26
+ const { include = ['*'], exclude = [] } = options;
27
+ const action = event.action;
28
+ const included = include.some((pattern) => matchesGlob(pattern, action));
29
+ if (!included)
30
+ return false;
31
+ const excluded = exclude.some((pattern) => matchesGlob(pattern, action));
32
+ return !excluded;
33
+ }
34
+ class AuditEventListener {
35
+ constructor() {
36
+ this.handlers = [];
37
+ this.options = { handlers: [] };
38
+ }
39
+ configure(handlers, options) {
40
+ this.handlers = handlers;
41
+ this.options = options;
42
+ }
43
+ async handleEvent(event) {
44
+ const auditEvent = event;
45
+ if (!shouldDispatch(auditEvent, this.options))
46
+ return;
47
+ const results = this.handlers.map(async (handler) => {
48
+ try {
49
+ await handler.handle(auditEvent);
50
+ }
51
+ catch (err) {
52
+ console.error(`[AuditEvent] Handler ${handler.constructor.name} failed for "${auditEvent.action}":`, err);
53
+ }
54
+ });
55
+ await Promise.allSettled(results);
56
+ }
57
+ }
58
+ exports.AuditEventListener = AuditEventListener;
@@ -0,0 +1,6 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import type { AuditEventModuleOptions } from './audit-event.interface';
3
+ export declare class AuditEventModule {
4
+ static forRoot(options: AuditEventModuleOptions): DynamicModule;
5
+ }
6
+ //# sourceMappingURL=audit-event.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-event.module.d.ts","sourceRoot":"","sources":["../../../src/lib/events/audit-event.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,gBAAgB,CAAC;AAE/D,OAAO,KAAK,EAAc,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAMnF,qBAEa,gBAAgB;IAC3B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,uBAAuB,GAAG,aAAa;CA8BhE"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var AuditEventModule_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AuditEventModule = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const event_emitter_1 = require("@nestjs/event-emitter");
8
+ const audit_event_listener_1 = require("./audit-event.listener");
9
+ const AUDIT_EVENT_OPTIONS = 'AUDIT_EVENT_OPTIONS';
10
+ const AUDIT_EVENT_HANDLERS = 'AUDIT_EVENT_HANDLERS';
11
+ let AuditEventModule = AuditEventModule_1 = class AuditEventModule {
12
+ static forRoot(options) {
13
+ const listenerProvider = {
14
+ provide: audit_event_listener_1.AuditEventListener,
15
+ useFactory: (eventEmitter) => {
16
+ const listener = new audit_event_listener_1.AuditEventListener();
17
+ listener.configure(options.handlers, options);
18
+ eventEmitter.onAny(async (...args) => {
19
+ const event = args[1];
20
+ if (event?.action) {
21
+ await listener.handleEvent(event);
22
+ }
23
+ });
24
+ return listener;
25
+ },
26
+ inject: [event_emitter_1.EventEmitter2],
27
+ };
28
+ return {
29
+ module: AuditEventModule_1,
30
+ imports: [event_emitter_1.EventEmitterModule.forRoot()],
31
+ providers: [
32
+ listenerProvider,
33
+ { provide: AUDIT_EVENT_OPTIONS, useValue: options },
34
+ { provide: AUDIT_EVENT_HANDLERS, useValue: options.handlers },
35
+ ],
36
+ exports: [event_emitter_1.EventEmitterModule],
37
+ };
38
+ }
39
+ };
40
+ exports.AuditEventModule = AuditEventModule;
41
+ exports.AuditEventModule = AuditEventModule = AuditEventModule_1 = tslib_1.__decorate([
42
+ (0, common_1.Global)(),
43
+ (0, common_1.Module)({})
44
+ ], AuditEventModule);
@@ -0,0 +1,5 @@
1
+ import { AuditEvent, AuditEventHandler } from '../audit-event.interface';
2
+ export declare class ConsoleHandler implements AuditEventHandler {
3
+ handle(event: AuditEvent): void;
4
+ }
5
+ //# sourceMappingURL=console.handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/events/handlers/console.handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAwCzE,qBAAa,cAAe,YAAW,iBAAiB;IACtD,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;CAGhC"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConsoleHandler = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const COLORS = {
6
+ reset: '\x1b[0m',
7
+ dim: '\x1b[2m',
8
+ red: '\x1b[31m',
9
+ green: '\x1b[32m',
10
+ yellow: '\x1b[33m',
11
+ blue: '\x1b[34m',
12
+ cyan: '\x1b[36m',
13
+ gray: '\x1b[90m',
14
+ };
15
+ function colorize(text, color) {
16
+ return `${color}${text}${COLORS.reset}`;
17
+ }
18
+ function formatEvent(event) {
19
+ const ts = event.timestamp.toISOString();
20
+ const isSuccess = event.action.endsWith('.success') || (!event.action.includes('.failed') && !event.action.includes('.error') && !event.action.includes('.denied') && !event.action.includes('.conflict') && !event.action.includes('.locked') && !event.action.includes('.disabled'));
21
+ const statusColor = isSuccess ? COLORS.green : COLORS.red;
22
+ const parts = [
23
+ colorize(ts, COLORS.dim),
24
+ colorize(event.action, statusColor),
25
+ colorize(`entity=${event.entity}`, COLORS.cyan),
26
+ ];
27
+ if (event.entityId != null) {
28
+ parts.push(colorize(`id=${event.entityId}`, COLORS.blue));
29
+ }
30
+ if (event.userId != null) {
31
+ parts.push(colorize(`userId=${event.userId}`, COLORS.yellow));
32
+ }
33
+ if (event.ip) {
34
+ parts.push(colorize(`ip=${event.ip}`, COLORS.gray));
35
+ }
36
+ return parts.join(' ');
37
+ }
38
+ class ConsoleHandler {
39
+ handle(event) {
40
+ common_1.Logger.log(formatEvent(event));
41
+ }
42
+ }
43
+ exports.ConsoleHandler = ConsoleHandler;
@@ -0,0 +1,5 @@
1
+ export * from './audit-event.interface';
2
+ export * from './audit-event.module';
3
+ export * from './audit-event.listener';
4
+ export * from './handlers/console.handler';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/events/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./audit-event.interface"), exports);
5
+ tslib_1.__exportStar(require("./audit-event.module"), exports);
6
+ tslib_1.__exportStar(require("./audit-event.listener"), exports);
7
+ tslib_1.__exportStar(require("./handlers/console.handler"), exports);
@@ -1,12 +1,15 @@
1
1
  import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
2
2
  import { Reflector } from '@nestjs/core';
3
3
  import { Observable } from 'rxjs';
4
+ import { EventEmitter2 } from '@nestjs/event-emitter';
4
5
  import { AuditService } from '../services/audit-log.service';
5
6
  export declare class AuditInterceptor implements NestInterceptor {
6
7
  private readonly auditService;
7
8
  private readonly reflector;
8
- constructor(auditService: AuditService, reflector: Reflector);
9
+ private readonly eventEmitter?;
10
+ constructor(auditService: AuditService, reflector: Reflector, eventEmitter?: EventEmitter2 | undefined);
9
11
  intercept(context: ExecutionContext, next: CallHandler<unknown>): Observable<unknown>;
12
+ private emitEvent;
10
13
  private resolveEntityName;
11
14
  }
12
15
  //# sourceMappingURL=audit-log.interceptor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit-log.interceptor.d.ts","sourceRoot":"","sources":["../../../src/lib/interceptors/audit-log.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAO,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAS7D,qBACa,gBAAiB,YAAW,eAAe;IAEpD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,SAAS;IAGvC,SAAS,CACP,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,GACzB,UAAU,CAAC,OAAO,CAAC;IAyCtB,OAAO,CAAC,iBAAiB;CAwB1B"}
1
+ {"version":3,"file":"audit-log.interceptor.d.ts","sourceRoot":"","sources":["../../../src/lib/interceptors/audit-log.interceptor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,gBAAgB,EAChB,WAAW,EAEZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAA+B,MAAM,MAAM,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAU7D,qBACa,gBAAiB,YAAW,eAAe;IAEpD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS;IACd,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAFzB,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,SAAS,EACR,YAAY,CAAC,EAAE,aAAa,YAAA;IAG3D,SAAS,CACP,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,GACzB,UAAU,CAAC,OAAO,CAAC;IAkFtB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,iBAAiB;CAwB1B"}
@@ -5,14 +5,16 @@ const tslib_1 = require("tslib");
5
5
  const common_1 = require("@nestjs/common");
6
6
  const core_1 = require("@nestjs/core");
7
7
  const rxjs_1 = require("rxjs");
8
+ const event_emitter_1 = require("@nestjs/event-emitter");
8
9
  const audit_log_service_1 = require("../services/audit-log.service");
9
10
  const audit_log_decorator_1 = require("../decorators/audit-log.decorator");
10
11
  const CONTROLLER_ENTITY_NAME_KEY = 'entityName';
11
12
  const ENTITY_ENTITY_NAME_KEY = 'custom:entityName';
12
13
  let AuditInterceptor = class AuditInterceptor {
13
- constructor(auditService, reflector) {
14
+ constructor(auditService, reflector, eventEmitter) {
14
15
  this.auditService = auditService;
15
16
  this.reflector = reflector;
17
+ this.eventEmitter = eventEmitter;
16
18
  }
17
19
  intercept(context, next) {
18
20
  const handler = context.getHandler();
@@ -24,14 +26,23 @@ let AuditInterceptor = class AuditInterceptor {
24
26
  const userId = request.user?.id;
25
27
  const ip = request.ip;
26
28
  const userAgent = request.headers?.['user-agent'];
29
+ const entityIdFromParams = request.params?.id;
27
30
  let entityName = auditOptions.entity;
28
31
  if (!entityName) {
29
32
  entityName = this.resolveEntityName(context);
30
33
  }
34
+ const basePayload = {
35
+ entity: entityName,
36
+ userId,
37
+ ip,
38
+ userAgent,
39
+ };
31
40
  return next.handle().pipe((0, rxjs_1.tap)(async (result) => {
41
+ const entityId = result?.id ?? entityIdFromParams;
32
42
  await this.auditService.log({
33
43
  action: auditOptions.action,
34
44
  entity: entityName,
45
+ entityId,
35
46
  userId,
36
47
  ip,
37
48
  userAgent,
@@ -42,8 +53,39 @@ let AuditInterceptor = class AuditInterceptor {
42
53
  response: result,
43
54
  },
44
55
  });
56
+ this.emitEvent({
57
+ ...basePayload,
58
+ action: `crud.${entityName.toLowerCase()}.${auditOptions.action.toLowerCase()}.success`,
59
+ entityId,
60
+ timestamp: new Date(),
61
+ metadata: {
62
+ body: request.body,
63
+ params: request.params,
64
+ query: request.query,
65
+ },
66
+ });
67
+ }), (0, rxjs_1.catchError)((error) => {
68
+ const entityId = entityIdFromParams;
69
+ this.emitEvent({
70
+ ...basePayload,
71
+ action: `crud.${entityName.toLowerCase()}.${auditOptions.action.toLowerCase()}.error`,
72
+ entityId,
73
+ timestamp: new Date(),
74
+ metadata: {
75
+ body: request.body,
76
+ params: request.params,
77
+ query: request.query,
78
+ error: { message: error.message, statusCode: error.status },
79
+ },
80
+ });
81
+ return (0, rxjs_1.throwError)(() => error);
45
82
  }));
46
83
  }
84
+ emitEvent(event) {
85
+ if (!this.eventEmitter)
86
+ return;
87
+ this.eventEmitter.emit(event.action, event);
88
+ }
47
89
  resolveEntityName(context) {
48
90
  const controllerClass = context.getClass();
49
91
  const controllerMeta = Reflect.getMetadata(CONTROLLER_ENTITY_NAME_KEY, controllerClass);
@@ -67,6 +109,8 @@ let AuditInterceptor = class AuditInterceptor {
67
109
  exports.AuditInterceptor = AuditInterceptor;
68
110
  exports.AuditInterceptor = AuditInterceptor = tslib_1.__decorate([
69
111
  (0, common_1.Injectable)(),
112
+ tslib_1.__param(2, (0, common_1.Optional)()),
70
113
  tslib_1.__metadata("design:paramtypes", [audit_log_service_1.AuditService,
71
- core_1.Reflector])
114
+ core_1.Reflector,
115
+ event_emitter_1.EventEmitter2])
72
116
  ], AuditInterceptor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nest-util/nest-crud",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -34,6 +34,7 @@
34
34
  "@nest-util/nest-auth": "workspace:*",
35
35
  "@nestjs/common": "^11.0.0",
36
36
  "@nestjs/core": "^11.0.0",
37
+ "@nestjs/event-emitter": "^3.0.0",
37
38
  "@nestjs/swagger": "^11.2.6",
38
39
  "@nestjs/typeorm": "^11.0.1",
39
40
  "class-transformer": "^0.5.1",
@@ -45,6 +46,9 @@
45
46
  "peerDependenciesMeta": {
46
47
  "@nest-util/nest-auth": {
47
48
  "optional": true
49
+ },
50
+ "@nestjs/event-emitter": {
51
+ "optional": true
48
52
  }
49
53
  }
50
54
  }