@deenruv/email-plugin 1.0.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/LICENSE +23 -0
- package/README.md +85 -0
- package/dev-mailbox.html +218 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +30 -0
- package/lib/index.js.map +1 -0
- package/lib/src/attachment-utils.d.ts +3 -0
- package/lib/src/attachment-utils.js +66 -0
- package/lib/src/attachment-utils.js.map +1 -0
- package/lib/src/common.d.ts +4 -0
- package/lib/src/common.js +17 -0
- package/lib/src/common.js.map +1 -0
- package/lib/src/constants.d.ts +2 -0
- package/lib/src/constants.js +6 -0
- package/lib/src/constants.js.map +1 -0
- package/lib/src/dev-mailbox.d.ts +14 -0
- package/lib/src/dev-mailbox.js +116 -0
- package/lib/src/dev-mailbox.js.map +1 -0
- package/lib/src/email-processor.d.ts +21 -0
- package/lib/src/email-processor.js +109 -0
- package/lib/src/email-processor.js.map +1 -0
- package/lib/src/email-send-event.d.ts +18 -0
- package/lib/src/email-send-event.js +24 -0
- package/lib/src/email-send-event.js.map +1 -0
- package/lib/src/event-listener.d.ts +19 -0
- package/lib/src/event-listener.js +25 -0
- package/lib/src/event-listener.js.map +1 -0
- package/lib/src/generator/email-generator.d.ts +25 -0
- package/lib/src/generator/email-generator.js +3 -0
- package/lib/src/generator/email-generator.js.map +1 -0
- package/lib/src/generator/handlebars-mjml-generator.d.ts +19 -0
- package/lib/src/generator/handlebars-mjml-generator.js +78 -0
- package/lib/src/generator/handlebars-mjml-generator.js.map +1 -0
- package/lib/src/generator/noop-email-generator.d.ts +11 -0
- package/lib/src/generator/noop-email-generator.js +13 -0
- package/lib/src/generator/noop-email-generator.js.map +1 -0
- package/lib/src/generator/react-email-generator.d.ts +7 -0
- package/lib/src/generator/react-email-generator.js +40 -0
- package/lib/src/generator/react-email-generator.js.map +1 -0
- package/lib/src/handler/default-email-handlers.d.ts +32 -0
- package/lib/src/handler/default-email-handlers.js +111 -0
- package/lib/src/handler/default-email-handlers.js.map +1 -0
- package/lib/src/handler/event-handler.d.ts +276 -0
- package/lib/src/handler/event-handler.js +396 -0
- package/lib/src/handler/event-handler.js.map +1 -0
- package/lib/src/handler/mock-events.d.ts +5 -0
- package/lib/src/handler/mock-events.js +119 -0
- package/lib/src/handler/mock-events.js.map +1 -0
- package/lib/src/plugin.d.ts +301 -0
- package/lib/src/plugin.js +428 -0
- package/lib/src/plugin.js.map +1 -0
- package/lib/src/sender/email-sender.d.ts +45 -0
- package/lib/src/sender/email-sender.js +3 -0
- package/lib/src/sender/email-sender.js.map +1 -0
- package/lib/src/sender/nodemailer-email-sender.d.ts +37 -0
- package/lib/src/sender/nodemailer-email-sender.js +151 -0
- package/lib/src/sender/nodemailer-email-sender.js.map +1 -0
- package/lib/src/template-loader/file-based-template-loader.d.ts +17 -0
- package/lib/src/template-loader/file-based-template-loader.js +37 -0
- package/lib/src/template-loader/file-based-template-loader.js.map +1 -0
- package/lib/src/template-loader/react-email-template-loader.d.ts +6 -0
- package/lib/src/template-loader/react-email-template-loader.js +14 -0
- package/lib/src/template-loader/react-email-template-loader.js.map +1 -0
- package/lib/src/template-loader/template-loader.d.ts +42 -0
- package/lib/src/template-loader/template-loader.js +3 -0
- package/lib/src/template-loader/template-loader.js.map +1 -0
- package/lib/src/types.d.ts +453 -0
- package/lib/src/types.js +3 -0
- package/lib/src/types.js.map +1 -0
- package/package.json +51 -0
- package/templates/email-address-change/body.hbs +20 -0
- package/templates/email-verification/body.hbs +20 -0
- package/templates/order-confirmation/body.hbs +133 -0
- package/templates/partials/footer.hbs +10 -0
- package/templates/partials/header.hbs +18 -0
- package/templates/password-reset/body.hbs +24 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ModuleRef } from "@nestjs/core";
|
|
2
|
+
import { EventBus, RequestContext } from "@deenruv/core";
|
|
3
|
+
import { EmailGenerator } from "./generator/email-generator";
|
|
4
|
+
import { EmailSender } from "./sender/email-sender";
|
|
5
|
+
import { EmailTransportOptions, InitializedEmailPluginOptions, IntermediateEmailDetails } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* This class combines the template loading, generation, and email sending - the actual "work" of
|
|
8
|
+
* the EmailPlugin. It is arranged this way primarily to accommodate easier testing, so that the
|
|
9
|
+
* tests can be run without needing all the JobQueue stuff which would require a full e2e test.
|
|
10
|
+
*/
|
|
11
|
+
export declare class EmailProcessor {
|
|
12
|
+
protected options: InitializedEmailPluginOptions;
|
|
13
|
+
private moduleRef;
|
|
14
|
+
private eventBus;
|
|
15
|
+
protected emailSender: EmailSender;
|
|
16
|
+
protected generator: EmailGenerator;
|
|
17
|
+
constructor(options: InitializedEmailPluginOptions, moduleRef: ModuleRef, eventBus: EventBus);
|
|
18
|
+
init(): Promise<void>;
|
|
19
|
+
process(data: IntermediateEmailDetails): Promise<boolean>;
|
|
20
|
+
getTransportSettings(ctx?: RequestContext): Promise<EmailTransportOptions>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.EmailProcessor = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const core_1 = require("@nestjs/core");
|
|
21
|
+
const core_2 = require("@deenruv/core");
|
|
22
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
23
|
+
const attachment_utils_1 = require("./attachment-utils");
|
|
24
|
+
const common_2 = require("./common");
|
|
25
|
+
const constants_1 = require("./constants");
|
|
26
|
+
const email_send_event_1 = require("./email-send-event");
|
|
27
|
+
const handlebars_mjml_generator_1 = require("./generator/handlebars-mjml-generator");
|
|
28
|
+
const nodemailer_email_sender_1 = require("./sender/nodemailer-email-sender");
|
|
29
|
+
/**
|
|
30
|
+
* This class combines the template loading, generation, and email sending - the actual "work" of
|
|
31
|
+
* the EmailPlugin. It is arranged this way primarily to accommodate easier testing, so that the
|
|
32
|
+
* tests can be run without needing all the JobQueue stuff which would require a full e2e test.
|
|
33
|
+
*/
|
|
34
|
+
let EmailProcessor = class EmailProcessor {
|
|
35
|
+
constructor(options, moduleRef, eventBus) {
|
|
36
|
+
this.options = options;
|
|
37
|
+
this.moduleRef = moduleRef;
|
|
38
|
+
this.eventBus = eventBus;
|
|
39
|
+
}
|
|
40
|
+
async init() {
|
|
41
|
+
this.emailSender = this.options.emailSender
|
|
42
|
+
? this.options.emailSender
|
|
43
|
+
: new nodemailer_email_sender_1.NodemailerEmailSender();
|
|
44
|
+
this.generator = this.options.emailGenerator
|
|
45
|
+
? this.options.emailGenerator
|
|
46
|
+
: new handlebars_mjml_generator_1.HandlebarsMjmlGenerator();
|
|
47
|
+
if (this.generator.onInit) {
|
|
48
|
+
await this.generator.onInit.call(this.generator, this.options);
|
|
49
|
+
}
|
|
50
|
+
const transport = await this.getTransportSettings();
|
|
51
|
+
if (transport.type === "file") {
|
|
52
|
+
// ensure the configured directory exists before
|
|
53
|
+
// we attempt to write files to it
|
|
54
|
+
const emailPath = transport.outputPath;
|
|
55
|
+
await fs_extra_1.default.ensureDir(emailPath);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async process(data) {
|
|
59
|
+
const ctx = core_2.RequestContext.deserialize(data.ctx);
|
|
60
|
+
let emailDetails = {};
|
|
61
|
+
try {
|
|
62
|
+
const bodySource = await this.options.templateLoader.loadTemplate(new core_2.Injector(this.moduleRef), ctx, {
|
|
63
|
+
templateName: data.templateFile,
|
|
64
|
+
type: data.type,
|
|
65
|
+
templateVars: data.templateVars,
|
|
66
|
+
});
|
|
67
|
+
const generated = await this.generator.generate(data.from, data.subject, bodySource, data.templateVars);
|
|
68
|
+
emailDetails = Object.assign(Object.assign({}, generated), { recipient: data.recipient, attachments: (0, attachment_utils_1.deserializeAttachments)(data.attachments), cc: data.cc, bcc: data.bcc, replyTo: data.replyTo });
|
|
69
|
+
const transportSettings = await this.getTransportSettings(ctx);
|
|
70
|
+
await this.emailSender.send(emailDetails, transportSettings);
|
|
71
|
+
await this.eventBus.publish(new email_send_event_1.EmailSendEvent(ctx, emailDetails, true));
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
if (err instanceof Error) {
|
|
76
|
+
core_2.Logger.error(err.message, constants_1.loggerCtx, err.stack);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
core_2.Logger.error(String(err), constants_1.loggerCtx);
|
|
80
|
+
}
|
|
81
|
+
await this.eventBus.publish(new email_send_event_1.EmailSendEvent(ctx, emailDetails, false, err));
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async getTransportSettings(ctx) {
|
|
86
|
+
const transport = await (0, common_2.resolveTransportSettings)(this.options, new core_2.Injector(this.moduleRef), ctx);
|
|
87
|
+
if ((0, common_2.isDevModeOptions)(this.options)) {
|
|
88
|
+
if (transport && transport.type !== "file") {
|
|
89
|
+
core_2.Logger.warn(`The EmailPlugin is running in dev mode. The configured '${transport.type}' transport will be replaced by the 'file' transport.`, constants_1.loggerCtx);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
type: "file",
|
|
93
|
+
raw: false,
|
|
94
|
+
outputPath: this.options.outputPath,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
return transport;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
exports.EmailProcessor = EmailProcessor;
|
|
103
|
+
exports.EmailProcessor = EmailProcessor = __decorate([
|
|
104
|
+
(0, common_1.Injectable)(),
|
|
105
|
+
__param(0, (0, common_1.Inject)(constants_1.EMAIL_PLUGIN_OPTIONS)),
|
|
106
|
+
__metadata("design:paramtypes", [Object, core_1.ModuleRef,
|
|
107
|
+
core_2.EventBus])
|
|
108
|
+
], EmailProcessor);
|
|
109
|
+
//# sourceMappingURL=email-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-processor.js","sourceRoot":"","sources":["../../src/email-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RequestContext, DeenruvEvent } from "@deenruv/core";
|
|
2
|
+
import { EmailDetails } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* This event is fired when an email sending attempt has been made. If the sending was successful,
|
|
6
|
+
* the `success` property will be `true`, and if not, the `error` property will contain the error
|
|
7
|
+
* which occurred.
|
|
8
|
+
*
|
|
9
|
+
* @docsCategory core plugins/EmailPlugin
|
|
10
|
+
* @since 2.2.0
|
|
11
|
+
*/
|
|
12
|
+
export declare class EmailSendEvent extends DeenruvEvent {
|
|
13
|
+
readonly ctx: RequestContext;
|
|
14
|
+
readonly details: EmailDetails;
|
|
15
|
+
readonly success: boolean;
|
|
16
|
+
readonly error?: Error | undefined;
|
|
17
|
+
constructor(ctx: RequestContext, details: EmailDetails, success: boolean, error?: Error | undefined);
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EmailSendEvent = void 0;
|
|
4
|
+
const core_1 = require("@deenruv/core");
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* This event is fired when an email sending attempt has been made. If the sending was successful,
|
|
8
|
+
* the `success` property will be `true`, and if not, the `error` property will contain the error
|
|
9
|
+
* which occurred.
|
|
10
|
+
*
|
|
11
|
+
* @docsCategory core plugins/EmailPlugin
|
|
12
|
+
* @since 2.2.0
|
|
13
|
+
*/
|
|
14
|
+
class EmailSendEvent extends core_1.DeenruvEvent {
|
|
15
|
+
constructor(ctx, details, success, error) {
|
|
16
|
+
super();
|
|
17
|
+
this.ctx = ctx;
|
|
18
|
+
this.details = details;
|
|
19
|
+
this.success = success;
|
|
20
|
+
this.error = error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.EmailSendEvent = EmailSendEvent;
|
|
24
|
+
//# sourceMappingURL=email-send-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-send-event.js","sourceRoot":"","sources":["../../src/email-send-event.ts"],"names":[],"mappings":";;;AAAA,wCAA6D;AAI7D;;;;;;;;GAQG;AACH,MAAa,cAAe,SAAQ,mBAAY;IAC9C,YACkB,GAAmB,EACnB,OAAqB,EACrB,OAAgB,EAChB,KAAa;QAE7B,KAAK,EAAE,CAAC;QALQ,QAAG,GAAH,GAAG,CAAgB;QACnB,YAAO,GAAP,OAAO,CAAc;QACrB,YAAO,GAAP,OAAO,CAAS;QAChB,UAAK,GAAL,KAAK,CAAQ;IAG/B,CAAC;CACF;AATD,wCASC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Type } from "@deenruv/common/lib/shared-types";
|
|
2
|
+
import { EmailEventHandler } from "./handler/event-handler";
|
|
3
|
+
import { EventWithContext } from "./types";
|
|
4
|
+
/**
|
|
5
|
+
* @description
|
|
6
|
+
* An EmailEventListener is used to listen for events and set up a {@link EmailEventHandler} which
|
|
7
|
+
* defines how an email will be generated from this event.
|
|
8
|
+
*
|
|
9
|
+
* @docsCategory core plugins/EmailPlugin
|
|
10
|
+
*/
|
|
11
|
+
export declare class EmailEventListener<T extends string> {
|
|
12
|
+
type: T;
|
|
13
|
+
constructor(type: T);
|
|
14
|
+
/**
|
|
15
|
+
* @description
|
|
16
|
+
* Defines the event to listen for.
|
|
17
|
+
*/
|
|
18
|
+
on<Event extends EventWithContext>(event: Type<Event>): EmailEventHandler<T, Event>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EmailEventListener = void 0;
|
|
4
|
+
const event_handler_1 = require("./handler/event-handler");
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* An EmailEventListener is used to listen for events and set up a {@link EmailEventHandler} which
|
|
8
|
+
* defines how an email will be generated from this event.
|
|
9
|
+
*
|
|
10
|
+
* @docsCategory core plugins/EmailPlugin
|
|
11
|
+
*/
|
|
12
|
+
class EmailEventListener {
|
|
13
|
+
constructor(type) {
|
|
14
|
+
this.type = type;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* Defines the event to listen for.
|
|
19
|
+
*/
|
|
20
|
+
on(event) {
|
|
21
|
+
return new event_handler_1.EmailEventHandler(this, event);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.EmailEventListener = EmailEventListener;
|
|
25
|
+
//# sourceMappingURL=event-listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-listener.js","sourceRoot":"","sources":["../../src/event-listener.ts"],"names":[],"mappings":";;;AAEA,2DAA4D;AAG5D;;;;;;GAMG;AACH,MAAa,kBAAkB;IAE7B,YAAY,IAAO;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,EAAE,CACA,KAAkB;QAElB,OAAO,IAAI,iCAAiB,CAAW,IAAI,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;CACF;AAfD,gDAeC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InjectableStrategy, DeenruvEvent } from "@deenruv/core";
|
|
2
|
+
import { EmailDetails, EmailPluginOptions } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* An EmailGenerator generates the subject and body details of an email.
|
|
6
|
+
*
|
|
7
|
+
* @docsCategory core plugins/EmailPlugin
|
|
8
|
+
* @docsPage EmailGenerator
|
|
9
|
+
* @docsWeight 0
|
|
10
|
+
*/
|
|
11
|
+
export interface EmailGenerator<T extends string = any, E extends DeenruvEvent = any> extends InjectableStrategy {
|
|
12
|
+
/**
|
|
13
|
+
* @description
|
|
14
|
+
* Any necessary setup can be performed here.
|
|
15
|
+
*/
|
|
16
|
+
onInit?(options: EmailPluginOptions): void | Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* @description
|
|
19
|
+
* Given a subject and body from an email template, this method generates the final
|
|
20
|
+
* interpolated email text.
|
|
21
|
+
*/
|
|
22
|
+
generate(from: string, subject: string, body: string, templateVars: {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}): Promise<Pick<EmailDetails, "from" | "subject" | "body">> | Pick<EmailDetails, "from" | "subject" | "body">;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-generator.js","sourceRoot":"","sources":["../../../src/generator/email-generator.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { InitializedEmailPluginOptions } from "../types";
|
|
2
|
+
import { EmailGenerator } from "./email-generator";
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* Uses Handlebars (https://handlebarsjs.com/) to output MJML (https://mjml.io) which is then
|
|
6
|
+
* compiled down to responsive email HTML.
|
|
7
|
+
*
|
|
8
|
+
* @docsCategory core plugins/EmailPlugin
|
|
9
|
+
* @docsPage EmailGenerator
|
|
10
|
+
*/
|
|
11
|
+
export declare class HandlebarsMjmlGenerator implements EmailGenerator {
|
|
12
|
+
onInit(options: InitializedEmailPluginOptions): Promise<void>;
|
|
13
|
+
generate(from: string, subject: string, template: string, templateVars: any): {
|
|
14
|
+
from: string;
|
|
15
|
+
subject: string;
|
|
16
|
+
body: string;
|
|
17
|
+
};
|
|
18
|
+
private registerHelpers;
|
|
19
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.HandlebarsMjmlGenerator = void 0;
|
|
7
|
+
const dateformat_1 = __importDefault(require("dateformat"));
|
|
8
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
9
|
+
const mjml_1 = __importDefault(require("mjml"));
|
|
10
|
+
/**
|
|
11
|
+
* @description
|
|
12
|
+
* Uses Handlebars (https://handlebarsjs.com/) to output MJML (https://mjml.io) which is then
|
|
13
|
+
* compiled down to responsive email HTML.
|
|
14
|
+
*
|
|
15
|
+
* @docsCategory core plugins/EmailPlugin
|
|
16
|
+
* @docsPage EmailGenerator
|
|
17
|
+
*/
|
|
18
|
+
class HandlebarsMjmlGenerator {
|
|
19
|
+
async onInit(options) {
|
|
20
|
+
if (options.templateLoader.loadPartials) {
|
|
21
|
+
const partials = await options.templateLoader.loadPartials();
|
|
22
|
+
partials.forEach(({ name, content }) => handlebars_1.default.registerPartial(name, content));
|
|
23
|
+
}
|
|
24
|
+
this.registerHelpers();
|
|
25
|
+
}
|
|
26
|
+
generate(from, subject, template, templateVars) {
|
|
27
|
+
const compiledFrom = handlebars_1.default.compile(from, { noEscape: true });
|
|
28
|
+
const compiledSubject = handlebars_1.default.compile(subject);
|
|
29
|
+
const compiledTemplate = handlebars_1.default.compile(template);
|
|
30
|
+
// We enable prototype properties here, aware of the security implications
|
|
31
|
+
// described here: https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access
|
|
32
|
+
// This is needed because some Deenruv entities use getters on the entity
|
|
33
|
+
// prototype (e.g. Order.total) which may need to be interpolated.
|
|
34
|
+
const templateOptions = {
|
|
35
|
+
allowProtoPropertiesByDefault: true,
|
|
36
|
+
};
|
|
37
|
+
const fromResult = compiledFrom(templateVars, {
|
|
38
|
+
allowProtoPropertiesByDefault: true,
|
|
39
|
+
});
|
|
40
|
+
const subjectResult = compiledSubject(templateVars, {
|
|
41
|
+
allowProtoPropertiesByDefault: true,
|
|
42
|
+
});
|
|
43
|
+
const mjml = compiledTemplate(templateVars, {
|
|
44
|
+
allowProtoPropertiesByDefault: true,
|
|
45
|
+
});
|
|
46
|
+
const body = (0, mjml_1.default)(mjml).html;
|
|
47
|
+
return { from: fromResult, subject: subjectResult, body };
|
|
48
|
+
}
|
|
49
|
+
registerHelpers() {
|
|
50
|
+
handlebars_1.default.registerHelper("formatDate", (date, format) => {
|
|
51
|
+
if (!date) {
|
|
52
|
+
return date;
|
|
53
|
+
}
|
|
54
|
+
if (typeof format !== "string") {
|
|
55
|
+
format = "default";
|
|
56
|
+
}
|
|
57
|
+
return (0, dateformat_1.default)(date, format);
|
|
58
|
+
});
|
|
59
|
+
handlebars_1.default.registerHelper("formatMoney", (amount, currencyCode, locale) => {
|
|
60
|
+
if (amount == null) {
|
|
61
|
+
return amount;
|
|
62
|
+
}
|
|
63
|
+
// Last parameter is a generic "options" object which is not used here.
|
|
64
|
+
// If it's supplied, it means the helper function did not receive the additional, optional parameters.
|
|
65
|
+
// See https://handlebarsjs.com/api-reference/helpers.html#the-options-parameter
|
|
66
|
+
if (!currencyCode || typeof currencyCode === "object") {
|
|
67
|
+
return (amount / 100).toFixed(2);
|
|
68
|
+
}
|
|
69
|
+
// Same reasoning for `locale` as for `currencyCode` here.
|
|
70
|
+
return new Intl.NumberFormat(typeof locale === "object" ? undefined : locale, {
|
|
71
|
+
style: "currency",
|
|
72
|
+
currency: currencyCode,
|
|
73
|
+
}).format(amount / 100);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.HandlebarsMjmlGenerator = HandlebarsMjmlGenerator;
|
|
78
|
+
//# sourceMappingURL=handlebars-mjml-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlebars-mjml-generator.js","sourceRoot":"","sources":["../../../src/generator/handlebars-mjml-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { EmailGenerator } from "./email-generator";
|
|
2
|
+
/**
|
|
3
|
+
* Simply passes through the subject and template content without modification.
|
|
4
|
+
*/
|
|
5
|
+
export declare class NoopEmailGenerator implements EmailGenerator {
|
|
6
|
+
generate(from: string, subject: string, body: string, templateVars: any): {
|
|
7
|
+
from: string;
|
|
8
|
+
subject: string;
|
|
9
|
+
body: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoopEmailGenerator = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Simply passes through the subject and template content without modification.
|
|
6
|
+
*/
|
|
7
|
+
class NoopEmailGenerator {
|
|
8
|
+
generate(from, subject, body, templateVars) {
|
|
9
|
+
return { from, subject, body };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.NoopEmailGenerator = NoopEmailGenerator;
|
|
13
|
+
//# sourceMappingURL=noop-email-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noop-email-generator.js","sourceRoot":"","sources":["../../../src/generator/noop-email-generator.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH,MAAa,kBAAkB;IAC7B,QAAQ,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY,EAAE,YAAiB;QACrE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;CACF;AAJD,gDAIC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EmailDetails, ReactEmailSenderPluginOptions } from "../types.js";
|
|
2
|
+
import { EmailGenerator } from "./email-generator.js";
|
|
3
|
+
export declare class ReactComponentEmailGenerator implements EmailGenerator {
|
|
4
|
+
private opts;
|
|
5
|
+
constructor(opts: ReactEmailSenderPluginOptions);
|
|
6
|
+
generate(from: string, subject: string, templateData: string, templateVars: Record<string, unknown>): Promise<Pick<EmailDetails, "from" | "subject" | "body">>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ReactComponentEmailGenerator = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const render_1 = require("@react-email/render");
|
|
9
|
+
const core_1 = require("@deenruv/core");
|
|
10
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
11
|
+
class ReactComponentEmailGenerator {
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
this.opts = opts;
|
|
14
|
+
}
|
|
15
|
+
async generate(from, subject, templateData, templateVars) {
|
|
16
|
+
var _a, _b;
|
|
17
|
+
const compiledFrom = handlebars_1.default.compile(from, { noEscape: true });
|
|
18
|
+
const compiledSubject = handlebars_1.default.compile(subject);
|
|
19
|
+
const fromResult = compiledFrom(templateVars, {
|
|
20
|
+
allowProtoPropertiesByDefault: true,
|
|
21
|
+
});
|
|
22
|
+
const subjectResult = compiledSubject(templateVars, {
|
|
23
|
+
allowProtoPropertiesByDefault: true,
|
|
24
|
+
});
|
|
25
|
+
const data = JSON.parse(templateData);
|
|
26
|
+
const ctx = core_1.RequestContext.deserialize(data.ctx);
|
|
27
|
+
const Component = (_b = (_a = this.opts.templates)[data.type]) === null || _b === void 0 ? void 0 : _b.call(_a, ctx);
|
|
28
|
+
if (!Component) {
|
|
29
|
+
throw new Error(`Component not found [${data.type}]`);
|
|
30
|
+
}
|
|
31
|
+
const body = await (0, render_1.render)((0, jsx_runtime_1.jsx)(Component, Object.assign({}, templateVars)), {});
|
|
32
|
+
return {
|
|
33
|
+
from: fromResult,
|
|
34
|
+
subject: subjectResult,
|
|
35
|
+
body,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.ReactComponentEmailGenerator = ReactComponentEmailGenerator;
|
|
40
|
+
//# sourceMappingURL=react-email-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-email-generator.js","sourceRoot":"","sources":["../../../src/generator/react-email-generator.tsx"],"names":[],"mappings":";;;;;;;AAAA,gDAA6C;AAC7C,wCAA+C;AAC/C,4DAAoC;AAQpC,MAAa,4BAA4B;IACvC,YAAoB,IAAmC;QAAnC,SAAI,GAAJ,IAAI,CAA+B;IAAG,CAAC;IAC3D,KAAK,CAAC,QAAQ,CACZ,IAAY,EACZ,OAAe,EACf,YAAoB,EACpB,YAAqC;;QAErC,MAAM,YAAY,GAAG,oBAAU,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,eAAe,GAAG,oBAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,EAAE;YAC5C,6BAA6B,EAAE,IAAI;SACpC,CAAC,CAAC;QACH,MAAM,aAAa,GAAG,eAAe,CAAC,YAAY,EAAE;YAClD,6BAA6B,EAAE,IAAI;SACpC,CAAC,CAAC;QACH,MAAM,IAAI,GAAe,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,qBAAc,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,SAAS,GAAG,MAAA,MAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAC,IAAI,CAAC,IAAI,CAAC,mDAAG,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,IAAA,eAAM,EAAC,uBAAC,SAAS,oBAAK,YAAY,EAAI,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,aAAa;YACtB,IAAI;SACL,CAAC;IACJ,CAAC;CACF;AA7BD,oEA6BC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AccountRegistrationEvent, IdentifierChangeRequestEvent, Injector, Order, OrderStateTransitionEvent, PasswordResetEvent, RequestContext, ShippingLine } from "@deenruv/core";
|
|
2
|
+
import { EmailEventHandler } from "./event-handler";
|
|
3
|
+
export declare const orderConfirmationHandler: EmailEventHandler<"order-confirmation", import("../types").EventWithAsyncData<OrderStateTransitionEvent, {
|
|
4
|
+
shippingLines: ShippingLine[];
|
|
5
|
+
}>>;
|
|
6
|
+
export declare const emailVerificationHandler: EmailEventHandler<"email-verification", AccountRegistrationEvent>;
|
|
7
|
+
export declare const passwordResetHandler: EmailEventHandler<"password-reset", PasswordResetEvent>;
|
|
8
|
+
export declare const emailAddressChangeHandler: EmailEventHandler<"email-address-change", IdentifierChangeRequestEvent>;
|
|
9
|
+
export declare const defaultEmailHandlers: Array<EmailEventHandler<any, any>>;
|
|
10
|
+
/**
|
|
11
|
+
* @description
|
|
12
|
+
* Applies the configured `AssetStorageStrategy.toAbsoluteUrl()` function to each of the
|
|
13
|
+
* OrderLine's `featuredAsset.preview` properties, so that they can be correctly displayed
|
|
14
|
+
* in the email template.
|
|
15
|
+
* This is required since that step usually happens at the API in middleware, which is not
|
|
16
|
+
* applicable in this context. So we need to do it manually.
|
|
17
|
+
*
|
|
18
|
+
* **Note: Mutates the Order object**
|
|
19
|
+
*
|
|
20
|
+
* @docsCategory core plugins/EmailPlugin
|
|
21
|
+
* @docsPage Email utils
|
|
22
|
+
*/
|
|
23
|
+
export declare function transformOrderLineAssetUrls(ctx: RequestContext, order: Order, injector: Injector): Order;
|
|
24
|
+
/**
|
|
25
|
+
* @description
|
|
26
|
+
* Ensures that the ShippingLines are hydrated so that we can use the
|
|
27
|
+
* `shippingMethod.name` property in the email template.
|
|
28
|
+
*
|
|
29
|
+
* @docsCategory core plugins/EmailPlugin
|
|
30
|
+
* @docsPage Email utils
|
|
31
|
+
*/
|
|
32
|
+
export declare function hydrateShippingLines(ctx: RequestContext, order: Order, injector: Injector): Promise<ShippingLine[]>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hydrateShippingLines = exports.transformOrderLineAssetUrls = exports.defaultEmailHandlers = exports.emailAddressChangeHandler = exports.passwordResetHandler = exports.emailVerificationHandler = exports.orderConfirmationHandler = void 0;
|
|
4
|
+
const core_1 = require("@deenruv/core");
|
|
5
|
+
const event_listener_1 = require("../event-listener");
|
|
6
|
+
const mock_events_1 = require("./mock-events");
|
|
7
|
+
exports.orderConfirmationHandler = new event_listener_1.EmailEventListener("order-confirmation")
|
|
8
|
+
.on(core_1.OrderStateTransitionEvent)
|
|
9
|
+
.filter((event) => event.toState === "PaymentSettled" &&
|
|
10
|
+
event.fromState !== "Modifying" &&
|
|
11
|
+
!!event.order.customer)
|
|
12
|
+
.loadData(async ({ event, injector }) => {
|
|
13
|
+
transformOrderLineAssetUrls(event.ctx, event.order, injector);
|
|
14
|
+
const shippingLines = await hydrateShippingLines(event.ctx, event.order, injector);
|
|
15
|
+
return { shippingLines };
|
|
16
|
+
})
|
|
17
|
+
.setRecipient((event) => event.order.customer.emailAddress)
|
|
18
|
+
.setFrom("{{ fromAddress }}")
|
|
19
|
+
.setSubject("Order confirmation for #{{ order.code }}")
|
|
20
|
+
.setTemplateVars((event) => ({
|
|
21
|
+
order: event.order,
|
|
22
|
+
shippingLines: event.data.shippingLines,
|
|
23
|
+
}))
|
|
24
|
+
.setMockEvent(mock_events_1.mockOrderStateTransitionEvent);
|
|
25
|
+
exports.emailVerificationHandler = new event_listener_1.EmailEventListener("email-verification")
|
|
26
|
+
.on(core_1.AccountRegistrationEvent)
|
|
27
|
+
.filter((event) => !!event.user.getNativeAuthenticationMethod().identifier)
|
|
28
|
+
.filter((event) => {
|
|
29
|
+
const nativeAuthMethod = event.user.authenticationMethods.find((m) => m instanceof core_1.NativeAuthenticationMethod);
|
|
30
|
+
return (nativeAuthMethod && !!nativeAuthMethod.identifier) || false;
|
|
31
|
+
})
|
|
32
|
+
.setRecipient((event) => event.user.identifier)
|
|
33
|
+
.setFrom("{{ fromAddress }}")
|
|
34
|
+
.setSubject("Please verify your email address")
|
|
35
|
+
.setTemplateVars((event) => ({
|
|
36
|
+
verificationToken: event.user.getNativeAuthenticationMethod().verificationToken,
|
|
37
|
+
}))
|
|
38
|
+
.setMockEvent(mock_events_1.mockAccountRegistrationEvent);
|
|
39
|
+
exports.passwordResetHandler = new event_listener_1.EmailEventListener("password-reset")
|
|
40
|
+
.on(core_1.PasswordResetEvent)
|
|
41
|
+
.setRecipient((event) => event.user.identifier)
|
|
42
|
+
.setFrom("{{ fromAddress }}")
|
|
43
|
+
.setSubject("Forgotten password reset")
|
|
44
|
+
.setTemplateVars((event) => ({
|
|
45
|
+
passwordResetToken: event.user.getNativeAuthenticationMethod().passwordResetToken,
|
|
46
|
+
}))
|
|
47
|
+
.setMockEvent(mock_events_1.mockPasswordResetEvent);
|
|
48
|
+
exports.emailAddressChangeHandler = new event_listener_1.EmailEventListener("email-address-change")
|
|
49
|
+
.on(core_1.IdentifierChangeRequestEvent)
|
|
50
|
+
.setRecipient((event) => event.user.getNativeAuthenticationMethod().pendingIdentifier)
|
|
51
|
+
.setFrom("{{ fromAddress }}")
|
|
52
|
+
.setSubject("Please verify your change of email address")
|
|
53
|
+
.setTemplateVars((event) => ({
|
|
54
|
+
identifierChangeToken: event.user.getNativeAuthenticationMethod().identifierChangeToken,
|
|
55
|
+
}))
|
|
56
|
+
.setMockEvent(mock_events_1.mockEmailAddressChangeEvent);
|
|
57
|
+
exports.defaultEmailHandlers = [
|
|
58
|
+
exports.orderConfirmationHandler,
|
|
59
|
+
exports.emailVerificationHandler,
|
|
60
|
+
exports.passwordResetHandler,
|
|
61
|
+
exports.emailAddressChangeHandler,
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* @description
|
|
65
|
+
* Applies the configured `AssetStorageStrategy.toAbsoluteUrl()` function to each of the
|
|
66
|
+
* OrderLine's `featuredAsset.preview` properties, so that they can be correctly displayed
|
|
67
|
+
* in the email template.
|
|
68
|
+
* This is required since that step usually happens at the API in middleware, which is not
|
|
69
|
+
* applicable in this context. So we need to do it manually.
|
|
70
|
+
*
|
|
71
|
+
* **Note: Mutates the Order object**
|
|
72
|
+
*
|
|
73
|
+
* @docsCategory core plugins/EmailPlugin
|
|
74
|
+
* @docsPage Email utils
|
|
75
|
+
*/
|
|
76
|
+
function transformOrderLineAssetUrls(ctx, order, injector) {
|
|
77
|
+
const { assetStorageStrategy } = injector.get(core_1.ConfigService).assetOptions;
|
|
78
|
+
if (assetStorageStrategy.toAbsoluteUrl) {
|
|
79
|
+
const toAbsoluteUrl = assetStorageStrategy.toAbsoluteUrl.bind(assetStorageStrategy);
|
|
80
|
+
for (const line of order.lines) {
|
|
81
|
+
if (line.featuredAsset) {
|
|
82
|
+
line.featuredAsset.preview = toAbsoluteUrl(ctx.req, line.featuredAsset.preview);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return order;
|
|
87
|
+
}
|
|
88
|
+
exports.transformOrderLineAssetUrls = transformOrderLineAssetUrls;
|
|
89
|
+
/**
|
|
90
|
+
* @description
|
|
91
|
+
* Ensures that the ShippingLines are hydrated so that we can use the
|
|
92
|
+
* `shippingMethod.name` property in the email template.
|
|
93
|
+
*
|
|
94
|
+
* @docsCategory core plugins/EmailPlugin
|
|
95
|
+
* @docsPage Email utils
|
|
96
|
+
*/
|
|
97
|
+
async function hydrateShippingLines(ctx, order, injector) {
|
|
98
|
+
const shippingLines = [];
|
|
99
|
+
const entityHydrator = injector.get(core_1.EntityHydrator);
|
|
100
|
+
for (const line of order.shippingLines || []) {
|
|
101
|
+
await entityHydrator.hydrate(ctx, line, {
|
|
102
|
+
relations: ["shippingMethod"],
|
|
103
|
+
});
|
|
104
|
+
if (line.shippingMethod) {
|
|
105
|
+
shippingLines.push(line);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return shippingLines;
|
|
109
|
+
}
|
|
110
|
+
exports.hydrateShippingLines = hydrateShippingLines;
|
|
111
|
+
//# sourceMappingURL=default-email-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-email-handlers.js","sourceRoot":"","sources":["../../../src/handler/default-email-handlers.ts"],"names":[],"mappings":"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"}
|