rl-core-api 0.16.0 → 0.16.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.
@@ -0,0 +1,6 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+ export declare class NotificationDismissal1789171200000 implements MigrationInterface {
3
+ name: string;
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationDismissal1789171200000 = void 0;
4
+ class NotificationDismissal1789171200000 {
5
+ constructor() {
6
+ this.name = "NotificationDismissal1789171200000";
7
+ }
8
+ async up(queryRunner) {
9
+ await queryRunner.query(`ALTER TABLE notification_reads
10
+ ADD COLUMN dismissed_at datetime NULL AFTER read_at`);
11
+ }
12
+ async down(queryRunner) {
13
+ await queryRunner.query(`ALTER TABLE notification_reads DROP COLUMN dismissed_at`);
14
+ }
15
+ }
16
+ exports.NotificationDismissal1789171200000 = NotificationDismissal1789171200000;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.coreMigrations = void 0;
4
+ const _1789171200000_NotificationDismissal_1 = require("./1789171200000-NotificationDismissal");
4
5
  const _1710000000000_InitialSchema_1 = require("./1710000000000-InitialSchema");
5
6
  exports.coreMigrations = [
6
7
  _1710000000000_InitialSchema_1.InitialSchema1710000000000,
8
+ _1789171200000_NotificationDismissal_1.NotificationDismissal1789171200000,
7
9
  ];
@@ -38,6 +38,8 @@ export declare class NotificationsService {
38
38
  findByUser(user: AuthenticatedUser, query: PaginationQuery): Promise<Paginated<UserNotification>>;
39
39
  countUnread(user: AuthenticatedUser): Promise<number>;
40
40
  markAsRead(id: string, user: AuthenticatedUser): Promise<void>;
41
+ dismiss(id: string, user: AuthenticatedUser): Promise<void>;
42
+ dismissRead(user: AuthenticatedUser): Promise<number>;
41
43
  markAllAsRead(user: AuthenticatedUser): Promise<void>;
42
44
  cleanupOldRead(retentionDays: number): Promise<number>;
43
45
  private visibilityOf;
@@ -60,6 +60,18 @@ let NotificationsService = class NotificationsService {
60
60
  }
61
61
  await this.reads.markAsRead([id], user.id);
62
62
  }
63
+ async dismiss(id, user) {
64
+ const visible = await this.notifications.isVisibleToUser(id, this.visibilityOf(user));
65
+ if (!visible) {
66
+ throw new common_1.NotFoundException("Notificação não encontrada");
67
+ }
68
+ await this.reads.dismiss([id], user.id);
69
+ }
70
+ async dismissRead(user) {
71
+ const ids = await this.notifications.findReadIds(this.visibilityOf(user));
72
+ await this.reads.dismiss(ids, user.id);
73
+ return ids.length;
74
+ }
63
75
  async markAllAsRead(user) {
64
76
  const ids = await this.notifications.findUnreadIds(this.visibilityOf(user));
65
77
  await this.reads.markAsRead(ids, user.id);
@@ -9,6 +9,7 @@ export declare class NotificationRepository extends Repository<Notification> {
9
9
  findVisibleToUser(params: VisibilityParams, page: number, limit: number): Promise<[Notification[], number]>;
10
10
  countUnread(params: VisibilityParams): Promise<number>;
11
11
  isVisibleToUser(notificationId: string, params: VisibilityParams): Promise<boolean>;
12
+ findReadIds(params: VisibilityParams): Promise<string[]>;
12
13
  findUnreadIds(params: VisibilityParams): Promise<string[]>;
13
14
  softDeleteReadByAllBefore(limit: Date): Promise<number>;
14
15
  private baseVisibleQuery;
@@ -69,6 +69,13 @@ let NotificationRepository = class NotificationRepository extends typeorm_1.Repo
69
69
  .getCount();
70
70
  return count > 0;
71
71
  }
72
+ async findReadIds(params) {
73
+ const rows = await this.baseVisibleQuery(params)
74
+ .andWhere("read.notification_id IS NOT NULL")
75
+ .select("notification.id", "id")
76
+ .getRawMany();
77
+ return rows.map((row) => row.id);
78
+ }
72
79
  async findUnreadIds(params) {
73
80
  const rows = await this.baseVisibleQuery(params)
74
81
  .andWhere("read.notification_id IS NULL")
@@ -92,6 +99,7 @@ let NotificationRepository = class NotificationRepository extends typeorm_1.Repo
92
99
  return this.createQueryBuilder("notification")
93
100
  .leftJoinAndSelect("notification.reads", "read", "read.user_id = :userId", { userId: params.userId })
94
101
  .where("notification.deletedAt IS NULL")
102
+ .andWhere("read.dismissed_at IS NULL")
95
103
  .andWhere(VISIBLE_TO_USER, {
96
104
  userScope: scopeType_enum_1.ScopeType.USER,
97
105
  roleScope: scopeType_enum_1.ScopeType.ROLE,
@@ -3,4 +3,5 @@ import { NotificationRead } from "../schema/notificationRead.schema";
3
3
  export declare class NotificationReadRepository extends Repository<NotificationRead> {
4
4
  constructor(dataSource: DataSource);
5
5
  markAsRead(notificationIds: string[], userId: string): Promise<void>;
6
+ dismiss(notificationIds: string[], userId: string): Promise<void>;
6
7
  }
@@ -32,6 +32,23 @@ let NotificationReadRepository = class NotificationReadRepository extends typeor
32
32
  .orIgnore()
33
33
  .execute();
34
34
  }
35
+ async dismiss(notificationIds, userId) {
36
+ if (notificationIds.length === 0) {
37
+ return;
38
+ }
39
+ const agora = new Date();
40
+ await this.createQueryBuilder()
41
+ .insert()
42
+ .into(notificationRead_schema_1.NotificationRead)
43
+ .values(notificationIds.map((notificationId) => ({
44
+ notificationId,
45
+ userId,
46
+ readAt: agora,
47
+ dismissedAt: agora,
48
+ })))
49
+ .orUpdate(["dismissed_at"], ["notification_id", "user_id"])
50
+ .execute();
51
+ }
35
52
  };
36
53
  exports.NotificationReadRepository = NotificationReadRepository;
37
54
  exports.NotificationReadRepository = NotificationReadRepository = __decorate([
@@ -3,5 +3,6 @@ export declare class NotificationRead {
3
3
  notificationId: string;
4
4
  userId: string;
5
5
  readAt: Date;
6
+ dismissedAt: Date | null;
6
7
  notification: Notification;
7
8
  }
@@ -27,6 +27,10 @@ __decorate([
27
27
  (0, typeorm_1.Column)({ name: "read_at", type: "datetime" }),
28
28
  __metadata("design:type", Date)
29
29
  ], NotificationRead.prototype, "readAt", void 0);
30
+ __decorate([
31
+ (0, typeorm_1.Column)({ name: "dismissed_at", type: "datetime", nullable: true }),
32
+ __metadata("design:type", Object)
33
+ ], NotificationRead.prototype, "dismissedAt", void 0);
30
34
  __decorate([
31
35
  (0, typeorm_1.ManyToOne)(() => notification_schema_1.Notification, { onDelete: "CASCADE" }),
32
36
  (0, typeorm_1.JoinColumn)({ name: "notification_id" }),
@@ -12,5 +12,7 @@ export declare class NotificationsController {
12
12
  unreadCount(user: AuthenticatedUser): Promise<UnreadCountResponse>;
13
13
  markAllAsRead(user: AuthenticatedUser): Promise<void>;
14
14
  markAsRead(id: string, user: AuthenticatedUser): Promise<void>;
15
+ dismissRead(user: AuthenticatedUser): Promise<void>;
16
+ dismiss(id: string, user: AuthenticatedUser): Promise<void>;
15
17
  create(command: CreateNotificationCommand, user: AuthenticatedUser): Promise<UserNotificationResponse>;
16
18
  }
@@ -40,6 +40,12 @@ let NotificationsController = class NotificationsController {
40
40
  async markAsRead(id, user) {
41
41
  await this.notifications.markAsRead(id, user);
42
42
  }
43
+ async dismissRead(user) {
44
+ await this.notifications.dismissRead(user);
45
+ }
46
+ async dismiss(id, user) {
47
+ await this.notifications.dismiss(id, user);
48
+ }
43
49
  create(command, user) {
44
50
  return this.publisher.publishAndPush({
45
51
  title: command.title,
@@ -88,6 +94,23 @@ __decorate([
88
94
  __metadata("design:paramtypes", [String, Object]),
89
95
  __metadata("design:returntype", Promise)
90
96
  ], NotificationsController.prototype, "markAsRead", null);
97
+ __decorate([
98
+ (0, common_1.Delete)("read"),
99
+ (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT),
100
+ __param(0, (0, currentUser_decorator_1.CurrentUser)()),
101
+ __metadata("design:type", Function),
102
+ __metadata("design:paramtypes", [Object]),
103
+ __metadata("design:returntype", Promise)
104
+ ], NotificationsController.prototype, "dismissRead", null);
105
+ __decorate([
106
+ (0, common_1.Delete)(":id"),
107
+ (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT),
108
+ __param(0, (0, common_1.Param)("id", common_1.ParseUUIDPipe)),
109
+ __param(1, (0, currentUser_decorator_1.CurrentUser)()),
110
+ __metadata("design:type", Function),
111
+ __metadata("design:paramtypes", [String, Object]),
112
+ __metadata("design:returntype", Promise)
113
+ ], NotificationsController.prototype, "dismiss", null);
91
114
  __decorate([
92
115
  (0, common_1.Post)(),
93
116
  (0, requirePermission_decorator_1.RequirePermission)("notifications:create:any"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rl-core-api",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "Core NestJS: autenticação com 2FA, RBAC, auditoria, notificações e listagens com filtro dinâmico",
5
5
  "author": "Rodrigo Liberti",
6
6
  "license": "MIT",