@rytass/bpm-core-nestjs-module 0.9.1 → 0.11.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +17 -5
  3. package/package.json +3 -3
  4. package/src/lib/attachment/attachment-options.js +7 -1
  5. package/src/lib/attachment/attachment-options.js.map +1 -1
  6. package/src/lib/attachment/attachment.service.js +7 -0
  7. package/src/lib/attachment/attachment.service.js.map +1 -1
  8. package/src/lib/bpm/bpm-root.module.d.ts +11 -0
  9. package/src/lib/bpm/bpm-root.module.js.map +1 -1
  10. package/src/lib/calendar/calendar.module.d.ts +12 -0
  11. package/src/lib/calendar/calendar.module.js.map +1 -1
  12. package/src/lib/common/filters/all-exceptions.filter.d.ts +11 -0
  13. package/src/lib/common/filters/all-exceptions.filter.js +35 -1
  14. package/src/lib/common/filters/all-exceptions.filter.js.map +1 -1
  15. package/src/lib/form-data-source/form-data-source-value-resolver.service.d.ts +6 -7
  16. package/src/lib/form-data-source/form-data-source-value-resolver.service.js +91 -291
  17. package/src/lib/form-data-source/form-data-source-value-resolver.service.js.map +1 -1
  18. package/src/lib/form-data-source/form-data-source.queries.d.ts +24 -0
  19. package/src/lib/form-data-source/form-data-source.queries.js +179 -7
  20. package/src/lib/form-data-source/form-data-source.queries.js.map +1 -1
  21. package/src/lib/form-data-source/form-data-source.service.d.ts +36 -21
  22. package/src/lib/form-data-source/form-data-source.service.js +143 -359
  23. package/src/lib/form-data-source/form-data-source.service.js.map +1 -1
  24. package/src/lib/form-data-source/form-data-source.types.d.ts +17 -0
  25. package/src/lib/form-data-source/form-data-source.types.js.map +1 -1
  26. package/src/lib/form-data-source/form-data-source.validation.d.ts +78 -0
  27. package/src/lib/form-data-source/form-data-source.validation.js +409 -0
  28. package/src/lib/form-data-source/form-data-source.validation.js.map +1 -0
  29. package/src/lib/migrations/0000000021000-notification-silenced.d.ts +15 -0
  30. package/src/lib/migrations/0000000021000-notification-silenced.js +31 -0
  31. package/src/lib/migrations/0000000021000-notification-silenced.js.map +1 -0
  32. package/src/lib/migrations/index.d.ts +1 -0
  33. package/src/lib/migrations/index.js +3 -0
  34. package/src/lib/migrations/index.js.map +1 -1
  35. package/src/lib/notification/index.d.ts +1 -0
  36. package/src/lib/notification/index.js +1 -0
  37. package/src/lib/notification/index.js.map +1 -1
  38. package/src/lib/notification/notification-delivery.service.d.ts +26 -1
  39. package/src/lib/notification/notification-delivery.service.js +205 -20
  40. package/src/lib/notification/notification-delivery.service.js.map +1 -1
  41. package/src/lib/notification/notification-dispatcher.token.d.ts +13 -0
  42. package/src/lib/notification/notification-dispatcher.token.js.map +1 -1
  43. package/src/lib/notification/notification-observer.token.d.ts +6 -0
  44. package/src/lib/notification/notification-observer.token.js.map +1 -1
  45. package/src/lib/notification/notification-options.d.ts +43 -0
  46. package/src/lib/notification/notification-options.js +45 -4
  47. package/src/lib/notification/notification-options.js.map +1 -1
  48. package/src/lib/notification/notification-schedule.d.ts +41 -0
  49. package/src/lib/notification/notification-schedule.js +158 -0
  50. package/src/lib/notification/notification-schedule.js.map +1 -0
  51. package/src/lib/notification/notification.entity.d.ts +12 -0
  52. package/src/lib/notification/notification.entity.js +5 -0
  53. package/src/lib/notification/notification.entity.js.map +1 -1
  54. package/src/lib/notification/notification.service.d.ts +10 -0
  55. package/src/lib/notification/notification.service.js +100 -21
  56. package/src/lib/notification/notification.service.js.map +1 -1
  57. package/src/lib/template/index.d.ts +1 -0
  58. package/src/lib/template/index.js +1 -0
  59. package/src/lib/template/index.js.map +1 -1
  60. package/src/lib/template/template-observer.token.d.ts +67 -0
  61. package/src/lib/template/template-observer.token.js +16 -0
  62. package/src/lib/template/template-observer.token.js.map +1 -0
  63. package/src/lib/template/template.mutations.d.ts +1 -1
  64. package/src/lib/template/template.mutations.js +4 -3
  65. package/src/lib/template/template.mutations.js.map +1 -1
  66. package/src/lib/template/template.service.d.ts +18 -2
  67. package/src/lib/template/template.service.js +117 -17
  68. package/src/lib/template/template.service.js.map +1 -1
@@ -0,0 +1,15 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ /**
3
+ * Records whether a notification was deliberately not announced.
4
+ *
5
+ * Before this, a member preference of `in_app_enabled = false` stopped the row
6
+ * being written at all, so silencing notifications for an afternoon destroyed
7
+ * every notification raised in it. In-app rows are now always recorded and
8
+ * this column carries the announce decision instead. Existing rows were, by
9
+ * definition, announced.
10
+ */
11
+ export declare class NotificationSilenced0000000021000 implements MigrationInterface {
12
+ name: string;
13
+ up(queryRunner: QueryRunner): Promise<void>;
14
+ down(queryRunner: QueryRunner): Promise<void>;
15
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationSilenced0000000021000 = void 0;
4
+ /**
5
+ * Records whether a notification was deliberately not announced.
6
+ *
7
+ * Before this, a member preference of `in_app_enabled = false` stopped the row
8
+ * being written at all, so silencing notifications for an afternoon destroyed
9
+ * every notification raised in it. In-app rows are now always recorded and
10
+ * this column carries the announce decision instead. Existing rows were, by
11
+ * definition, announced.
12
+ */
13
+ class NotificationSilenced0000000021000 {
14
+ constructor() {
15
+ this.name = 'NotificationSilenced0000000021000';
16
+ }
17
+ async up(queryRunner) {
18
+ await queryRunner.query(`
19
+ ALTER TABLE "notifications"
20
+ ADD COLUMN IF NOT EXISTS "silenced" boolean NOT NULL DEFAULT false
21
+ `);
22
+ }
23
+ async down(queryRunner) {
24
+ await queryRunner.query(`
25
+ ALTER TABLE "notifications"
26
+ DROP COLUMN IF EXISTS "silenced"
27
+ `);
28
+ }
29
+ }
30
+ exports.NotificationSilenced0000000021000 = NotificationSilenced0000000021000;
31
+ //# sourceMappingURL=0000000021000-notification-silenced.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"0000000021000-notification-silenced.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/migrations/0000000021000-notification-silenced.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;GAQG;AACH,MAAa,iCAAiC;IAA9C;QACE,SAAI,GAAG,mCAAmC,CAAC;IAe7C,CAAC;IAbC,KAAK,CAAC,EAAE,CAAC,WAAwB;QAC/B,MAAM,WAAW,CAAC,KAAK,CAAC;;;KAGvB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAwB;QACjC,MAAM,WAAW,CAAC,KAAK,CAAC;;;KAGvB,CAAC,CAAC;IACL,CAAC;CACF;AAhBD,8EAgBC"}
@@ -21,3 +21,4 @@ export * from './0000000017000-adhoc-directives';
21
21
  export * from './0000000018000-notification-archive';
22
22
  export * from './0000000019000-approval-template-activation';
23
23
  export * from './0000000020000-form-data-option-snapshots';
24
+ export * from './0000000021000-notification-silenced';
@@ -23,6 +23,7 @@ const _0000000017000_adhoc_directives_1 = require("./0000000017000-adhoc-directi
23
23
  const _0000000018000_notification_archive_1 = require("./0000000018000-notification-archive");
24
24
  const _0000000019000_approval_template_activation_1 = require("./0000000019000-approval-template-activation");
25
25
  const _0000000020000_form_data_option_snapshots_1 = require("./0000000020000-form-data-option-snapshots");
26
+ const _0000000021000_notification_silenced_1 = require("./0000000021000-notification-silenced");
26
27
  exports.BPM_CORE_MIGRATIONS = [
27
28
  _0000000000001_enable_postgres_extensions_1.EnablePostgresExtensions0000000000001,
28
29
  _0000000001000_identity_organization_foundation_1.IdentityOrganizationFoundation0000000001000,
@@ -45,6 +46,7 @@ exports.BPM_CORE_MIGRATIONS = [
45
46
  _0000000018000_notification_archive_1.NotificationArchive0000000018000,
46
47
  _0000000019000_approval_template_activation_1.ApprovalTemplateActivation0000000019000,
47
48
  _0000000020000_form_data_option_snapshots_1.FormDataOptionSnapshots0000000020000,
49
+ _0000000021000_notification_silenced_1.NotificationSilenced0000000021000,
48
50
  ];
49
51
  tslib_1.__exportStar(require("./0000000000001-enable-postgres-extensions"), exports);
50
52
  tslib_1.__exportStar(require("./0000000001000-identity-organization-foundation"), exports);
@@ -67,4 +69,5 @@ tslib_1.__exportStar(require("./0000000017000-adhoc-directives"), exports);
67
69
  tslib_1.__exportStar(require("./0000000018000-notification-archive"), exports);
68
70
  tslib_1.__exportStar(require("./0000000019000-approval-template-activation"), exports);
69
71
  tslib_1.__exportStar(require("./0000000020000-form-data-option-snapshots"), exports);
72
+ tslib_1.__exportStar(require("./0000000021000-notification-silenced"), exports);
70
73
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/migrations/index.ts"],"names":[],"mappings":";;;;AACA,0GAAmG;AACnG,sHAA+G;AAC/G,oGAA6F;AAC7F,8GAAuG;AACvG,0GAAmG;AACnG,sFAAgF;AAChF,wFAAkF;AAClF,kGAA4F;AAC5F,8GAAuG;AACvG,oFAA8E;AAC9E,4GAAqG;AACrG,sHAA8G;AAC9G,8GAAuG;AACvG,kGAA2F;AAC3F,oGAA8F;AAC9F,kIAA0H;AAC1H,8GAAsG;AACtG,sFAAgF;AAChF,8FAAwF;AACxF,8GAAuG;AACvG,0GAAkG;AAErF,QAAA,mBAAmB,GAA8C;IAC5E,iFAAqC;IACrC,6FAA2C;IAC3C,2EAAkC;IAClC,qFAAuC;IACvC,iFAAqC;IACrC,8DAA4B;IAC5B,gEAA6B;IAC7B,0EAAkC;IAClC,qFAAuC;IACvC,4DAA2B;IAC3B,mFAAsC;IACtC,4FAA0C;IAC1C,qFAAuC;IACvC,yEAAiC;IACjC,4EAAmC;IACnC,wGAAgD;IAChD,oFAAsC;IACtC,8DAA4B;IAC5B,sEAAgC;IAChC,qFAAuC;IACvC,gFAAoC;CACrC,CAAC;AAEF,qFAA2D;AAC3D,2FAAiE;AACjE,kFAAwD;AACxD,uFAA6D;AAC7D,qFAA2D;AAC3D,2EAAiD;AACjD,4EAAkD;AAClD,iFAAuD;AACvD,uFAA6D;AAC7D,0EAAgD;AAChD,sFAA4D;AAC5D,2FAAiE;AACjE,uFAA6D;AAC7D,iFAAuD;AACvD,kFAAwD;AACxD,iGAAuE;AACvE,uFAA6D;AAC7D,2EAAiD;AACjD,+EAAqD;AACrD,uFAA6D;AAC7D,qFAA2D"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/migrations/index.ts"],"names":[],"mappings":";;;;AACA,0GAAmG;AACnG,sHAA+G;AAC/G,oGAA6F;AAC7F,8GAAuG;AACvG,0GAAmG;AACnG,sFAAgF;AAChF,wFAAkF;AAClF,kGAA4F;AAC5F,8GAAuG;AACvG,oFAA8E;AAC9E,4GAAqG;AACrG,sHAA8G;AAC9G,8GAAuG;AACvG,kGAA2F;AAC3F,oGAA8F;AAC9F,kIAA0H;AAC1H,8GAAsG;AACtG,sFAAgF;AAChF,8FAAwF;AACxF,8GAAuG;AACvG,0GAAkG;AAClG,gGAA0F;AAE7E,QAAA,mBAAmB,GAA8C;IAC5E,iFAAqC;IACrC,6FAA2C;IAC3C,2EAAkC;IAClC,qFAAuC;IACvC,iFAAqC;IACrC,8DAA4B;IAC5B,gEAA6B;IAC7B,0EAAkC;IAClC,qFAAuC;IACvC,4DAA2B;IAC3B,mFAAsC;IACtC,4FAA0C;IAC1C,qFAAuC;IACvC,yEAAiC;IACjC,4EAAmC;IACnC,wGAAgD;IAChD,oFAAsC;IACtC,8DAA4B;IAC5B,sEAAgC;IAChC,qFAAuC;IACvC,gFAAoC;IACpC,wEAAiC;CAClC,CAAC;AAEF,qFAA2D;AAC3D,2FAAiE;AACjE,kFAAwD;AACxD,uFAA6D;AAC7D,qFAA2D;AAC3D,2EAAiD;AACjD,4EAAkD;AAClD,iFAAuD;AACvD,uFAA6D;AAC7D,0EAAgD;AAChD,sFAA4D;AAC5D,2FAAiE;AACjE,uFAA6D;AAC7D,iFAAuD;AACvD,kFAAwD;AACxD,iGAAuE;AACvE,uFAA6D;AAC7D,2EAAiD;AACjD,+EAAqD;AACrD,uFAA6D;AAC7D,qFAA2D;AAC3D,gFAAsD"}
@@ -2,6 +2,7 @@ export * from './notification-delivery.service';
2
2
  export * from './notification-dispatcher.token';
3
3
  export * from './notification-observer.token';
4
4
  export * from './notification-preference.entity';
5
+ export * from './notification-schedule';
5
6
  export * from './notification.entity';
6
7
  export * from './notification.enums';
7
8
  export * from './notification-options';
@@ -5,6 +5,7 @@ tslib_1.__exportStar(require("./notification-delivery.service"), exports);
5
5
  tslib_1.__exportStar(require("./notification-dispatcher.token"), exports);
6
6
  tslib_1.__exportStar(require("./notification-observer.token"), exports);
7
7
  tslib_1.__exportStar(require("./notification-preference.entity"), exports);
8
+ tslib_1.__exportStar(require("./notification-schedule"), exports);
8
9
  tslib_1.__exportStar(require("./notification.entity"), exports);
9
10
  tslib_1.__exportStar(require("./notification.enums"), exports);
10
11
  tslib_1.__exportStar(require("./notification-options"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/index.ts"],"names":[],"mappings":";;;AAAA,0EAAgD;AAChD,0EAAgD;AAChD,wEAA8C;AAC9C,2EAAiD;AACjD,gEAAsC;AACtC,+DAAqC;AACrC,iEAAuC;AACvC,wEAA8C;AAC9C,gEAAsC;AACtC,iEAAuC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/index.ts"],"names":[],"mappings":";;;AAAA,0EAAgD;AAChD,0EAAgD;AAChD,wEAA8C;AAC9C,2EAAiD;AACjD,kEAAwC;AACxC,gEAAsC;AACtC,+DAAqC;AACrC,iEAAuC;AACvC,wEAA8C;AAC9C,gEAAsC;AACtC,iEAAuC"}
@@ -1,23 +1,48 @@
1
1
  import { ModuleRef } from '@nestjs/core';
2
2
  import { Repository } from 'typeorm';
3
+ import { NotificationPreferenceEntity } from './notification-preference.entity';
3
4
  import { NotificationEntity } from './notification.entity';
4
5
  import { BPMResolvedNotificationOptions } from './notification-options';
5
6
  export declare class NotificationDeliveryService {
6
7
  private readonly notificationRepository;
8
+ private readonly notificationPreferenceRepository;
7
9
  private readonly moduleRef;
8
10
  private readonly logger;
9
- constructor(notificationRepository: Repository<NotificationEntity>, moduleRef: ModuleRef);
11
+ constructor(notificationRepository: Repository<NotificationEntity>, notificationPreferenceRepository: Repository<NotificationPreferenceEntity>, moduleRef: ModuleRef);
10
12
  deliverPendingNotifications({ limit, now, options, }: {
11
13
  readonly limit?: number;
12
14
  readonly now?: Date;
13
15
  readonly options: BPMResolvedNotificationOptions;
14
16
  }): Promise<number>;
17
+ /**
18
+ * Splits a claimed batch into recipients who asked for a daily digest and
19
+ * everyone else.
20
+ *
21
+ * Only email digests, and only when a recipient has more than one row
22
+ * waiting — a "digest" of a single notification is just that notification
23
+ * with a worse subject line.
24
+ */
25
+ private groupDigestBatches;
26
+ private readDailyDigestMemberIds;
27
+ /**
28
+ * Sends one message covering a recipient's held notifications and marks all
29
+ * of them delivered, so a member on `DAILY` gets one email rather than one
30
+ * per approval that happened overnight.
31
+ *
32
+ * Returns how many rows were delivered, so the scan's count still reflects
33
+ * notifications rather than messages.
34
+ */
35
+ private deliverDigest;
36
+ private dispatchDigest;
37
+ private dispatchDigestEmail;
15
38
  deliverNotification(notification: NotificationEntity, options: BPMResolvedNotificationOptions): Promise<boolean>;
16
39
  private claimPendingNotifications;
17
40
  private dispatch;
18
41
  private dispatchBuiltIn;
19
42
  private readHostDispatcher;
20
43
  private dispatchEmail;
44
+ private createEmailTransport;
45
+ private readRecipientEmail;
21
46
  private dispatchWebhook;
22
47
  private recordDeliveryFailure;
23
48
  }
@@ -11,11 +11,13 @@ const nodemailer = require("nodemailer");
11
11
  const typeorm_2 = require("typeorm");
12
12
  const identity_service_1 = require("../identity/identity.service");
13
13
  const notification_dispatcher_token_1 = require("./notification-dispatcher.token");
14
+ const notification_preference_entity_1 = require("./notification-preference.entity");
14
15
  const notification_entity_1 = require("./notification.entity");
15
16
  const notification_enums_1 = require("./notification.enums");
16
17
  let NotificationDeliveryService = NotificationDeliveryService_1 = class NotificationDeliveryService {
17
- constructor(notificationRepository, moduleRef) {
18
+ constructor(notificationRepository, notificationPreferenceRepository, moduleRef) {
18
19
  this.notificationRepository = notificationRepository;
20
+ this.notificationPreferenceRepository = notificationPreferenceRepository;
19
21
  this.moduleRef = moduleRef;
20
22
  this.logger = new common_1.Logger(NotificationDeliveryService_1.name);
21
23
  }
@@ -26,8 +28,117 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
26
28
  limit: deliveryLimit,
27
29
  now,
28
30
  });
29
- const results = await Promise.all(pendingNotifications.map((notification) => this.deliverNotification(notification, options)));
30
- return results.filter(Boolean).length;
31
+ const { digests, individual } = await this.groupDigestBatches(pendingNotifications);
32
+ const results = await Promise.all([
33
+ ...individual.map((notification) => this.deliverNotification(notification, options)),
34
+ ...digests.map((batch) => this.deliverDigest(batch, options)),
35
+ ]);
36
+ // `deliverNotification` reports a boolean per row and `deliverDigest` a
37
+ // row count, so both coerce to "notifications delivered".
38
+ return results.reduce((total, result) => total + Number(result), 0);
39
+ }
40
+ /**
41
+ * Splits a claimed batch into recipients who asked for a daily digest and
42
+ * everyone else.
43
+ *
44
+ * Only email digests, and only when a recipient has more than one row
45
+ * waiting — a "digest" of a single notification is just that notification
46
+ * with a worse subject line.
47
+ */
48
+ async groupDigestBatches(notifications) {
49
+ const emailNotifications = notifications.filter((notification) => notification.channel === notification_enums_1.NotificationChannelEnum.EMAIL);
50
+ if (emailNotifications.length === 0) {
51
+ return { digests: [], individual: notifications };
52
+ }
53
+ const digestMemberIds = await this.readDailyDigestMemberIds(uniqueStrings(emailNotifications.map((notification) => notification.recipientMemberId)));
54
+ const byRecipient = emailNotifications.reduce((groups, notification) => {
55
+ if (!digestMemberIds.has(notification.recipientMemberId)) {
56
+ return groups;
57
+ }
58
+ const group = groups.get(notification.recipientMemberId) ?? [];
59
+ group.push(notification);
60
+ groups.set(notification.recipientMemberId, group);
61
+ return groups;
62
+ }, new Map());
63
+ const digests = [...byRecipient.values()].filter((group) => group.length > 1);
64
+ const digestedIds = new Set(digests.flatMap((group) => group.map((notification) => notification.id)));
65
+ return {
66
+ digests,
67
+ individual: notifications.filter((notification) => !digestedIds.has(notification.id)),
68
+ };
69
+ }
70
+ async readDailyDigestMemberIds(memberIds) {
71
+ if (memberIds.length === 0) {
72
+ return new Set();
73
+ }
74
+ const preferences = await this.notificationPreferenceRepository.find({
75
+ where: { memberId: (0, typeorm_2.In)([...memberIds]) },
76
+ });
77
+ return new Set(preferences
78
+ .filter((preference) => preference.emailDigestMode === notification_enums_1.NotificationDigestModeEnum.DAILY)
79
+ .map((preference) => preference.memberId));
80
+ }
81
+ /**
82
+ * Sends one message covering a recipient's held notifications and marks all
83
+ * of them delivered, so a member on `DAILY` gets one email rather than one
84
+ * per approval that happened overnight.
85
+ *
86
+ * Returns how many rows were delivered, so the scan's count still reflects
87
+ * notifications rather than messages.
88
+ */
89
+ async deliverDigest(notifications, options) {
90
+ try {
91
+ const deliveryTarget = await withDispatchTimeout(this.dispatchDigest(notifications, options), options.deliveryDispatchTimeoutMs);
92
+ const deliveredAt = new Date();
93
+ await this.notificationRepository.save(notifications.map((notification) => ({
94
+ ...notification,
95
+ attemptCount: notification.attemptCount + 1,
96
+ deliveredAt,
97
+ deliveryError: null,
98
+ deliveryTarget,
99
+ lastAttemptAt: deliveredAt,
100
+ nextRetryAt: null,
101
+ sentAt: deliveredAt,
102
+ status: notification_enums_1.NotificationStatusEnum.SENT,
103
+ })));
104
+ return notifications.length;
105
+ }
106
+ catch (error) {
107
+ const errorMessage = readErrorMessage(error);
108
+ // Recorded per row: a digest that fails must leave each notification
109
+ // retryable on its own terms, not strand the whole batch.
110
+ await Promise.all(notifications.map((notification) => this.recordDeliveryFailure(notification, errorMessage, options)));
111
+ return 0;
112
+ }
113
+ }
114
+ async dispatchDigest(notifications, options) {
115
+ const hostDispatcher = this.readHostDispatcher();
116
+ if (hostDispatcher?.dispatchDigest) {
117
+ return hostDispatcher.dispatchDigest(notifications, options);
118
+ }
119
+ if (hostDispatcher) {
120
+ // The host owns delivery and cannot combine, so honour the hold but not
121
+ // the merge: every row still goes out now, at the digest hour.
122
+ const targets = await notifications.reduce(async (previousPromise, notification) => [
123
+ ...(await previousPromise),
124
+ await hostDispatcher.dispatch(notification, options),
125
+ ], Promise.resolve([]));
126
+ return targets[0] ?? '';
127
+ }
128
+ return this.dispatchDigestEmail(notifications, options);
129
+ }
130
+ async dispatchDigestEmail(notifications, options) {
131
+ const transporter = this.createEmailTransport(options);
132
+ const recipientEmail = await this.readRecipientEmail(notifications[0].recipientMemberId);
133
+ await transporter.sendMail({
134
+ from: options.emailFrom ?? '',
135
+ subject: `BPM 通知摘要(${notifications.length} 則)`,
136
+ text: notifications
137
+ .map((notification) => `${notification.title}\n${notification.body}`)
138
+ .join('\n\n---\n\n'),
139
+ to: recipientEmail,
140
+ });
141
+ return recipientEmail;
31
142
  }
32
143
  async deliverNotification(notification, options) {
33
144
  if (notification.channel === notification_enums_1.NotificationChannelEnum.IN_APP) {
@@ -38,7 +149,7 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
38
149
  return false;
39
150
  }
40
151
  try {
41
- const deliveryTarget = await this.dispatch(notification, options);
152
+ const deliveryTarget = await withDispatchTimeout(this.dispatch(notification, options), options.deliveryDispatchTimeoutMs);
42
153
  await this.notificationRepository.save({
43
154
  ...notification,
44
155
  attemptCount: notification.attemptCount + 1,
@@ -109,12 +220,20 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
109
220
  notification_enums_1.NotificationStatusEnum.DELIVERY_IN_PROGRESS,
110
221
  claimStaleBefore,
111
222
  ]));
112
- const claimedIds = claimedRows.map((row) => row.id);
113
- return claimedIds.length
114
- ? manager
115
- .getRepository(notification_entity_1.NotificationEntity)
116
- .find({ where: { id: (0, typeorm_2.In)(claimedIds) } })
117
- : [];
223
+ const claimedIds = readClaimedIds(claimedRows);
224
+ if (claimedIds.length === 0) {
225
+ return [];
226
+ }
227
+ const claimedNotifications = await manager
228
+ .getRepository(notification_entity_1.NotificationEntity)
229
+ .find({ where: { id: (0, typeorm_2.In)([...claimedIds]) } });
230
+ if (claimedNotifications.length !== claimedIds.length) {
231
+ // A row moved to `DELIVERY_IN_PROGRESS` that this pass then cannot
232
+ // load would sit claimed with nothing to show for it, so say so
233
+ // rather than let the next stale window quietly re-claim it.
234
+ this.logger.warn(`Claimed ${claimedIds.length} notifications but loaded ${claimedNotifications.length}; unloaded rows stay DELIVERY_IN_PROGRESS until the next stale claim`);
235
+ }
236
+ return claimedNotifications;
118
237
  });
119
238
  }
120
239
  async dispatch(notification, options) {
@@ -144,6 +263,17 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
144
263
  }
145
264
  }
146
265
  async dispatchEmail(notification, options) {
266
+ const transporter = this.createEmailTransport(options);
267
+ const recipientEmail = await this.readRecipientEmail(notification.recipientMemberId);
268
+ await transporter.sendMail({
269
+ from: options.emailFrom ?? '',
270
+ subject: notification.title,
271
+ text: notification.body,
272
+ to: recipientEmail,
273
+ });
274
+ return recipientEmail;
275
+ }
276
+ createEmailTransport(options) {
147
277
  if (!options.emailEnabled ||
148
278
  !options.emailSmtpHost ||
149
279
  !options.emailSmtpPort ||
@@ -152,11 +282,7 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
152
282
  !options.emailFrom) {
153
283
  throw new Error('EMAIL_DISABLED');
154
284
  }
155
- const identityService = this.moduleRef.get(identity_service_1.IdentityService, {
156
- strict: false,
157
- });
158
- const recipient = await identityService.resolveMember(notification.recipientMemberId);
159
- const transporter = nodemailer.createTransport({
285
+ return nodemailer.createTransport({
160
286
  auth: {
161
287
  pass: options.emailSmtpPassword,
162
288
  user: options.emailSmtpUsername,
@@ -165,12 +291,12 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
165
291
  port: options.emailSmtpPort,
166
292
  secure: options.emailSmtpSecure,
167
293
  });
168
- await transporter.sendMail({
169
- from: options.emailFrom,
170
- subject: notification.title,
171
- text: notification.body,
172
- to: recipient.email,
294
+ }
295
+ async readRecipientEmail(memberId) {
296
+ const identityService = this.moduleRef.get(identity_service_1.IdentityService, {
297
+ strict: false,
173
298
  });
299
+ const recipient = await identityService.resolveMember(memberId);
174
300
  return recipient.email;
175
301
  }
176
302
  async dispatchWebhook(notification, options) {
@@ -230,12 +356,71 @@ exports.NotificationDeliveryService = NotificationDeliveryService;
230
356
  exports.NotificationDeliveryService = NotificationDeliveryService = NotificationDeliveryService_1 = tslib_1.__decorate([
231
357
  (0, common_1.Injectable)(),
232
358
  tslib_1.__param(0, (0, typeorm_1.InjectRepository)(notification_entity_1.NotificationEntity)),
359
+ tslib_1.__param(1, (0, typeorm_1.InjectRepository)(notification_preference_entity_1.NotificationPreferenceEntity)),
233
360
  tslib_1.__metadata("design:paramtypes", [typeorm_2.Repository,
361
+ typeorm_2.Repository,
234
362
  core_1.ModuleRef])
235
363
  ], NotificationDeliveryService);
364
+ function uniqueStrings(values) {
365
+ return Array.from(new Set(values));
366
+ }
236
367
  function readErrorMessage(error) {
237
368
  return error instanceof Error ? error.message : 'Unknown delivery error';
238
369
  }
370
+ /**
371
+ * Reads the ids returned by the claiming `UPDATE ... RETURNING id`.
372
+ *
373
+ * TypeORM's Postgres driver returns `[rows, affectedCount]` for `UPDATE` and
374
+ * `DELETE`, and a bare row array for everything else. Reading the two-element
375
+ * form as a row array yields `[undefined, undefined]`, which matches no row —
376
+ * the claim commits, the delivery pass finds nothing, and the row is re-claimed
377
+ * on every stale window forever with `attempt_count` still at 0. Both shapes
378
+ * are accepted here so the claim does not depend on driver-specific packaging.
379
+ */
380
+ function readClaimedIds(rawResult) {
381
+ const rows = Array.isArray(rawResult) && Array.isArray(rawResult[0])
382
+ ? rawResult[0]
383
+ : rawResult;
384
+ if (!Array.isArray(rows)) {
385
+ return [];
386
+ }
387
+ return rows
388
+ .map((row) => row && typeof row === 'object' && 'id' in row
389
+ ? row.id
390
+ : undefined)
391
+ .filter((id) => typeof id === 'string' && id.length > 0);
392
+ }
393
+ /**
394
+ * Fails a dispatch that never settles.
395
+ *
396
+ * Delivery marks a row `DELIVERY_IN_PROGRESS` before dispatching, and only the
397
+ * resolve and reject paths write back. A host dispatcher, member resolver or
398
+ * SMTP call that hangs would therefore leave a permanently claimed row with an
399
+ * empty `delivery_error` — nothing for the host to diagnose. A timeout turns
400
+ * that into an ordinary recorded failure that retries.
401
+ */
402
+ async function withDispatchTimeout(operation, timeoutMs) {
403
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
404
+ return operation;
405
+ }
406
+ let timer;
407
+ try {
408
+ return await Promise.race([
409
+ operation,
410
+ new Promise((_resolve, reject) => {
411
+ timer = setTimeout(() => {
412
+ reject(new Error(`DELIVERY_TIMEOUT_${timeoutMs}MS`));
413
+ }, timeoutMs);
414
+ timer.unref();
415
+ }),
416
+ ]);
417
+ }
418
+ finally {
419
+ if (timer) {
420
+ clearTimeout(timer);
421
+ }
422
+ }
423
+ }
239
424
  function normalizePositiveInteger(value, fallback) {
240
425
  if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) {
241
426
  return fallback;
@@ -1 +1 @@
1
- {"version":3,"file":"notification-delivery.service.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-delivery.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notification-delivery.service.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-delivery.service.ts"],"names":[],"mappings":"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"}
@@ -3,5 +3,18 @@ import { NotificationEntity } from './notification.entity';
3
3
  import { BPMResolvedNotificationOptions } from './notification-options';
4
4
  export interface BPMNotificationDispatcher {
5
5
  dispatch(notification: NotificationEntity, options: BPMResolvedNotificationOptions): Promise<string>;
6
+ /**
7
+ * Sends one message covering several notifications, for a recipient whose
8
+ * `emailDigestMode` is `DAILY`.
9
+ *
10
+ * Optional. Without it BPM falls back to {@link dispatch} once per row, so
11
+ * a `DAILY` recipient still gets their email held until the digest hour but
12
+ * receives one message per notification rather than one combined message.
13
+ * BPM's built-in SMTP path always combines.
14
+ *
15
+ * Every notification in the batch is for the same recipient and channel.
16
+ * Return the delivery target recorded against every row in the batch.
17
+ */
18
+ dispatchDigest?(notifications: readonly NotificationEntity[], options: BPMResolvedNotificationOptions): Promise<string>;
6
19
  }
7
20
  export declare const BPM_NOTIFICATION_DISPATCHER: InjectionToken<BPMNotificationDispatcher>;
@@ -1 +1 @@
1
- {"version":3,"file":"notification-dispatcher.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-dispatcher.token.ts"],"names":[],"mappings":";;;AAWa,QAAA,2BAA2B,GACtC,MAAM,CAAC,6BAA6B,CAAC,CAAC"}
1
+ {"version":3,"file":"notification-dispatcher.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-dispatcher.token.ts"],"names":[],"mappings":";;;AA4Ba,QAAA,2BAA2B,GACtC,MAAM,CAAC,6BAA6B,CAAC,CAAC"}
@@ -11,6 +11,12 @@ export interface BPMNotificationsCreatedEvent {
11
11
  * Note that a batch is always for **one recipient**: several rows mean
12
12
  * several channels, not several people. A node assigned to three approvers
13
13
  * produces three separate events.
14
+ *
15
+ * A row whose `silenced` flag is set was recorded but must not be
16
+ * announced: the recipient turned in-app notifications off, or it arrived
17
+ * inside their quiet hours. Push it into the list without a toast rather
18
+ * than skipping it — the row exists precisely so the notification centre
19
+ * stays complete.
14
20
  */
15
21
  readonly notifications: readonly NotificationEntity[];
16
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"notification-observer.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-observer.token.ts"],"names":[],"mappings":";;;AAwDa,QAAA,yBAAyB,GACpC,MAAM,CAAC,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"notification-observer.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-observer.token.ts"],"names":[],"mappings":";;;AA8Da,QAAA,yBAAyB,GACpC,MAAM,CAAC,2BAA2B,CAAC,CAAC"}
@@ -112,6 +112,18 @@ export interface BPMRootNotificationOptions {
112
112
  * by the current attempt count.
113
113
  */
114
114
  readonly notificationDeliveryRetryBaseDelayMs?: number;
115
+ /**
116
+ * Maximum time in milliseconds a single delivery dispatch may take before it
117
+ * is recorded as a failed attempt.
118
+ *
119
+ * Covers the whole dispatch, including the host `BPM_NOTIFICATION_DISPATCHER`,
120
+ * member resolution and the SMTP or webhook call. Delivery claims a row
121
+ * before dispatching and only writes back on success or failure, so a
122
+ * dispatch that never settles would otherwise leave that row permanently in
123
+ * `DELIVERY_IN_PROGRESS` with no recorded error. Defaults to `30000`. Set to
124
+ * `0` to wait indefinitely.
125
+ */
126
+ readonly notificationDeliveryDispatchTimeoutMs?: number;
115
127
  /**
116
128
  * Enables the background SLA scheduler that scans pending tasks.
117
129
  *
@@ -179,6 +191,28 @@ export interface BPMRootNotificationOptions {
179
191
  * Default email digest mode for members without a stored preference.
180
192
  */
181
193
  readonly notificationDefaultEmailDigestMode?: NotificationDigestModeEnum;
194
+ /**
195
+ * IANA time zone the members' `quietHoursStart` / `quietHoursEnd`
196
+ * preferences are read in.
197
+ *
198
+ * Those columns store a bare wall-clock time, so a zone is required to turn
199
+ * "22:00" into an instant. When omitted, BPM reads the zone off the
200
+ * registered `BPM_BUSINESS_CALENDAR` — the host's own calendar when it
201
+ * supplied one, otherwise the built-in weekday calendar built from
202
+ * `notificationSlaBusinessCalendarTimeZone`. A host that already told BPM
203
+ * where its people work therefore gets sensible quiet hours without a second
204
+ * setting. Set this only when notification quiet hours and business days
205
+ * belong to different zones.
206
+ */
207
+ readonly notificationQuietHoursTimeZone?: string;
208
+ /**
209
+ * Local hour (0–23) at which held email is flushed for members whose
210
+ * `emailDigestMode` is `DAILY`.
211
+ *
212
+ * Read in `notificationQuietHoursTimeZone`. Defaults to `9`. Values outside
213
+ * 0–23 fall back to the default rather than throwing at wiring time.
214
+ */
215
+ readonly notificationEmailDigestHour?: number;
182
216
  /**
183
217
  * Default in-app notification preference for members without a stored
184
218
  * preference.
@@ -204,10 +238,19 @@ export interface BPMResolvedNotificationOptions {
204
238
  readonly defaultEmailPreferenceEnabled: boolean;
205
239
  readonly defaultInAppPreferenceEnabled: boolean;
206
240
  readonly deliveryBatchSize: number;
241
+ readonly deliveryDispatchTimeoutMs: number;
207
242
  readonly deliveryMaxAttempts: number;
208
243
  readonly deliveryRetryBaseDelayMs: number;
209
244
  readonly deliveryScanIntervalMs: number;
210
245
  readonly deliverySchedulerEnabled: boolean;
246
+ readonly emailDigestHour: number;
247
+ /**
248
+ * `null` when the host did not configure one, which means "use the
249
+ * registered business calendar's zone" — resolved at notification time,
250
+ * because the calendar is a DI provider and options are flattened before it
251
+ * exists.
252
+ */
253
+ readonly quietHoursTimeZone: string | null;
211
254
  readonly slaBusinessCalendarTimeZone: string;
212
255
  readonly slaScanIntervalMs: number;
213
256
  readonly slaSchedulerEnabled: boolean;