@carlonicora/nestjs-neo4jsonapi 8.9.0 → 8.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/constants/core-module.ids.d.ts +1 -0
- package/dist/common/constants/core-module.ids.d.ts.map +1 -1
- package/dist/common/constants/core-module.ids.js +1 -0
- package/dist/common/constants/core-module.ids.js.map +1 -1
- package/dist/config/enums/queue.id.d.ts +1 -0
- package/dist/config/enums/queue.id.d.ts.map +1 -1
- package/dist/config/enums/queue.id.js +1 -0
- package/dist/config/enums/queue.id.js.map +1 -1
- package/dist/core/email/templates/en/emailBlast.hbs +24 -0
- package/dist/foundations/account-deletion/repositories/account-deletion.wipe.repository.d.ts.map +1 -1
- package/dist/foundations/account-deletion/repositories/account-deletion.wipe.repository.js +1 -0
- package/dist/foundations/account-deletion/repositories/account-deletion.wipe.repository.js.map +1 -1
- package/dist/foundations/email-automation/index.d.ts +1 -0
- package/dist/foundations/email-automation/index.d.ts.map +1 -1
- package/dist/foundations/email-automation/index.js +2 -0
- package/dist/foundations/email-automation/index.js.map +1 -1
- package/dist/foundations/email-automation/services/email-automation-renderer.service.d.ts.map +1 -1
- package/dist/foundations/email-automation/services/email-automation-renderer.service.js +2 -12
- package/dist/foundations/email-automation/services/email-automation-renderer.service.js.map +1 -1
- package/dist/foundations/email-automation/utils/email-markdown.renderer.d.ts +20 -0
- package/dist/foundations/email-automation/utils/email-markdown.renderer.d.ts.map +1 -0
- package/dist/foundations/email-automation/utils/email-markdown.renderer.js +63 -0
- package/dist/foundations/email-automation/utils/email-markdown.renderer.js.map +1 -0
- package/dist/foundations/email-blast/controllers/email-blast.controller.d.ts +30 -0
- package/dist/foundations/email-blast/controllers/email-blast.controller.d.ts.map +1 -0
- package/dist/foundations/email-blast/controllers/email-blast.controller.js +171 -0
- package/dist/foundations/email-blast/controllers/email-blast.controller.js.map +1 -0
- package/dist/foundations/email-blast/controllers/email-blast.public.controller.d.ts +24 -0
- package/dist/foundations/email-blast/controllers/email-blast.public.controller.d.ts.map +1 -0
- package/dist/foundations/email-blast/controllers/email-blast.public.controller.js +61 -0
- package/dist/foundations/email-blast/controllers/email-blast.public.controller.js.map +1 -0
- package/dist/foundations/email-blast/cron/email-blast-recovery.cron.d.ts +15 -0
- package/dist/foundations/email-blast/cron/email-blast-recovery.cron.d.ts.map +1 -0
- package/dist/foundations/email-blast/cron/email-blast-recovery.cron.js +50 -0
- package/dist/foundations/email-blast/cron/email-blast-recovery.cron.js.map +1 -0
- package/dist/foundations/email-blast/dtos/email-blast-unsubscribe.dto.d.ts +7 -0
- package/dist/foundations/email-blast/dtos/email-blast-unsubscribe.dto.d.ts.map +1 -0
- package/dist/foundations/email-blast/dtos/email-blast-unsubscribe.dto.js +35 -0
- package/dist/foundations/email-blast/dtos/email-blast-unsubscribe.dto.js.map +1 -0
- package/dist/foundations/email-blast/dtos/email-blast.patch.dto.d.ts +14 -0
- package/dist/foundations/email-blast/dtos/email-blast.patch.dto.d.ts.map +1 -0
- package/dist/foundations/email-blast/dtos/email-blast.patch.dto.js +63 -0
- package/dist/foundations/email-blast/dtos/email-blast.patch.dto.js.map +1 -0
- package/dist/foundations/email-blast/dtos/email-blast.post.dto.d.ts +14 -0
- package/dist/foundations/email-blast/dtos/email-blast.post.dto.d.ts.map +1 -0
- package/dist/foundations/email-blast/dtos/email-blast.post.dto.js +63 -0
- package/dist/foundations/email-blast/dtos/email-blast.post.dto.js.map +1 -0
- package/dist/foundations/email-blast/email-blast.constants.d.ts +34 -0
- package/dist/foundations/email-blast/email-blast.constants.d.ts.map +1 -0
- package/dist/foundations/email-blast/email-blast.constants.js +49 -0
- package/dist/foundations/email-blast/email-blast.constants.js.map +1 -0
- package/dist/foundations/email-blast/email-blast.module.d.ts +21 -0
- package/dist/foundations/email-blast/email-blast.module.d.ts.map +1 -0
- package/dist/foundations/email-blast/email-blast.module.js +101 -0
- package/dist/foundations/email-blast/email-blast.module.js.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.d.ts +10 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.d.ts.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.js +15 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.js.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.meta.d.ts +6 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.meta.d.ts.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.meta.js +13 -0
- package/dist/foundations/email-blast/entities/email-blast-audience.meta.js.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.d.ts +31 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.d.ts.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.js +34 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.js.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.meta.d.ts +3 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.meta.d.ts.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.meta.js +10 -0
- package/dist/foundations/email-blast/entities/email-blast-delivery.meta.js.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast.d.ts +16 -0
- package/dist/foundations/email-blast/entities/email-blast.d.ts.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast.js +25 -0
- package/dist/foundations/email-blast/entities/email-blast.js.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast.meta.d.ts +13 -0
- package/dist/foundations/email-blast/entities/email-blast.meta.d.ts.map +1 -0
- package/dist/foundations/email-blast/entities/email-blast.meta.js +20 -0
- package/dist/foundations/email-blast/entities/email-blast.meta.js.map +1 -0
- package/dist/foundations/email-blast/index.d.ts +20 -0
- package/dist/foundations/email-blast/index.d.ts.map +1 -0
- package/dist/foundations/email-blast/index.js +44 -0
- package/dist/foundations/email-blast/index.js.map +1 -0
- package/dist/foundations/email-blast/processors/email-blast.processor.d.ts +23 -0
- package/dist/foundations/email-blast/processors/email-blast.processor.d.ts.map +1 -0
- package/dist/foundations/email-blast/processors/email-blast.processor.js +80 -0
- package/dist/foundations/email-blast/processors/email-blast.processor.js.map +1 -0
- package/dist/foundations/email-blast/repositories/email-blast-delivery.repository.d.ts +98 -0
- package/dist/foundations/email-blast/repositories/email-blast-delivery.repository.d.ts.map +1 -0
- package/dist/foundations/email-blast/repositories/email-blast-delivery.repository.js +273 -0
- package/dist/foundations/email-blast/repositories/email-blast-delivery.repository.js.map +1 -0
- package/dist/foundations/email-blast/repositories/email-blast.admin.repository.d.ts +19 -0
- package/dist/foundations/email-blast/repositories/email-blast.admin.repository.d.ts.map +1 -0
- package/dist/foundations/email-blast/repositories/email-blast.admin.repository.js +63 -0
- package/dist/foundations/email-blast/repositories/email-blast.admin.repository.js.map +1 -0
- package/dist/foundations/email-blast/repositories/email-blast.repository.d.ts +29 -0
- package/dist/foundations/email-blast/repositories/email-blast.repository.d.ts.map +1 -0
- package/dist/foundations/email-blast/repositories/email-blast.repository.js +97 -0
- package/dist/foundations/email-blast/repositories/email-blast.repository.js.map +1 -0
- package/dist/foundations/email-blast/services/email-blast-delivery.service.d.ts +79 -0
- package/dist/foundations/email-blast/services/email-blast-delivery.service.d.ts.map +1 -0
- package/dist/foundations/email-blast/services/email-blast-delivery.service.js +206 -0
- package/dist/foundations/email-blast/services/email-blast-delivery.service.js.map +1 -0
- package/dist/foundations/email-blast/services/email-blast.service.d.ts +57 -0
- package/dist/foundations/email-blast/services/email-blast.service.d.ts.map +1 -0
- package/dist/foundations/email-blast/services/email-blast.service.js +134 -0
- package/dist/foundations/email-blast/services/email-blast.service.js.map +1 -0
- package/dist/foundations/email-blast/utils/email-blast.renderer.d.ts +29 -0
- package/dist/foundations/email-blast/utils/email-blast.renderer.d.ts.map +1 -0
- package/dist/foundations/email-blast/utils/email-blast.renderer.js +70 -0
- package/dist/foundations/email-blast/utils/email-blast.renderer.js.map +1 -0
- package/dist/foundations/foundations.modules.d.ts.map +1 -1
- package/dist/foundations/foundations.modules.js +3 -0
- package/dist/foundations/foundations.modules.js.map +1 -1
- package/dist/foundations/index.d.ts +1 -0
- package/dist/foundations/index.d.ts.map +1 -1
- package/dist/foundations/index.js +1 -0
- package/dist/foundations/index.js.map +1 -1
- package/dist/foundations/s3/services/s3.service.d.ts.map +1 -1
- package/dist/foundations/s3/services/s3.service.js +17 -0
- package/dist/foundations/s3/services/s3.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.EmailBlastPublicController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const cache_invalidate_decorator_1 = require("../../../common/decorators/cache-invalidate.decorator");
|
|
18
|
+
const cache_service_1 = require("../../../core/cache/services/cache.service");
|
|
19
|
+
const email_blast_unsubscribe_dto_1 = require("../dtos/email-blast-unsubscribe.dto");
|
|
20
|
+
const email_blast_meta_1 = require("../entities/email-blast.meta");
|
|
21
|
+
const email_blast_delivery_service_1 = require("../services/email-blast-delivery.service");
|
|
22
|
+
/**
|
|
23
|
+
* Public email-blast routes (no guard). Kept apart from the admin controller so the
|
|
24
|
+
* literal `unsubscribe` segment never collides with `:emailBlastId`.
|
|
25
|
+
*/
|
|
26
|
+
let EmailBlastPublicController = class EmailBlastPublicController {
|
|
27
|
+
constructor(deliveryService, cacheService) {
|
|
28
|
+
this.deliveryService = deliveryService;
|
|
29
|
+
this.cacheService = cacheService;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* POST /email-blasts/unsubscribe/:token — answers 204 with no body, so a token holder
|
|
33
|
+
* never receives the delivery's email or user id.
|
|
34
|
+
*
|
|
35
|
+
* Two callers:
|
|
36
|
+
* - the web page: JSON:API body `{ data: { type: EMAIL_BLAST_UNSUBSCRIBE_TYPE } }`;
|
|
37
|
+
* - a mail client's RFC 8058 one-click POST: form body `List-Unsubscribe=One-Click`. The
|
|
38
|
+
* global ValidationPipe whitelist strips the form key, so `body.data` is absent.
|
|
39
|
+
*/
|
|
40
|
+
async unsubscribe(request, token, body) {
|
|
41
|
+
await this.deliveryService.unsubscribe({ token, source: body?.data ? "link" : "header" });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
exports.EmailBlastPublicController = EmailBlastPublicController;
|
|
45
|
+
__decorate([
|
|
46
|
+
(0, common_1.Post)(`${email_blast_meta_1.emailBlastMeta.endpoint}/${email_blast_meta_1.EMAIL_BLAST_UNSUBSCRIBE_SEGMENT}/:token`),
|
|
47
|
+
(0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT),
|
|
48
|
+
(0, cache_invalidate_decorator_1.CacheInvalidate)(email_blast_meta_1.emailBlastMeta),
|
|
49
|
+
__param(0, (0, common_1.Req)()),
|
|
50
|
+
__param(1, (0, common_1.Param)("token")),
|
|
51
|
+
__param(2, (0, common_1.Body)()),
|
|
52
|
+
__metadata("design:type", Function),
|
|
53
|
+
__metadata("design:paramtypes", [Object, String, email_blast_unsubscribe_dto_1.EmailBlastUnsubscribeDTO]),
|
|
54
|
+
__metadata("design:returntype", Promise)
|
|
55
|
+
], EmailBlastPublicController.prototype, "unsubscribe", null);
|
|
56
|
+
exports.EmailBlastPublicController = EmailBlastPublicController = __decorate([
|
|
57
|
+
(0, common_1.Controller)(),
|
|
58
|
+
__metadata("design:paramtypes", [email_blast_delivery_service_1.EmailBlastDeliveryService,
|
|
59
|
+
cache_service_1.CacheService])
|
|
60
|
+
], EmailBlastPublicController);
|
|
61
|
+
//# sourceMappingURL=email-blast.public.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.public.controller.js","sourceRoot":"","sources":["../../../../src/foundations/email-blast/controllers/email-blast.public.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA0F;AAC1F,sGAAwF;AAExF,8EAA0E;AAC1E,qFAA+E;AAC/E,mEAA+F;AAC/F,2FAAqF;AAErF;;;GAGG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IACrC,YACmB,eAA0C,EAC1C,YAA0B;QAD1B,oBAAe,GAAf,eAAe,CAA2B;QAC1C,iBAAY,GAAZ,YAAY,CAAc;IAC1C,CAAC;IAEJ;;;;;;;;OAQG;IAIG,AAAN,KAAK,CAAC,WAAW,CACR,OAA6B,EACpB,KAAa,EACrB,IAA+B;QAEvC,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5F,CAAC;CACF,CAAA;AAzBY,gEAA0B;AAkB/B;IAHL,IAAA,aAAI,EAAC,GAAG,iCAAc,CAAC,QAAQ,IAAI,kDAA+B,SAAS,CAAC;IAC5E,IAAA,iBAAQ,EAAC,mBAAU,CAAC,UAAU,CAAC;IAC/B,IAAA,4CAAe,EAAC,iCAAc,CAAC;IAE7B,WAAA,IAAA,YAAG,GAAE,CAAA;IACL,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;IACd,WAAA,IAAA,aAAI,GAAE,CAAA;;qDAAQ,sDAAwB;;6DAGxC;qCAxBU,0BAA0B;IADtC,IAAA,mBAAU,GAAE;qCAGyB,wDAAyB;QAC5B,4BAAY;GAHlC,0BAA0B,CAyBtC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ClsService } from "nestjs-cls";
|
|
2
|
+
import { AppLoggingService } from "../../../core/logging/services/logging.service";
|
|
3
|
+
import { EmailBlastDeliveryService } from "../services/email-blast-delivery.service";
|
|
4
|
+
/**
|
|
5
|
+
* Every 10 minutes, worker only: fails the deliveries a dead worker left in `sending`
|
|
6
|
+
* (never resent) and queues the send job again for every blast still `sending`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class EmailBlastRecoveryCron {
|
|
9
|
+
private readonly deliveryService;
|
|
10
|
+
private readonly clsService;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
constructor(deliveryService: EmailBlastDeliveryService, clsService: ClsService, logger: AppLoggingService);
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=email-blast-recovery.cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast-recovery.cron.d.ts","sourceRoot":"","sources":["../../../../src/foundations/email-blast/cron/email-blast-recovery.cron.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AACnF,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AAErF;;;GAGG;AACH,qBACa,sBAAsB;IAE/B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,eAAe,EAAE,yBAAyB,EAC1C,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,iBAAiB;IAItC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAO3B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmailBlastRecoveryCron = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const schedule_1 = require("@nestjs/schedule");
|
|
15
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
16
|
+
const logging_service_1 = require("../../../core/logging/services/logging.service");
|
|
17
|
+
const email_blast_delivery_service_1 = require("../services/email-blast-delivery.service");
|
|
18
|
+
/**
|
|
19
|
+
* Every 10 minutes, worker only: fails the deliveries a dead worker left in `sending`
|
|
20
|
+
* (never resent) and queues the send job again for every blast still `sending`.
|
|
21
|
+
*/
|
|
22
|
+
let EmailBlastRecoveryCron = class EmailBlastRecoveryCron {
|
|
23
|
+
constructor(deliveryService, clsService, logger) {
|
|
24
|
+
this.deliveryService = deliveryService;
|
|
25
|
+
this.clsService = clsService;
|
|
26
|
+
this.logger = logger;
|
|
27
|
+
}
|
|
28
|
+
async run() {
|
|
29
|
+
try {
|
|
30
|
+
await this.clsService.run(() => this.deliveryService.recoverStuck({ now: new Date() }));
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
this.logger.error(`Failed to recover email blasts: ${error.message}`, "EmailBlastRecoveryCron");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.EmailBlastRecoveryCron = EmailBlastRecoveryCron;
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_10_MINUTES),
|
|
40
|
+
__metadata("design:type", Function),
|
|
41
|
+
__metadata("design:paramtypes", []),
|
|
42
|
+
__metadata("design:returntype", Promise)
|
|
43
|
+
], EmailBlastRecoveryCron.prototype, "run", null);
|
|
44
|
+
exports.EmailBlastRecoveryCron = EmailBlastRecoveryCron = __decorate([
|
|
45
|
+
(0, common_1.Injectable)(),
|
|
46
|
+
__metadata("design:paramtypes", [email_blast_delivery_service_1.EmailBlastDeliveryService,
|
|
47
|
+
nestjs_cls_1.ClsService,
|
|
48
|
+
logging_service_1.AppLoggingService])
|
|
49
|
+
], EmailBlastRecoveryCron);
|
|
50
|
+
//# sourceMappingURL=email-blast-recovery.cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast-recovery.cron.js","sourceRoot":"","sources":["../../../../src/foundations/email-blast/cron/email-blast-recovery.cron.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAAwD;AACxD,2CAAwC;AACxC,oFAAmF;AACnF,2FAAqF;AAErF;;;GAGG;AAEI,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IACjC,YACmB,eAA0C,EAC1C,UAAsB,EACtB,MAAyB;QAFzB,oBAAe,GAAf,eAAe,CAA2B;QAC1C,eAAU,GAAV,UAAU,CAAY;QACtB,WAAM,GAAN,MAAM,CAAmB;IACzC,CAAC;IAGE,AAAN,KAAK,CAAC,GAAG;QACP,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAoC,KAAe,CAAC,OAAO,EAAE,EAAE,wBAAwB,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;CACF,CAAA;AAfY,wDAAsB;AAQ3B;IADL,IAAA,eAAI,EAAC,yBAAc,CAAC,gBAAgB,CAAC;;;;iDAOrC;iCAdU,sBAAsB;IADlC,IAAA,mBAAU,GAAE;qCAGyB,wDAAyB;QAC9B,uBAAU;QACd,mCAAiB;GAJjC,sBAAsB,CAelC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast-unsubscribe.dto.d.ts","sourceRoot":"","sources":["../../../../src/foundations/email-blast/dtos/email-blast-unsubscribe.dto.ts"],"names":[],"mappings":"AAIA,qBAAa,4BAA4B;IAEvC,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,qBAAa,wBAAwB;IAInC,IAAI,CAAC,EAAE,4BAA4B,CAAC;CACrC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmailBlastUnsubscribeDTO = exports.EmailBlastUnsubscribeDataDTO = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const email_blast_meta_1 = require("../entities/email-blast.meta");
|
|
16
|
+
class EmailBlastUnsubscribeDataDTO {
|
|
17
|
+
}
|
|
18
|
+
exports.EmailBlastUnsubscribeDataDTO = EmailBlastUnsubscribeDataDTO;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, class_validator_1.Equals)(email_blast_meta_1.EMAIL_BLAST_UNSUBSCRIBE_TYPE),
|
|
21
|
+
__metadata("design:type", String)
|
|
22
|
+
], EmailBlastUnsubscribeDataDTO.prototype, "type", void 0);
|
|
23
|
+
// `data` is optional: the RFC 8058 one-click POST carries a form body
|
|
24
|
+
// (`List-Unsubscribe=One-Click`) that the global whitelist strips to `{}`,
|
|
25
|
+
// so `data` is absent on that path. The unsubscribe page sends `data`.
|
|
26
|
+
class EmailBlastUnsubscribeDTO {
|
|
27
|
+
}
|
|
28
|
+
exports.EmailBlastUnsubscribeDTO = EmailBlastUnsubscribeDTO;
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, class_validator_1.IsOptional)(),
|
|
31
|
+
(0, class_validator_1.ValidateNested)(),
|
|
32
|
+
(0, class_transformer_1.Type)(() => EmailBlastUnsubscribeDataDTO),
|
|
33
|
+
__metadata("design:type", EmailBlastUnsubscribeDataDTO)
|
|
34
|
+
], EmailBlastUnsubscribeDTO.prototype, "data", void 0);
|
|
35
|
+
//# sourceMappingURL=email-blast-unsubscribe.dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast-unsubscribe.dto.js","sourceRoot":"","sources":["../../../../src/foundations/email-blast/dtos/email-blast-unsubscribe.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yDAAyC;AACzC,qDAAqE;AACrE,mEAA4E;AAE5E,MAAa,4BAA4B;CAGxC;AAHD,oEAGC;AADC;IADC,IAAA,wBAAM,EAAC,+CAA4B,CAAC;;0DACxB;AAGf,sEAAsE;AACtE,2EAA2E;AAC3E,uEAAuE;AACvE,MAAa,wBAAwB;CAKpC;AALD,4DAKC;AADC;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,gCAAc,GAAE;IAChB,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC;8BAClC,4BAA4B;sDAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class EmailBlastPatchAttributesDTO {
|
|
2
|
+
subject?: string;
|
|
3
|
+
body?: string;
|
|
4
|
+
replyTo?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class EmailBlastPatchDataDTO {
|
|
7
|
+
type: string;
|
|
8
|
+
id: string;
|
|
9
|
+
attributes: EmailBlastPatchAttributesDTO;
|
|
10
|
+
}
|
|
11
|
+
export declare class EmailBlastPatchDTO {
|
|
12
|
+
data: EmailBlastPatchDataDTO;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=email-blast.patch.dto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.patch.dto.d.ts","sourceRoot":"","sources":["../../../../src/foundations/email-blast/dtos/email-blast.patch.dto.ts"],"names":[],"mappings":"AAKA,qBAAa,4BAA4B;IAIvC,OAAO,CAAC,EAAE,MAAM,CAAC;IAKjB,IAAI,CAAC,EAAE,MAAM,CAAC;IAId,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,sBAAsB;IAEjC,IAAI,EAAE,MAAM,CAAC;IAGb,EAAE,EAAE,MAAM,CAAC;IAKX,UAAU,EAAE,4BAA4B,CAAC;CAC1C;AAED,qBAAa,kBAAkB;IAI7B,IAAI,EAAE,sBAAsB,CAAC;CAC9B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmailBlastPatchDTO = exports.EmailBlastPatchDataDTO = exports.EmailBlastPatchAttributesDTO = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const email_blast_meta_1 = require("../entities/email-blast.meta");
|
|
16
|
+
// No status, counters or dates are accepted: the global whitelist strips them.
|
|
17
|
+
class EmailBlastPatchAttributesDTO {
|
|
18
|
+
}
|
|
19
|
+
exports.EmailBlastPatchAttributesDTO = EmailBlastPatchAttributesDTO;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, class_validator_1.IsOptional)(),
|
|
22
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
23
|
+
(0, class_validator_1.IsString)(),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], EmailBlastPatchAttributesDTO.prototype, "subject", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, class_validator_1.IsOptional)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
(0, class_validator_1.IsString)(),
|
|
30
|
+
__metadata("design:type", String)
|
|
31
|
+
], EmailBlastPatchAttributesDTO.prototype, "body", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, class_validator_1.IsEmail)(),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], EmailBlastPatchAttributesDTO.prototype, "replyTo", void 0);
|
|
37
|
+
class EmailBlastPatchDataDTO {
|
|
38
|
+
}
|
|
39
|
+
exports.EmailBlastPatchDataDTO = EmailBlastPatchDataDTO;
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, class_validator_1.Equals)(email_blast_meta_1.emailBlastMeta.endpoint),
|
|
42
|
+
__metadata("design:type", String)
|
|
43
|
+
], EmailBlastPatchDataDTO.prototype, "type", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, class_validator_1.IsUUID)(),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], EmailBlastPatchDataDTO.prototype, "id", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, class_validator_1.ValidateNested)(),
|
|
50
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
51
|
+
(0, class_transformer_1.Type)(() => EmailBlastPatchAttributesDTO),
|
|
52
|
+
__metadata("design:type", EmailBlastPatchAttributesDTO)
|
|
53
|
+
], EmailBlastPatchDataDTO.prototype, "attributes", void 0);
|
|
54
|
+
class EmailBlastPatchDTO {
|
|
55
|
+
}
|
|
56
|
+
exports.EmailBlastPatchDTO = EmailBlastPatchDTO;
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, class_validator_1.ValidateNested)(),
|
|
59
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
60
|
+
(0, class_transformer_1.Type)(() => EmailBlastPatchDataDTO),
|
|
61
|
+
__metadata("design:type", EmailBlastPatchDataDTO)
|
|
62
|
+
], EmailBlastPatchDTO.prototype, "data", void 0);
|
|
63
|
+
//# sourceMappingURL=email-blast.patch.dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.patch.dto.js","sourceRoot":"","sources":["../../../../src/foundations/email-blast/dtos/email-blast.patch.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yDAAyC;AACzC,qDAA4G;AAC5G,mEAA8D;AAE9D,+EAA+E;AAC/E,MAAa,4BAA4B;CAcxC;AAdD,oEAcC;AAVC;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;6DACM;AAKjB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;0DACG;AAId;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,yBAAO,GAAE;;6DACO;AAGnB,MAAa,sBAAsB;CAWlC;AAXD,wDAWC;AATC;IADC,IAAA,wBAAM,EAAC,iCAAc,CAAC,QAAQ,CAAC;;oDACnB;AAGb;IADC,IAAA,wBAAM,GAAE;;kDACE;AAKX;IAHC,IAAA,gCAAc,GAAE;IAChB,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC;8BAC7B,4BAA4B;0DAAC;AAG3C,MAAa,kBAAkB;CAK9B;AALD,gDAKC;AADC;IAHC,IAAA,gCAAc,GAAE;IAChB,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC;8BAC7B,sBAAsB;gDAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare class EmailBlastPostAttributesDTO {
|
|
2
|
+
subject: string;
|
|
3
|
+
body: string;
|
|
4
|
+
replyTo?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class EmailBlastPostDataDTO {
|
|
7
|
+
type: string;
|
|
8
|
+
id: string;
|
|
9
|
+
attributes: EmailBlastPostAttributesDTO;
|
|
10
|
+
}
|
|
11
|
+
export declare class EmailBlastPostDTO {
|
|
12
|
+
data: EmailBlastPostDataDTO;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=email-blast.post.dto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.post.dto.d.ts","sourceRoot":"","sources":["../../../../src/foundations/email-blast/dtos/email-blast.post.dto.ts"],"names":[],"mappings":"AAKA,qBAAa,2BAA2B;IAItC,OAAO,EAAE,MAAM,CAAC;IAKhB,IAAI,EAAE,MAAM,CAAC;IAIb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,qBAAqB;IAEhC,IAAI,EAAE,MAAM,CAAC;IAGb,EAAE,EAAE,MAAM,CAAC;IAKX,UAAU,EAAE,2BAA2B,CAAC;CACzC;AAED,qBAAa,iBAAiB;IAI5B,IAAI,EAAE,qBAAqB,CAAC;CAC7B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmailBlastPostDTO = exports.EmailBlastPostDataDTO = exports.EmailBlastPostAttributesDTO = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const email_blast_meta_1 = require("../entities/email-blast.meta");
|
|
16
|
+
// No status, counters or dates are accepted: the global whitelist strips them.
|
|
17
|
+
class EmailBlastPostAttributesDTO {
|
|
18
|
+
}
|
|
19
|
+
exports.EmailBlastPostAttributesDTO = EmailBlastPostAttributesDTO;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, class_validator_1.IsDefined)(),
|
|
22
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
23
|
+
(0, class_validator_1.IsString)(),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], EmailBlastPostAttributesDTO.prototype, "subject", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, class_validator_1.IsDefined)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
(0, class_validator_1.IsString)(),
|
|
30
|
+
__metadata("design:type", String)
|
|
31
|
+
], EmailBlastPostAttributesDTO.prototype, "body", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, class_validator_1.IsEmail)(),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], EmailBlastPostAttributesDTO.prototype, "replyTo", void 0);
|
|
37
|
+
class EmailBlastPostDataDTO {
|
|
38
|
+
}
|
|
39
|
+
exports.EmailBlastPostDataDTO = EmailBlastPostDataDTO;
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, class_validator_1.Equals)(email_blast_meta_1.emailBlastMeta.endpoint),
|
|
42
|
+
__metadata("design:type", String)
|
|
43
|
+
], EmailBlastPostDataDTO.prototype, "type", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, class_validator_1.IsUUID)(),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], EmailBlastPostDataDTO.prototype, "id", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, class_validator_1.ValidateNested)(),
|
|
50
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
51
|
+
(0, class_transformer_1.Type)(() => EmailBlastPostAttributesDTO),
|
|
52
|
+
__metadata("design:type", EmailBlastPostAttributesDTO)
|
|
53
|
+
], EmailBlastPostDataDTO.prototype, "attributes", void 0);
|
|
54
|
+
class EmailBlastPostDTO {
|
|
55
|
+
}
|
|
56
|
+
exports.EmailBlastPostDTO = EmailBlastPostDTO;
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, class_validator_1.ValidateNested)(),
|
|
59
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
60
|
+
(0, class_transformer_1.Type)(() => EmailBlastPostDataDTO),
|
|
61
|
+
__metadata("design:type", EmailBlastPostDataDTO)
|
|
62
|
+
], EmailBlastPostDTO.prototype, "data", void 0);
|
|
63
|
+
//# sourceMappingURL=email-blast.post.dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.post.dto.js","sourceRoot":"","sources":["../../../../src/foundations/email-blast/dtos/email-blast.post.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yDAAyC;AACzC,qDAAuH;AACvH,mEAA8D;AAE9D,+EAA+E;AAC/E,MAAa,2BAA2B;CAcvC;AAdD,kEAcC;AAVC;IAHC,IAAA,2BAAS,GAAE;IACX,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;4DACK;AAKhB;IAHC,IAAA,2BAAS,GAAE;IACX,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;yDACE;AAIb;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,yBAAO,GAAE;;4DACO;AAGnB,MAAa,qBAAqB;CAWjC;AAXD,sDAWC;AATC;IADC,IAAA,wBAAM,EAAC,iCAAc,CAAC,QAAQ,CAAC;;mDACnB;AAGb;IADC,IAAA,wBAAM,GAAE;;iDACE;AAKX;IAHC,IAAA,gCAAc,GAAE;IAChB,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,2BAA2B,CAAC;8BAC5B,2BAA2B;yDAAC;AAG1C,MAAa,iBAAiB;CAK7B;AALD,8CAKC;AADC;IAHC,IAAA,gCAAc,GAAE;IAChB,IAAA,4BAAU,GAAE;IACZ,IAAA,wBAAI,EAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC;8BAC5B,qBAAqB;+CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { JobsOptions } from "bullmq";
|
|
2
|
+
/** Job names on `QueueId.EMAIL_BLAST`. */
|
|
3
|
+
export declare const EMAIL_BLAST_JOB_NAMES: {
|
|
4
|
+
/** Snapshot the recipients of one blast and send it (data `EmailBlastJobData`). */
|
|
5
|
+
readonly sendBlast: "send-blast";
|
|
6
|
+
};
|
|
7
|
+
export type EmailBlastJobData = {
|
|
8
|
+
blastId: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Options of the `send-blast` job. One attempt: a job retry must never re-run a send; the
|
|
12
|
+
* recovery cron re-enqueues instead, and `removeOnFail` frees the jobId so it can (BullMQ
|
|
13
|
+
* ignores `add` while a job with that id exists in any state).
|
|
14
|
+
*/
|
|
15
|
+
export declare const EMAIL_BLAST_JOB_OPTIONS: JobsOptions;
|
|
16
|
+
/** The jobId of a blast's send job. Never contains a colon (BullMQ rejects it). */
|
|
17
|
+
export declare function emailBlastJobId(blastId: string): string;
|
|
18
|
+
/** Deliveries claimed and sent per batch. */
|
|
19
|
+
export declare const EMAIL_BLAST_BATCH_SIZE = 50;
|
|
20
|
+
/**
|
|
21
|
+
* Minutes after which a delivery still in `sending` is failed (never resent). Well above the
|
|
22
|
+
* time one batch can take, so a live batch is never marked stuck.
|
|
23
|
+
*/
|
|
24
|
+
export declare const EMAIL_BLAST_STUCK_MINUTES = 60;
|
|
25
|
+
/** Unsubscribe token of a test send: it matches no delivery. */
|
|
26
|
+
export declare const EMAIL_BLAST_TEST_TOKEN = "test";
|
|
27
|
+
/** Subject prefix of a test send. */
|
|
28
|
+
export declare const EMAIL_BLAST_TEST_SUBJECT_PREFIX = "[TEST] ";
|
|
29
|
+
/**
|
|
30
|
+
* The one eligibility block both the admin recipient count and the snapshot use. Binds
|
|
31
|
+
* `email` (lower-cased) and `recipient` (one User per email).
|
|
32
|
+
*/
|
|
33
|
+
export declare const ELIGIBLE_RECIPIENTS_CYPHER = "\n MATCH (candidate:User)\n WHERE candidate.marketingConsent = true\n AND candidate.isActive = true\n AND coalesce(candidate.isDeleted, false) = false\n AND candidate.deletionScheduledAt IS NULL\n AND candidate.email IS NOT NULL AND trim(candidate.email) <> \"\"\n AND NOT EXISTS { MATCH (optOut:EmailOptOut) WHERE toLower(optOut.email) = toLower(candidate.email) }\n WITH toLower(candidate.email) AS email, collect(candidate)[0] AS recipient\n";
|
|
34
|
+
//# sourceMappingURL=email-blast.constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.constants.d.ts","sourceRoot":"","sources":["../../../src/foundations/email-blast/email-blast.constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB;IAChC,mFAAmF;;CAE3E,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAIrC,CAAC;AAEF,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAE7C,qCAAqC;AACrC,eAAO,MAAM,+BAA+B,YAAY,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,meAStC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ELIGIBLE_RECIPIENTS_CYPHER = exports.EMAIL_BLAST_TEST_SUBJECT_PREFIX = exports.EMAIL_BLAST_TEST_TOKEN = exports.EMAIL_BLAST_STUCK_MINUTES = exports.EMAIL_BLAST_BATCH_SIZE = exports.EMAIL_BLAST_JOB_OPTIONS = exports.EMAIL_BLAST_JOB_NAMES = void 0;
|
|
4
|
+
exports.emailBlastJobId = emailBlastJobId;
|
|
5
|
+
/** Job names on `QueueId.EMAIL_BLAST`. */
|
|
6
|
+
exports.EMAIL_BLAST_JOB_NAMES = {
|
|
7
|
+
/** Snapshot the recipients of one blast and send it (data `EmailBlastJobData`). */
|
|
8
|
+
sendBlast: "send-blast",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Options of the `send-blast` job. One attempt: a job retry must never re-run a send; the
|
|
12
|
+
* recovery cron re-enqueues instead, and `removeOnFail` frees the jobId so it can (BullMQ
|
|
13
|
+
* ignores `add` while a job with that id exists in any state).
|
|
14
|
+
*/
|
|
15
|
+
exports.EMAIL_BLAST_JOB_OPTIONS = {
|
|
16
|
+
attempts: 1,
|
|
17
|
+
removeOnComplete: true,
|
|
18
|
+
removeOnFail: true,
|
|
19
|
+
};
|
|
20
|
+
/** The jobId of a blast's send job. Never contains a colon (BullMQ rejects it). */
|
|
21
|
+
function emailBlastJobId(blastId) {
|
|
22
|
+
return `email-blast-${blastId}`;
|
|
23
|
+
}
|
|
24
|
+
/** Deliveries claimed and sent per batch. */
|
|
25
|
+
exports.EMAIL_BLAST_BATCH_SIZE = 50;
|
|
26
|
+
/**
|
|
27
|
+
* Minutes after which a delivery still in `sending` is failed (never resent). Well above the
|
|
28
|
+
* time one batch can take, so a live batch is never marked stuck.
|
|
29
|
+
*/
|
|
30
|
+
exports.EMAIL_BLAST_STUCK_MINUTES = 60;
|
|
31
|
+
/** Unsubscribe token of a test send: it matches no delivery. */
|
|
32
|
+
exports.EMAIL_BLAST_TEST_TOKEN = "test";
|
|
33
|
+
/** Subject prefix of a test send. */
|
|
34
|
+
exports.EMAIL_BLAST_TEST_SUBJECT_PREFIX = "[TEST] ";
|
|
35
|
+
/**
|
|
36
|
+
* The one eligibility block both the admin recipient count and the snapshot use. Binds
|
|
37
|
+
* `email` (lower-cased) and `recipient` (one User per email).
|
|
38
|
+
*/
|
|
39
|
+
exports.ELIGIBLE_RECIPIENTS_CYPHER = `
|
|
40
|
+
MATCH (candidate:User)
|
|
41
|
+
WHERE candidate.marketingConsent = true
|
|
42
|
+
AND candidate.isActive = true
|
|
43
|
+
AND coalesce(candidate.isDeleted, false) = false
|
|
44
|
+
AND candidate.deletionScheduledAt IS NULL
|
|
45
|
+
AND candidate.email IS NOT NULL AND trim(candidate.email) <> ""
|
|
46
|
+
AND NOT EXISTS { MATCH (optOut:EmailOptOut) WHERE toLower(optOut.email) = toLower(candidate.email) }
|
|
47
|
+
WITH toLower(candidate.email) AS email, collect(candidate)[0] AS recipient
|
|
48
|
+
`;
|
|
49
|
+
//# sourceMappingURL=email-blast.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.constants.js","sourceRoot":"","sources":["../../../src/foundations/email-blast/email-blast.constants.ts"],"names":[],"mappings":";;;AAsBA,0CAEC;AAtBD,0CAA0C;AAC7B,QAAA,qBAAqB,GAAG;IACnC,mFAAmF;IACnF,SAAS,EAAE,YAAY;CACf,CAAC;AAIX;;;;GAIG;AACU,QAAA,uBAAuB,GAAgB;IAClD,QAAQ,EAAE,CAAC;IACX,gBAAgB,EAAE,IAAI;IACtB,YAAY,EAAE,IAAI;CACnB,CAAC;AAEF,mFAAmF;AACnF,SAAgB,eAAe,CAAC,OAAe;IAC7C,OAAO,eAAe,OAAO,EAAE,CAAC;AAClC,CAAC;AAED,6CAA6C;AAChC,QAAA,sBAAsB,GAAG,EAAE,CAAC;AAEzC;;;GAGG;AACU,QAAA,yBAAyB,GAAG,EAAE,CAAC;AAE5C,gEAAgE;AACnD,QAAA,sBAAsB,GAAG,MAAM,CAAC;AAE7C,qCAAqC;AACxB,QAAA,+BAA+B,GAAG,SAAS,CAAC;AAEzD;;;GAGG;AACU,QAAA,0BAA0B,GAAG;;;;;;;;;CASzC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DynamicModule, OnModuleInit } from "@nestjs/common";
|
|
2
|
+
/**
|
|
3
|
+
* EmailBlastModule — one-off marketing emails an administrator sends to every registered
|
|
4
|
+
* user who gave marketing consent.
|
|
5
|
+
*
|
|
6
|
+
* - Admin CRUD, recipient count, test send and Send (`EmailBlastController`, administrators only)
|
|
7
|
+
* - A public unsubscribe route (`EmailBlastPublicController`) that stops all marketing email
|
|
8
|
+
* - A worker job that snapshots the recipients and sends (`EmailBlastProcessor`)
|
|
9
|
+
* - A recovery cron that fails stuck deliveries and re-queues interrupted sends
|
|
10
|
+
* (`EmailBlastRecoveryCron`)
|
|
11
|
+
*
|
|
12
|
+
* It does not import `EmailAutomationModule`: that module is `@Module({})` with everything in
|
|
13
|
+
* `forRoot()`, so the bare class resolves nothing and a second `forRoot()` would mount the
|
|
14
|
+
* automation controllers and cron twice. The two automation repositories it needs are
|
|
15
|
+
* provided here with their serialisers.
|
|
16
|
+
*/
|
|
17
|
+
export declare class EmailBlastModule implements OnModuleInit {
|
|
18
|
+
onModuleInit(): void;
|
|
19
|
+
static forRoot(): DynamicModule;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=email-blast.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.module.d.ts","sourceRoot":"","sources":["../../../src/foundations/email-blast/email-blast.module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAU,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA6BrE;;;;;;;;;;;;;;GAcG;AACH,qBACa,gBAAiB,YAAW,YAAY;IACnD,YAAY;IAOZ,MAAM,CAAC,OAAO,IAAI,aAAa;CAkChC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var EmailBlastModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.EmailBlastModule = void 0;
|
|
11
|
+
const bullmq_1 = require("@nestjs/bullmq");
|
|
12
|
+
const common_1 = require("@nestjs/common");
|
|
13
|
+
const conditional_service_decorator_1 = require("../../common/decorators/conditional-service.decorator");
|
|
14
|
+
const registry_1 = require("../../common/registries/registry");
|
|
15
|
+
const queue_id_1 = require("../../config/enums/queue.id");
|
|
16
|
+
const cache_module_1 = require("../../core/cache/cache.module");
|
|
17
|
+
const email_module_1 = require("../../core/email/email.module");
|
|
18
|
+
const jsonapi_module_1 = require("../../core/jsonapi/jsonapi.module");
|
|
19
|
+
const security_module_1 = require("../../core/security/security.module");
|
|
20
|
+
const audit_module_1 = require("../audit/audit.module");
|
|
21
|
+
const email_automation_1 = require("../email-automation/entities/email-automation");
|
|
22
|
+
const email_automation_enrollment_1 = require("../email-automation/entities/email-automation-enrollment");
|
|
23
|
+
const email_automation_step_1 = require("../email-automation/entities/email-automation-step");
|
|
24
|
+
const email_opt_out_1 = require("../email-automation/entities/email-opt-out");
|
|
25
|
+
const email_automation_enrollment_repository_1 = require("../email-automation/repositories/email-automation-enrollment.repository");
|
|
26
|
+
const email_opt_out_repository_1 = require("../email-automation/repositories/email-opt-out.repository");
|
|
27
|
+
const user_module_1 = require("../user/user.module");
|
|
28
|
+
const email_blast_controller_1 = require("./controllers/email-blast.controller");
|
|
29
|
+
const email_blast_public_controller_1 = require("./controllers/email-blast.public.controller");
|
|
30
|
+
const email_blast_recovery_cron_1 = require("./cron/email-blast-recovery.cron");
|
|
31
|
+
const email_blast_1 = require("./entities/email-blast");
|
|
32
|
+
const email_blast_audience_1 = require("./entities/email-blast-audience");
|
|
33
|
+
const email_blast_delivery_1 = require("./entities/email-blast-delivery");
|
|
34
|
+
const email_blast_processor_1 = require("./processors/email-blast.processor");
|
|
35
|
+
const email_blast_admin_repository_1 = require("./repositories/email-blast.admin.repository");
|
|
36
|
+
const email_blast_delivery_repository_1 = require("./repositories/email-blast-delivery.repository");
|
|
37
|
+
const email_blast_repository_1 = require("./repositories/email-blast.repository");
|
|
38
|
+
const email_blast_delivery_service_1 = require("./services/email-blast-delivery.service");
|
|
39
|
+
const email_blast_service_1 = require("./services/email-blast.service");
|
|
40
|
+
/**
|
|
41
|
+
* EmailBlastModule — one-off marketing emails an administrator sends to every registered
|
|
42
|
+
* user who gave marketing consent.
|
|
43
|
+
*
|
|
44
|
+
* - Admin CRUD, recipient count, test send and Send (`EmailBlastController`, administrators only)
|
|
45
|
+
* - A public unsubscribe route (`EmailBlastPublicController`) that stops all marketing email
|
|
46
|
+
* - A worker job that snapshots the recipients and sends (`EmailBlastProcessor`)
|
|
47
|
+
* - A recovery cron that fails stuck deliveries and re-queues interrupted sends
|
|
48
|
+
* (`EmailBlastRecoveryCron`)
|
|
49
|
+
*
|
|
50
|
+
* It does not import `EmailAutomationModule`: that module is `@Module({})` with everything in
|
|
51
|
+
* `forRoot()`, so the bare class resolves nothing and a second `forRoot()` would mount the
|
|
52
|
+
* automation controllers and cron twice. The two automation repositories it needs are
|
|
53
|
+
* provided here with their serialisers.
|
|
54
|
+
*/
|
|
55
|
+
let EmailBlastModule = EmailBlastModule_1 = class EmailBlastModule {
|
|
56
|
+
onModuleInit() {
|
|
57
|
+
registry_1.modelRegistry.register(email_blast_1.EmailBlastDescriptor.model);
|
|
58
|
+
registry_1.modelRegistry.register(email_blast_delivery_1.EmailBlastDeliveryDescriptor.model);
|
|
59
|
+
// Synthetic resource (never a node): buildSingle needs it in the registry
|
|
60
|
+
registry_1.modelRegistry.register(email_blast_audience_1.EmailBlastAudienceDescriptor.model);
|
|
61
|
+
}
|
|
62
|
+
static forRoot() {
|
|
63
|
+
return {
|
|
64
|
+
module: EmailBlastModule_1,
|
|
65
|
+
imports: [
|
|
66
|
+
security_module_1.SecurityModule,
|
|
67
|
+
jsonapi_module_1.JsonApiModule,
|
|
68
|
+
email_module_1.EmailModule,
|
|
69
|
+
user_module_1.UserModule,
|
|
70
|
+
cache_module_1.CacheModule,
|
|
71
|
+
audit_module_1.AuditModule,
|
|
72
|
+
bullmq_1.BullModule.registerQueue({ name: queue_id_1.QueueId.EMAIL_BLAST }),
|
|
73
|
+
],
|
|
74
|
+
controllers: [email_blast_controller_1.EmailBlastController, email_blast_public_controller_1.EmailBlastPublicController],
|
|
75
|
+
providers: [
|
|
76
|
+
email_blast_1.EmailBlastDescriptor.model.serialiser,
|
|
77
|
+
email_blast_delivery_1.EmailBlastDeliveryDescriptor.model.serialiser,
|
|
78
|
+
email_blast_audience_1.EmailBlastAudienceDescriptor.model.serialiser,
|
|
79
|
+
email_opt_out_1.EmailOptOutDescriptor.model.serialiser,
|
|
80
|
+
email_automation_enrollment_1.EmailAutomationEnrollmentDescriptor.model.serialiser,
|
|
81
|
+
email_automation_1.EmailAutomationDescriptor.model.serialiser,
|
|
82
|
+
email_automation_step_1.EmailAutomationStepDescriptor.model.serialiser,
|
|
83
|
+
email_blast_repository_1.EmailBlastRepository,
|
|
84
|
+
email_blast_delivery_repository_1.EmailBlastDeliveryRepository,
|
|
85
|
+
email_blast_admin_repository_1.EmailBlastAdminRepository,
|
|
86
|
+
email_opt_out_repository_1.EmailOptOutRepository,
|
|
87
|
+
email_automation_enrollment_repository_1.EmailAutomationEnrollmentRepository,
|
|
88
|
+
email_blast_service_1.EmailBlastService,
|
|
89
|
+
email_blast_delivery_service_1.EmailBlastDeliveryService,
|
|
90
|
+
(0, conditional_service_decorator_1.createWorkerProvider)(email_blast_processor_1.EmailBlastProcessor),
|
|
91
|
+
(0, conditional_service_decorator_1.createWorkerProvider)(email_blast_recovery_cron_1.EmailBlastRecoveryCron),
|
|
92
|
+
],
|
|
93
|
+
exports: [email_blast_service_1.EmailBlastService, email_blast_delivery_service_1.EmailBlastDeliveryService, email_blast_repository_1.EmailBlastRepository, email_blast_delivery_repository_1.EmailBlastDeliveryRepository],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
exports.EmailBlastModule = EmailBlastModule;
|
|
98
|
+
exports.EmailBlastModule = EmailBlastModule = EmailBlastModule_1 = __decorate([
|
|
99
|
+
(0, common_1.Module)({})
|
|
100
|
+
], EmailBlastModule);
|
|
101
|
+
//# sourceMappingURL=email-blast.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast.module.js","sourceRoot":"","sources":["../../../src/foundations/email-blast/email-blast.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAA4C;AAC5C,2CAAqE;AACrE,yGAA6F;AAC7F,+DAAiE;AACjE,0DAAsD;AACtD,gEAA4D;AAC5D,gEAA4D;AAC5D,sEAAkE;AAClE,yEAAqE;AACrE,wDAAoD;AACpD,oFAA0F;AAC1F,0GAA+G;AAC/G,8FAAmG;AACnG,8EAAmF;AACnF,oIAA8H;AAC9H,wGAAkG;AAClG,qDAAiD;AACjD,iFAA4E;AAC5E,+FAAyF;AACzF,gFAA0E;AAC1E,wDAA8D;AAC9D,0EAA+E;AAC/E,0EAA+E;AAC/E,8EAAyE;AACzE,8FAAwF;AACxF,oGAA8F;AAC9F,kFAA6E;AAC7E,0FAAoF;AACpF,wEAAmE;AAEnE;;;;;;;;;;;;;;GAcG;AAEI,IAAM,gBAAgB,wBAAtB,MAAM,gBAAgB;IAC3B,YAAY;QACV,wBAAa,CAAC,QAAQ,CAAC,kCAAoB,CAAC,KAAK,CAAC,CAAC;QACnD,wBAAa,CAAC,QAAQ,CAAC,mDAA4B,CAAC,KAAK,CAAC,CAAC;QAC3D,0EAA0E;QAC1E,wBAAa,CAAC,QAAQ,CAAC,mDAA4B,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,MAAM,EAAE,kBAAgB;YACxB,OAAO,EAAE;gBACP,gCAAc;gBACd,8BAAa;gBACb,0BAAW;gBACX,wBAAU;gBACV,0BAAW;gBACX,0BAAW;gBACX,mBAAU,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,kBAAO,CAAC,WAAW,EAAE,CAAC;aACxD;YACD,WAAW,EAAE,CAAC,6CAAoB,EAAE,0DAA0B,CAAC;YAC/D,SAAS,EAAE;gBACT,kCAAoB,CAAC,KAAK,CAAC,UAAU;gBACrC,mDAA4B,CAAC,KAAK,CAAC,UAAU;gBAC7C,mDAA4B,CAAC,KAAK,CAAC,UAAU;gBAC7C,qCAAqB,CAAC,KAAK,CAAC,UAAU;gBACtC,iEAAmC,CAAC,KAAK,CAAC,UAAU;gBACpD,4CAAyB,CAAC,KAAK,CAAC,UAAU;gBAC1C,qDAA6B,CAAC,KAAK,CAAC,UAAU;gBAC9C,6CAAoB;gBACpB,8DAA4B;gBAC5B,wDAAyB;gBACzB,gDAAqB;gBACrB,4EAAmC;gBACnC,uCAAiB;gBACjB,wDAAyB;gBACzB,IAAA,oDAAoB,EAAC,2CAAmB,CAAC;gBACzC,IAAA,oDAAoB,EAAC,kDAAsB,CAAC;aAC7C;YACD,OAAO,EAAE,CAAC,uCAAiB,EAAE,wDAAyB,EAAE,6CAAoB,EAAE,8DAA4B,CAAC;SAC5G,CAAC;IACJ,CAAC;CACF,CAAA;AA1CY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,gBAAgB,CA0C5B"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Entity } from "../../../common";
|
|
2
|
+
/**
|
|
3
|
+
* Synthetic resource (`id` = the blast id): how many people the blast would reach. Never a node.
|
|
4
|
+
*/
|
|
5
|
+
export type EmailBlastAudience = Entity & {
|
|
6
|
+
recipientCount: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const EmailBlastAudienceDescriptor: import("../../../common").EntityDescriptor<EmailBlastAudience, {}>;
|
|
9
|
+
export type EmailBlastAudienceDescriptorType = typeof EmailBlastAudienceDescriptor;
|
|
10
|
+
//# sourceMappingURL=email-blast-audience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-blast-audience.d.ts","sourceRoot":"","sources":["../../../../src/foundations/email-blast/entities/email-blast-audience.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AAGvD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG;IACxC,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,4BAA4B,oEAQvC,CAAC;AAEH,MAAM,MAAM,gCAAgC,GAAG,OAAO,4BAA4B,CAAC"}
|