@rytass/bpm-core-nestjs-module 0.9.1 → 0.10.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.
- package/CHANGELOG.md +46 -0
- package/README.md +17 -5
- package/package.json +2 -2
- package/src/lib/attachment/attachment-options.js +7 -1
- package/src/lib/attachment/attachment-options.js.map +1 -1
- package/src/lib/attachment/attachment.service.js +7 -0
- package/src/lib/attachment/attachment.service.js.map +1 -1
- package/src/lib/bpm/bpm-root.module.d.ts +11 -0
- package/src/lib/bpm/bpm-root.module.js.map +1 -1
- package/src/lib/calendar/calendar.module.d.ts +12 -0
- package/src/lib/calendar/calendar.module.js.map +1 -1
- package/src/lib/common/filters/all-exceptions.filter.d.ts +11 -0
- package/src/lib/common/filters/all-exceptions.filter.js +35 -1
- package/src/lib/common/filters/all-exceptions.filter.js.map +1 -1
- package/src/lib/form-data-source/form-data-source-value-resolver.service.d.ts +6 -7
- package/src/lib/form-data-source/form-data-source-value-resolver.service.js +91 -291
- package/src/lib/form-data-source/form-data-source-value-resolver.service.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.queries.d.ts +24 -0
- package/src/lib/form-data-source/form-data-source.queries.js +179 -7
- package/src/lib/form-data-source/form-data-source.queries.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.service.d.ts +36 -21
- package/src/lib/form-data-source/form-data-source.service.js +143 -359
- package/src/lib/form-data-source/form-data-source.service.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.types.d.ts +17 -0
- package/src/lib/form-data-source/form-data-source.types.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.validation.d.ts +78 -0
- package/src/lib/form-data-source/form-data-source.validation.js +409 -0
- package/src/lib/form-data-source/form-data-source.validation.js.map +1 -0
- package/src/lib/migrations/0000000021000-notification-silenced.d.ts +15 -0
- package/src/lib/migrations/0000000021000-notification-silenced.js +31 -0
- package/src/lib/migrations/0000000021000-notification-silenced.js.map +1 -0
- package/src/lib/migrations/index.d.ts +1 -0
- package/src/lib/migrations/index.js +3 -0
- package/src/lib/migrations/index.js.map +1 -1
- package/src/lib/notification/index.d.ts +1 -0
- package/src/lib/notification/index.js +1 -0
- package/src/lib/notification/index.js.map +1 -1
- package/src/lib/notification/notification-delivery.service.d.ts +26 -1
- package/src/lib/notification/notification-delivery.service.js +136 -13
- package/src/lib/notification/notification-delivery.service.js.map +1 -1
- package/src/lib/notification/notification-dispatcher.token.d.ts +13 -0
- package/src/lib/notification/notification-dispatcher.token.js.map +1 -1
- package/src/lib/notification/notification-observer.token.d.ts +6 -0
- package/src/lib/notification/notification-observer.token.js.map +1 -1
- package/src/lib/notification/notification-options.d.ts +30 -0
- package/src/lib/notification/notification-options.js +32 -4
- package/src/lib/notification/notification-options.js.map +1 -1
- package/src/lib/notification/notification-schedule.d.ts +41 -0
- package/src/lib/notification/notification-schedule.js +158 -0
- package/src/lib/notification/notification-schedule.js.map +1 -0
- package/src/lib/notification/notification.entity.d.ts +12 -0
- package/src/lib/notification/notification.entity.js +5 -0
- package/src/lib/notification/notification.entity.js.map +1 -1
- package/src/lib/notification/notification.service.d.ts +10 -0
- package/src/lib/notification/notification.service.js +100 -21
- package/src/lib/notification/notification.service.js.map +1 -1
- package/src/lib/template/index.d.ts +1 -0
- package/src/lib/template/index.js +1 -0
- package/src/lib/template/index.js.map +1 -1
- package/src/lib/template/template-observer.token.d.ts +67 -0
- package/src/lib/template/template-observer.token.js +16 -0
- package/src/lib/template/template-observer.token.js.map +1 -0
- package/src/lib/template/template.mutations.d.ts +1 -1
- package/src/lib/template/template.mutations.js +4 -3
- package/src/lib/template/template.mutations.js.map +1 -1
- package/src/lib/template/template.service.d.ts +18 -2
- package/src/lib/template/template.service.js +117 -17
- 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;
|
|
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
|
|
30
|
-
|
|
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 this.dispatchDigest(notifications, options);
|
|
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) {
|
|
@@ -144,6 +255,17 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
|
|
|
144
255
|
}
|
|
145
256
|
}
|
|
146
257
|
async dispatchEmail(notification, options) {
|
|
258
|
+
const transporter = this.createEmailTransport(options);
|
|
259
|
+
const recipientEmail = await this.readRecipientEmail(notification.recipientMemberId);
|
|
260
|
+
await transporter.sendMail({
|
|
261
|
+
from: options.emailFrom ?? '',
|
|
262
|
+
subject: notification.title,
|
|
263
|
+
text: notification.body,
|
|
264
|
+
to: recipientEmail,
|
|
265
|
+
});
|
|
266
|
+
return recipientEmail;
|
|
267
|
+
}
|
|
268
|
+
createEmailTransport(options) {
|
|
147
269
|
if (!options.emailEnabled ||
|
|
148
270
|
!options.emailSmtpHost ||
|
|
149
271
|
!options.emailSmtpPort ||
|
|
@@ -152,11 +274,7 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
|
|
|
152
274
|
!options.emailFrom) {
|
|
153
275
|
throw new Error('EMAIL_DISABLED');
|
|
154
276
|
}
|
|
155
|
-
|
|
156
|
-
strict: false,
|
|
157
|
-
});
|
|
158
|
-
const recipient = await identityService.resolveMember(notification.recipientMemberId);
|
|
159
|
-
const transporter = nodemailer.createTransport({
|
|
277
|
+
return nodemailer.createTransport({
|
|
160
278
|
auth: {
|
|
161
279
|
pass: options.emailSmtpPassword,
|
|
162
280
|
user: options.emailSmtpUsername,
|
|
@@ -165,12 +283,12 @@ let NotificationDeliveryService = NotificationDeliveryService_1 = class Notifica
|
|
|
165
283
|
port: options.emailSmtpPort,
|
|
166
284
|
secure: options.emailSmtpSecure,
|
|
167
285
|
});
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
to: recipient.email,
|
|
286
|
+
}
|
|
287
|
+
async readRecipientEmail(memberId) {
|
|
288
|
+
const identityService = this.moduleRef.get(identity_service_1.IdentityService, {
|
|
289
|
+
strict: false,
|
|
173
290
|
});
|
|
291
|
+
const recipient = await identityService.resolveMember(memberId);
|
|
174
292
|
return recipient.email;
|
|
175
293
|
}
|
|
176
294
|
async dispatchWebhook(notification, options) {
|
|
@@ -230,9 +348,14 @@ exports.NotificationDeliveryService = NotificationDeliveryService;
|
|
|
230
348
|
exports.NotificationDeliveryService = NotificationDeliveryService = NotificationDeliveryService_1 = tslib_1.__decorate([
|
|
231
349
|
(0, common_1.Injectable)(),
|
|
232
350
|
tslib_1.__param(0, (0, typeorm_1.InjectRepository)(notification_entity_1.NotificationEntity)),
|
|
351
|
+
tslib_1.__param(1, (0, typeorm_1.InjectRepository)(notification_preference_entity_1.NotificationPreferenceEntity)),
|
|
233
352
|
tslib_1.__metadata("design:paramtypes", [typeorm_2.Repository,
|
|
353
|
+
typeorm_2.Repository,
|
|
234
354
|
core_1.ModuleRef])
|
|
235
355
|
], NotificationDeliveryService);
|
|
356
|
+
function uniqueStrings(values) {
|
|
357
|
+
return Array.from(new Set(values));
|
|
358
|
+
}
|
|
236
359
|
function readErrorMessage(error) {
|
|
237
360
|
return error instanceof Error ? error.message : 'Unknown delivery error';
|
|
238
361
|
}
|
|
@@ -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":";;;
|
|
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":";;;
|
|
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"}
|
|
@@ -179,6 +179,28 @@ export interface BPMRootNotificationOptions {
|
|
|
179
179
|
* Default email digest mode for members without a stored preference.
|
|
180
180
|
*/
|
|
181
181
|
readonly notificationDefaultEmailDigestMode?: NotificationDigestModeEnum;
|
|
182
|
+
/**
|
|
183
|
+
* IANA time zone the members' `quietHoursStart` / `quietHoursEnd`
|
|
184
|
+
* preferences are read in.
|
|
185
|
+
*
|
|
186
|
+
* Those columns store a bare wall-clock time, so a zone is required to turn
|
|
187
|
+
* "22:00" into an instant. When omitted, BPM reads the zone off the
|
|
188
|
+
* registered `BPM_BUSINESS_CALENDAR` — the host's own calendar when it
|
|
189
|
+
* supplied one, otherwise the built-in weekday calendar built from
|
|
190
|
+
* `notificationSlaBusinessCalendarTimeZone`. A host that already told BPM
|
|
191
|
+
* where its people work therefore gets sensible quiet hours without a second
|
|
192
|
+
* setting. Set this only when notification quiet hours and business days
|
|
193
|
+
* belong to different zones.
|
|
194
|
+
*/
|
|
195
|
+
readonly notificationQuietHoursTimeZone?: string;
|
|
196
|
+
/**
|
|
197
|
+
* Local hour (0–23) at which held email is flushed for members whose
|
|
198
|
+
* `emailDigestMode` is `DAILY`.
|
|
199
|
+
*
|
|
200
|
+
* Read in `notificationQuietHoursTimeZone`. Defaults to `9`. Values outside
|
|
201
|
+
* 0–23 fall back to the default rather than throwing at wiring time.
|
|
202
|
+
*/
|
|
203
|
+
readonly notificationEmailDigestHour?: number;
|
|
182
204
|
/**
|
|
183
205
|
* Default in-app notification preference for members without a stored
|
|
184
206
|
* preference.
|
|
@@ -208,6 +230,14 @@ export interface BPMResolvedNotificationOptions {
|
|
|
208
230
|
readonly deliveryRetryBaseDelayMs: number;
|
|
209
231
|
readonly deliveryScanIntervalMs: number;
|
|
210
232
|
readonly deliverySchedulerEnabled: boolean;
|
|
233
|
+
readonly emailDigestHour: number;
|
|
234
|
+
/**
|
|
235
|
+
* `null` when the host did not configure one, which means "use the
|
|
236
|
+
* registered business calendar's zone" — resolved at notification time,
|
|
237
|
+
* because the calendar is a DI provider and options are flattened before it
|
|
238
|
+
* exists.
|
|
239
|
+
*/
|
|
240
|
+
readonly quietHoursTimeZone: string | null;
|
|
211
241
|
readonly slaBusinessCalendarTimeZone: string;
|
|
212
242
|
readonly slaScanIntervalMs: number;
|
|
213
243
|
readonly slaSchedulerEnabled: boolean;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEFAULT_BPM_NOTIFICATION_OPTIONS = exports.BPM_NOTIFICATION_OPTIONS = void 0;
|
|
4
4
|
exports.resolveBPMNotificationOptions = resolveBPMNotificationOptions;
|
|
5
|
+
const notification_schedule_1 = require("./notification-schedule");
|
|
5
6
|
const notification_enums_1 = require("./notification.enums");
|
|
6
7
|
exports.BPM_NOTIFICATION_OPTIONS = Symbol('BPM_NOTIFICATION_OPTIONS');
|
|
7
8
|
exports.DEFAULT_BPM_NOTIFICATION_OPTIONS = {
|
|
@@ -22,6 +23,8 @@ exports.DEFAULT_BPM_NOTIFICATION_OPTIONS = {
|
|
|
22
23
|
deliveryRetryBaseDelayMs: 60_000,
|
|
23
24
|
deliveryScanIntervalMs: 30_000,
|
|
24
25
|
deliverySchedulerEnabled: false,
|
|
26
|
+
emailDigestHour: notification_schedule_1.DEFAULT_EMAIL_DIGEST_HOUR,
|
|
27
|
+
quietHoursTimeZone: null,
|
|
25
28
|
slaBusinessCalendarTimeZone: 'UTC',
|
|
26
29
|
slaScanIntervalMs: 60_000,
|
|
27
30
|
slaSchedulerEnabled: false,
|
|
@@ -42,6 +45,7 @@ function resolveBPMNotificationOptions(options = {}) {
|
|
|
42
45
|
const emailFrom = normalizeText(options.notificationEmailFrom);
|
|
43
46
|
const webhookSigningSecret = normalizeText(options.notificationWebhookSigningSecret);
|
|
44
47
|
const webhookEndpointUrl = normalizeText(options.notificationWebhookEndpointUrl);
|
|
48
|
+
const slaBusinessCalendarTimeZone = normalizeTimeZone(options.notificationSlaBusinessCalendarTimeZone, exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.slaBusinessCalendarTimeZone);
|
|
45
49
|
return {
|
|
46
50
|
deliveryScanIntervalMs: normalizeInterval(options.notificationDeliveryScanIntervalMs, exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.deliveryScanIntervalMs),
|
|
47
51
|
deliveryBatchSize: normalizePositiveInteger(options.notificationDeliveryBatchSize, exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.deliveryBatchSize),
|
|
@@ -70,7 +74,13 @@ function resolveBPMNotificationOptions(options = {}) {
|
|
|
70
74
|
exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.defaultEmailPreferenceEnabled,
|
|
71
75
|
defaultInAppPreferenceEnabled: options.notificationDefaultInAppPreferenceEnabled ??
|
|
72
76
|
exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.defaultInAppPreferenceEnabled,
|
|
73
|
-
|
|
77
|
+
emailDigestHour: (0, notification_schedule_1.normalizeDigestHour)(options.notificationEmailDigestHour),
|
|
78
|
+
// Left null when unset so `NotificationService` can read the zone off the
|
|
79
|
+
// registered business calendar. Resolving it here would silently mean UTC
|
|
80
|
+
// for every host that supplies its own calendar — the calendar knows the
|
|
81
|
+
// zone, but it does not exist yet at option-flattening time.
|
|
82
|
+
quietHoursTimeZone: normalizeOptionalTimeZone(options.notificationQuietHoursTimeZone),
|
|
83
|
+
slaBusinessCalendarTimeZone,
|
|
74
84
|
slaScanIntervalMs: normalizeInterval(options.notificationSlaScanIntervalMs, exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.slaScanIntervalMs),
|
|
75
85
|
slaSchedulerEnabled: options.notificationSlaSchedulerEnabled ??
|
|
76
86
|
exports.DEFAULT_BPM_NOTIFICATION_OPTIONS.slaSchedulerEnabled,
|
|
@@ -101,21 +111,39 @@ function normalizePort(value) {
|
|
|
101
111
|
? value
|
|
102
112
|
: null;
|
|
103
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* As {@link normalizeTimeZone}, but reports "not configured" as `null` instead
|
|
116
|
+
* of substituting a fallback. An unreadable zone is treated as absent, so the
|
|
117
|
+
* caller's own fallback applies rather than a silently wrong zone.
|
|
118
|
+
*/
|
|
119
|
+
function normalizeOptionalTimeZone(value) {
|
|
120
|
+
const trimmedValue = value?.trim() ?? '';
|
|
121
|
+
if (!trimmedValue) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
new Intl.DateTimeFormat('en-CA', { timeZone: trimmedValue });
|
|
126
|
+
return trimmedValue;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
104
132
|
/**
|
|
105
133
|
* Rejects unknown IANA zones at wiring time rather than letting every SLA
|
|
106
134
|
* calculation throw later inside `Intl.DateTimeFormat`.
|
|
107
135
|
*/
|
|
108
|
-
function normalizeTimeZone(value) {
|
|
136
|
+
function normalizeTimeZone(value, fallback) {
|
|
109
137
|
const trimmedValue = value?.trim() ?? '';
|
|
110
138
|
if (!trimmedValue) {
|
|
111
|
-
return
|
|
139
|
+
return fallback;
|
|
112
140
|
}
|
|
113
141
|
try {
|
|
114
142
|
new Intl.DateTimeFormat('en-CA', { timeZone: trimmedValue });
|
|
115
143
|
return trimmedValue;
|
|
116
144
|
}
|
|
117
145
|
catch {
|
|
118
|
-
return
|
|
146
|
+
return fallback;
|
|
119
147
|
}
|
|
120
148
|
}
|
|
121
149
|
function normalizeInterval(value, fallback) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-options.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-options.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"notification-options.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/notification/notification-options.ts"],"names":[],"mappings":"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"}
|