@c9up/rover 0.1.14 → 0.1.16
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/Mail.d.ts +8 -4
- package/dist/Mail.d.ts.map +1 -1
- package/dist/Mail.js +7 -6
- package/dist/Mail.js.map +1 -1
- package/dist/MessageBuilder.js +1 -1
- package/dist/MessageBuilder.js.map +1 -1
- package/dist/RoverProvider.d.ts +1 -0
- package/dist/RoverProvider.d.ts.map +1 -1
- package/dist/RoverProvider.js +9 -3
- package/dist/RoverProvider.js.map +1 -1
- package/dist/augmentations.d.ts +29 -0
- package/dist/augmentations.d.ts.map +1 -0
- package/dist/augmentations.js +18 -0
- package/dist/augmentations.js.map +1 -0
- package/dist/emitSafely.d.ts +18 -0
- package/dist/emitSafely.d.ts.map +1 -0
- package/dist/emitSafely.js +22 -0
- package/dist/emitSafely.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/queue/MemoryMailMessenger.d.ts.map +1 -1
- package/dist/queue/MemoryMailMessenger.js +14 -15
- package/dist/queue/MemoryMailMessenger.js.map +1 -1
- package/dist/retry.d.ts +10 -1
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +9 -0
- package/dist/retry.js.map +1 -1
- package/dist/testing/FakeMail.d.ts +4 -2
- package/dist/testing/FakeMail.d.ts.map +1 -1
- package/dist/testing/FakeMail.js +4 -19
- package/dist/testing/FakeMail.js.map +1 -1
- package/dist/transports/BrevoTransport.js +6 -3
- package/dist/transports/BrevoTransport.js.map +1 -1
- package/dist/transports/MailgunTransport.d.ts.map +1 -1
- package/dist/transports/MailgunTransport.js +59 -45
- package/dist/transports/MailgunTransport.js.map +1 -1
- package/dist/transports/SendGridTransport.d.ts.map +1 -1
- package/dist/transports/SendGridTransport.js +80 -82
- package/dist/transports/SendGridTransport.js.map +1 -1
- package/dist/transports/SparkPostTransport.js +6 -3
- package/dist/transports/SparkPostTransport.js.map +1 -1
- package/dist/webhooks/context.d.ts +9 -1
- package/dist/webhooks/context.d.ts.map +1 -1
- package/dist/webhooks/mailgun.d.ts.map +1 -1
- package/dist/webhooks/mailgun.js +2 -1
- package/dist/webhooks/mailgun.js.map +1 -1
- package/dist/webhooks/resend.d.ts.map +1 -1
- package/dist/webhooks/resend.js +2 -1
- package/dist/webhooks/resend.js.map +1 -1
- package/dist/webhooks/sendgrid.d.ts.map +1 -1
- package/dist/webhooks/sendgrid.js +2 -1
- package/dist/webhooks/sendgrid.js.map +1 -1
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +8 -7
- package/scripts/build-napi-types.mjs +4 -3
- package/scripts/generate-napi-types.mjs +9 -6
- package/src/Mail.ts +21 -11
- package/src/MessageBuilder.ts +1 -1
- package/src/RoverProvider.ts +9 -3
- package/src/augmentations.ts +33 -0
- package/src/emitSafely.ts +31 -0
- package/src/index.ts +2 -0
- package/src/queue/MemoryMailMessenger.ts +15 -14
- package/src/retry.ts +11 -2
- package/src/testing/FakeMail.ts +12 -3
- package/src/transports/BrevoTransport.ts +6 -3
- package/src/transports/MailgunTransport.ts +64 -56
- package/src/transports/SendGridTransport.ts +86 -117
- package/src/transports/SparkPostTransport.ts +6 -3
- package/src/webhooks/context.ts +9 -1
- package/src/webhooks/mailgun.ts +2 -1
- package/src/webhooks/resend.ts +2 -1
- package/src/webhooks/sendgrid.ts +2 -1
|
@@ -30,6 +30,14 @@ export interface WebhookHttpContext {
|
|
|
30
30
|
}
|
|
31
31
|
export type WebhookMiddleware = (ctx: WebhookHttpContext, next: () => Promise<void>) => Promise<void>;
|
|
32
32
|
export interface WebhookEmitter {
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* `unknown`, not `void`. `@adonisjs/events` declares
|
|
35
|
+
* `emit(): Promise<void>` and rethrows when a listener fails and no error
|
|
36
|
+
* handler is registered — and a `void` return ACCEPTS a promise-returning
|
|
37
|
+
* function, so the call site reads as if there were nothing to handle.
|
|
38
|
+
* Duck-typed, so it stays wider than Adonis's own class: a Node
|
|
39
|
+
* EventEmitter returns boolean.
|
|
40
|
+
*/
|
|
41
|
+
emit(event: string, data: unknown): unknown;
|
|
34
42
|
}
|
|
35
43
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/webhooks/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;IACrD,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE;QACR;;;;WAIG;QACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QACzC;;;;;;WAMG;QACH,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QACpC,IAAI,CAAC,IAAI,OAAO,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAC/B,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC9B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/webhooks/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IACtC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;IACrD,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE;QACR;;;;WAIG;QACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QACzC;;;;;;WAMG;QACH,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QACpC,IAAI,CAAC,IAAI,OAAO,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAC/B,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC9B;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAC5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mailgun.d.ts","sourceRoot":"","sources":["../../src/webhooks/mailgun.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mailgun.d.ts","sourceRoot":"","sources":["../../src/webhooks/mailgun.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,cAAc,EAEd,iBAAiB,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,qBAAqB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAqBD,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,qBAAqB,GAC5B,iBAAiB,CAuEnB"}
|
package/dist/webhooks/mailgun.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { emitSafely } from "../emitSafely.js";
|
|
3
4
|
const EVENT_MAP = {
|
|
4
5
|
delivered: "mail.delivered",
|
|
5
6
|
failed: "mail.failed",
|
|
@@ -58,7 +59,7 @@ export function createMailgunWebhookHandler(options) {
|
|
|
58
59
|
const eventName = EVENT_MAP[data.event];
|
|
59
60
|
if (eventName) {
|
|
60
61
|
try {
|
|
61
|
-
emitter
|
|
62
|
+
emitSafely(emitter, eventName, {
|
|
62
63
|
messageId: data.message?.headers?.["message-id"] ?? "",
|
|
63
64
|
to: data.recipient ?? "",
|
|
64
65
|
reason: data.reason,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mailgun.js","sourceRoot":"","sources":["../../src/webhooks/mailgun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"mailgun.js","sourceRoot":"","sources":["../../src/webhooks/mailgun.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resend.d.ts","sourceRoot":"","sources":["../../src/webhooks/resend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resend.d.ts","sourceRoot":"","sources":["../../src/webhooks/resend.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,cAAc,EAEd,iBAAiB,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACpC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAgED,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,oBAAoB,GAC3B,iBAAiB,CAgDnB"}
|
package/dist/webhooks/resend.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
3
|
+
import { emitSafely } from "../emitSafely.js";
|
|
3
4
|
/**
|
|
4
5
|
* Parse a provider-supplied `created_at` into an epoch-ms timestamp,
|
|
5
6
|
* falling back to "now" for anything unparseable. Without the
|
|
@@ -126,7 +127,7 @@ function emitMappedEvent(emitter, payload) {
|
|
|
126
127
|
? (payload.data.to[0] ?? "")
|
|
127
128
|
: (payload.data?.to ?? "");
|
|
128
129
|
try {
|
|
129
|
-
emitter
|
|
130
|
+
emitSafely(emitter, mapped, {
|
|
130
131
|
messageId: payload.data?.email_id ?? "",
|
|
131
132
|
to,
|
|
132
133
|
reason: payload.data?.reason,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resend.js","sourceRoot":"","sources":["../../src/webhooks/resend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"resend.js","sourceRoot":"","sources":["../../src/webhooks/resend.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sendgrid.d.ts","sourceRoot":"","sources":["../../src/webhooks/sendgrid.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sendgrid.d.ts","sourceRoot":"","sources":["../../src/webhooks/sendgrid.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,cAAc,EAEd,iBAAiB,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,sBAAsB;IACtC,wFAAwF;IACxF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,CAAC;IACxB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAkBD,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,sBAAsB,GAC7B,iBAAiB,CA8EnB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
2
|
import { createPublicKey, verify } from "node:crypto";
|
|
3
|
+
import { emitSafely } from "../emitSafely.js";
|
|
3
4
|
const EVENT_MAP = {
|
|
4
5
|
delivered: "mail.delivered",
|
|
5
6
|
bounce: "mail.bounced",
|
|
@@ -69,7 +70,7 @@ export function createSendGridWebhookHandler(options) {
|
|
|
69
70
|
if (!mapped)
|
|
70
71
|
continue;
|
|
71
72
|
try {
|
|
72
|
-
emitter
|
|
73
|
+
emitSafely(emitter, mapped, {
|
|
73
74
|
messageId: ev.sg_message_id ?? "",
|
|
74
75
|
to: ev.email ?? "",
|
|
75
76
|
reason: ev.reason,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sendgrid.js","sourceRoot":"","sources":["../../src/webhooks/sendgrid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"sendgrid.js","sourceRoot":"","sources":["../../src/webhooks/sendgrid.ts"],"names":[],"mappings":"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"}
|
package/index.darwin-arm64.node
CHANGED
|
Binary file
|
package/index.darwin-x64.node
CHANGED
|
Binary file
|
|
Binary file
|
package/index.linux-x64-gnu.node
CHANGED
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c9up/rover",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Mail transport for Ream — SMTP, log, and pluggable transports",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -64,16 +64,16 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"
|
|
68
|
-
"form-data": "^4.0.1",
|
|
69
|
-
"mailgun.js": "^13.0.1",
|
|
70
|
-
"nodemailer": "^8.0.5"
|
|
67
|
+
"nodemailer": "^9.0.1"
|
|
71
68
|
},
|
|
72
69
|
"devDependencies": {
|
|
73
70
|
"@biomejs/biome": "^2.4.10",
|
|
71
|
+
"@c9up/bay": "^0.1.13",
|
|
74
72
|
"@c9up/helix": "^0.2.0",
|
|
73
|
+
"@c9up/ream": "^0.2.0",
|
|
75
74
|
"@types/node": "*",
|
|
76
75
|
"@types/nodemailer": "^7.0.0",
|
|
76
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
77
77
|
"typescript": "^6.0.2",
|
|
78
78
|
"vitest": "^4.1.2"
|
|
79
79
|
},
|
|
@@ -109,8 +109,9 @@
|
|
|
109
109
|
"build:napi": "cargo build --release -p rover-template-engine-napi && pnpm build:napi-types && node scripts/copy-napi.mjs",
|
|
110
110
|
"build:napi-types": "node scripts/build-napi-types.mjs",
|
|
111
111
|
"test": "vitest run",
|
|
112
|
-
"lint": "biome check src/",
|
|
112
|
+
"lint": "biome check src/ tests/",
|
|
113
113
|
"test:coverage": "vitest run --coverage",
|
|
114
|
-
"typecheck": "tsc --noEmit"
|
|
114
|
+
"typecheck": "tsc --noEmit",
|
|
115
|
+
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json"
|
|
115
116
|
}
|
|
116
117
|
}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* cargo a `/tmp/...` path the native proc-macro cannot write to, so the
|
|
8
8
|
* type-def file comes back empty and the build fails for no visible reason.
|
|
9
9
|
*
|
|
10
|
-
* One crate at a time on purpose: napi-derive
|
|
10
|
+
* One crate at a time on purpose: with napi-derive 2 the writes all went to a
|
|
11
|
+
* single `TYPE_DEF_TMP_PATH` and a parallel build interleaved them
|
|
11
12
|
* while cargo compiles, and a parallel build interleaves the writes —
|
|
12
13
|
* definitions go missing, silently, and the generated file comes out short.
|
|
13
14
|
*/
|
|
@@ -28,11 +29,11 @@ const scratch = mkdtempSync(join(tmpdir(), 'napi-types-'))
|
|
|
28
29
|
try {
|
|
29
30
|
const lines = []
|
|
30
31
|
for (const crate of CRATES) {
|
|
31
|
-
const perCrate = join(scratch,
|
|
32
|
+
const perCrate = join(scratch, crate)
|
|
32
33
|
writeFileSync(perCrate, '')
|
|
33
34
|
execFileSync('cargo', ['build', '-p', crate], {
|
|
34
35
|
cwd: packageRoot,
|
|
35
|
-
env: { ...process.env,
|
|
36
|
+
env: { ...process.env, NAPI_TYPE_DEF_TMP_FOLDER: scratch },
|
|
36
37
|
stdio: ['ignore', 'ignore', 'inherit'],
|
|
37
38
|
})
|
|
38
39
|
const emitted = readFileSync(perCrate, 'utf8').split('\n').filter(Boolean)
|
|
@@ -130,12 +130,15 @@ for (const fn of fns) {
|
|
|
130
130
|
// napi-derive emits the whole declaration for a function, unlike a struct
|
|
131
131
|
// where `def` holds only the members.
|
|
132
132
|
const declaration = fn.def.trim()
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
// napi-derive 3 emits a bare `function name(...)` where 2 emitted the
|
|
134
|
+
// signature after the name; concatenating onto the former produced
|
|
135
|
+
// `function xfunction x(...)`.
|
|
136
|
+
const rendered = declaration.startsWith('export declare function')
|
|
137
|
+
? declaration
|
|
138
|
+
: declaration.startsWith('function ')
|
|
139
|
+
? `export declare ${declaration}`
|
|
140
|
+
: `export declare function ${fn.name}${declaration}`
|
|
141
|
+
out.push(`${rendered};`, '')
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
const stale = Object.keys(CALLBACK_REFINEMENTS).filter((k) => !used.has(k))
|
package/src/Mail.ts
CHANGED
|
@@ -72,7 +72,11 @@ export interface MailTransport {
|
|
|
72
72
|
* Rover never hard-imports the event bus.
|
|
73
73
|
*/
|
|
74
74
|
export interface EmitterLike {
|
|
75
|
-
|
|
75
|
+
/**
|
|
76
|
+
* `unknown`, not `void`: a `void` return ACCEPTS a promise-returning
|
|
77
|
+
* function, which is how an Adonis emitter's rejection went unnoticed.
|
|
78
|
+
*/
|
|
79
|
+
emit(event: string, data: unknown): unknown;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
/**
|
|
@@ -147,7 +151,7 @@ export interface MailConfig {
|
|
|
147
151
|
*/
|
|
148
152
|
mailers?: Record<
|
|
149
153
|
string,
|
|
150
|
-
{ transport: string; retry?: RetryConfig
|
|
154
|
+
{ transport: string; retry?: Partial<RetryConfig>; [key: string]: unknown }
|
|
151
155
|
>;
|
|
152
156
|
/**
|
|
153
157
|
* Rover's older spelling of `mailers`. Still accepted and identical in
|
|
@@ -155,14 +159,14 @@ export interface MailConfig {
|
|
|
155
159
|
*/
|
|
156
160
|
transports?: Record<
|
|
157
161
|
string,
|
|
158
|
-
{ transport: string; retry?: RetryConfig
|
|
162
|
+
{ transport: string; retry?: Partial<RetryConfig>; [key: string]: unknown }
|
|
159
163
|
>;
|
|
160
164
|
/** Root directory for `htmlView(path, data)` template lookups. Default: `"resources/views/emails"`. */
|
|
161
165
|
viewsRoot?: string;
|
|
162
166
|
/** Optional Bay queue tuning for `sendLater()`. */
|
|
163
167
|
queue?: { name?: string; maxAttempts?: number };
|
|
164
168
|
/** Process-wide retry defaults. Overridden per-mailer via `mailers[name].retry`. */
|
|
165
|
-
retry?: RetryConfig
|
|
169
|
+
retry?: Partial<RetryConfig>;
|
|
166
170
|
}
|
|
167
171
|
|
|
168
172
|
/**
|
|
@@ -393,8 +397,8 @@ export class Mail {
|
|
|
393
397
|
#memoryMessenger: MemoryMailMessenger;
|
|
394
398
|
#queueName: string;
|
|
395
399
|
#queueMaxAttempts: number;
|
|
396
|
-
#globalRetry: RetryConfig | undefined;
|
|
397
|
-
#transportRetry: Map<string, RetryConfig
|
|
400
|
+
#globalRetry: Partial<RetryConfig> | undefined;
|
|
401
|
+
#transportRetry: Map<string, Partial<RetryConfig>> = new Map();
|
|
398
402
|
#hooks: MailHooks;
|
|
399
403
|
#emitter: EmitterLike | null;
|
|
400
404
|
/** Per-instance template root, threaded into each render so concurrent Mails with different roots don't clobber the shared global. */
|
|
@@ -735,11 +739,17 @@ export class Mail {
|
|
|
735
739
|
);
|
|
736
740
|
}
|
|
737
741
|
if (this.#emitter) {
|
|
738
|
-
try
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
742
|
+
// Not just `try`: an Adonis-shaped emitter returns a promise, and a
|
|
743
|
+
// listener that failed asynchronously rejected it with nobody to
|
|
744
|
+
// catch — an unhandled rejection ending the process over a
|
|
745
|
+
// notification, long after the mail itself went out fine.
|
|
746
|
+
void (async () => this.#emitter?.emit(name, event))().catch(
|
|
747
|
+
(err: unknown) => {
|
|
748
|
+
process.stderr.write(
|
|
749
|
+
`[rover] ${name} listener failed: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
750
|
+
);
|
|
751
|
+
},
|
|
752
|
+
);
|
|
743
753
|
}
|
|
744
754
|
}
|
|
745
755
|
|
package/src/MessageBuilder.ts
CHANGED
|
@@ -228,7 +228,7 @@ function listUrls(value: ListHeader | ListHeader[] | ListHeader[][]): string[] {
|
|
|
228
228
|
function titleCaseKey(key: string): string {
|
|
229
229
|
return key
|
|
230
230
|
.split("-")
|
|
231
|
-
.map((part) => (
|
|
231
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
232
232
|
.join("-");
|
|
233
233
|
}
|
|
234
234
|
|
package/src/RoverProvider.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./augmentations.js";
|
|
1
2
|
import type { EmitterLike, MailConfig } from "./Mail.js";
|
|
2
3
|
import { Mail } from "./Mail.js";
|
|
3
4
|
import type { BayQueueLike } from "./queue/MailJob.js";
|
|
@@ -43,9 +44,14 @@ export default class RoverProvider {
|
|
|
43
44
|
},
|
|
44
45
|
);
|
|
45
46
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// Namespaced by the package that owns it, the way upstream namespaces
|
|
48
|
+
// `lucid.db`, `auth.manager` and `drive.manager` by theirs. The bare
|
|
49
|
+
// token stays bound beside it: it is what every existing
|
|
50
|
+
// `container.make(...)` asks for, and a token is not worth breaking an
|
|
51
|
+
// application over.
|
|
52
|
+
const mail = (): Promise<Mail> => this.app.container.resolve<Mail>(Mail);
|
|
53
|
+
this.app.container.singleton("rover.mail", mail);
|
|
54
|
+
this.app.container.singleton("mail", mail);
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
async boot() {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Teach ream's `ContainerBindings` what `container.make(...)` returns for the
|
|
3
|
+
* tokens rover binds.
|
|
4
|
+
*
|
|
5
|
+
* ream declares that interface open on purpose: it registers its own entries
|
|
6
|
+
* and expects each package to contribute the ones it owns. Nothing filled
|
|
7
|
+
* these in, so resolving by the string token answered `unknown` and every call
|
|
8
|
+
* site had to assert a type it could not prove.
|
|
9
|
+
*
|
|
10
|
+
* Loaded from the package barrel, so importing Rover anywhere in the
|
|
11
|
+
* application is enough — nobody writes a `declare module` of their own.
|
|
12
|
+
*
|
|
13
|
+
* Type-only, and ream stays an OPTIONAL peer: nothing here reaches a runtime
|
|
14
|
+
* import, and a `declare module` for a specifier that does not resolve is
|
|
15
|
+
* simply inert.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Referenced so the augmentation below resolves the module it augments.
|
|
19
|
+
import type {} from "@c9up/ream/types";
|
|
20
|
+
|
|
21
|
+
import type { Mail } from "./Mail.js";
|
|
22
|
+
|
|
23
|
+
declare module "@c9up/ream/types" {
|
|
24
|
+
interface ContainerBindings {
|
|
25
|
+
/** The mailer, bound by `RoverProvider`. */
|
|
26
|
+
"rover.mail": Mail;
|
|
27
|
+
/**
|
|
28
|
+
* The same binding under the name it had before the token carried its
|
|
29
|
+
* package. Kept bound so an existing `container.make(...)` resolves.
|
|
30
|
+
*/
|
|
31
|
+
mail: Mail;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emit an event without letting the listener come back.
|
|
3
|
+
*
|
|
4
|
+
* `@adonisjs/events` declares `emit(): Promise<void>` and rethrows when a
|
|
5
|
+
* listener fails and the application registered no error handler. Nothing here
|
|
6
|
+
* awaits an event — a webhook has already been acknowledged, a queued mail has
|
|
7
|
+
* already been sent or already failed — so that rejection had nowhere to go
|
|
8
|
+
* and ended the process over a notification.
|
|
9
|
+
*
|
|
10
|
+
* The emitter is invoked INSIDE the async function rather than before it:
|
|
11
|
+
* `Promise.resolve(emit(...))` runs `emit` first, so a synchronous throw would
|
|
12
|
+
* still escape. The call itself stays synchronous, because an async body runs
|
|
13
|
+
* to its first `await` — only the failure handling is deferred.
|
|
14
|
+
*/
|
|
15
|
+
export function emitSafely(
|
|
16
|
+
emitter:
|
|
17
|
+
| { emit: (event: string, data: unknown) => unknown }
|
|
18
|
+
| null
|
|
19
|
+
| undefined,
|
|
20
|
+
event: string,
|
|
21
|
+
data: unknown,
|
|
22
|
+
): void {
|
|
23
|
+
if (emitter == null) return;
|
|
24
|
+
void (async () => emitter.emit(event, data))().catch((error: unknown) => {
|
|
25
|
+
process.stderr.write(
|
|
26
|
+
`[rover] '${event}' listener failed: ${
|
|
27
|
+
error instanceof Error ? error.message : String(error)
|
|
28
|
+
}\n`,
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* for each of them, so each has to be there when the config is read.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import "./augmentations.js";
|
|
11
|
+
|
|
10
12
|
export type { MailAddress } from "./BaseMail.js";
|
|
11
13
|
export { BaseMail } from "./BaseMail.js";
|
|
12
14
|
export type { TransportDescriptor } from "./config.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { emitSafely } from "../emitSafely.js";
|
|
2
3
|
import type { EmitterLike, MailMessage } from "../Mail.js";
|
|
3
4
|
import type { MailDispatcher } from "./MailJob.js";
|
|
4
5
|
|
|
@@ -24,20 +25,20 @@ export class MemoryMailMessenger {
|
|
|
24
25
|
this.#dispatcher
|
|
25
26
|
.dispatchMessage(message, transport)
|
|
26
27
|
.catch((error: unknown) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
28
|
+
// The try/catch here only ever caught a listener that threw
|
|
29
|
+
// SYNCHRONOUSLY. An Adonis emitter's `emit` is async and
|
|
30
|
+
// rethrows when a listener fails and no error handler is
|
|
31
|
+
// registered, so an async one rejected inside a microtask
|
|
32
|
+
// nobody awaits — the failure notification taking the process
|
|
33
|
+
// down after the mail had already failed.
|
|
34
|
+
emitSafely(this.#emitter, "queued:mail:error", {
|
|
35
|
+
jobId,
|
|
36
|
+
transportName: transport,
|
|
37
|
+
error:
|
|
38
|
+
error instanceof Error
|
|
39
|
+
? { message: error.message }
|
|
40
|
+
: { message: String(error) },
|
|
41
|
+
});
|
|
41
42
|
});
|
|
42
43
|
});
|
|
43
44
|
return jobId;
|
package/src/retry.ts
CHANGED
|
@@ -83,9 +83,18 @@ export function computeBackoffMs(
|
|
|
83
83
|
return Math.min(config.maxDelayMs, Math.max(50, raw));
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Global and per-transport overrides, merged over the defaults.
|
|
88
|
+
*
|
|
89
|
+
* `Partial`, because that is what the function does: it spreads whatever it is
|
|
90
|
+
* given over {@link DEFAULT_RETRY_CONFIG}, so `{ maxAttempts: 1 }` is a
|
|
91
|
+
* complete answer. Declared as the full `RetryConfig`, a config file writing
|
|
92
|
+
* exactly that was a type error for doing the supported thing — and every
|
|
93
|
+
* caller had to spell `baseDelayMs` and `factor` it did not want to change.
|
|
94
|
+
*/
|
|
86
95
|
export function resolveRetryConfig(
|
|
87
|
-
globalConfig: RetryConfig | undefined,
|
|
88
|
-
transportConfig: RetryConfig | undefined,
|
|
96
|
+
globalConfig: Partial<RetryConfig> | undefined,
|
|
97
|
+
transportConfig: Partial<RetryConfig> | undefined,
|
|
89
98
|
): Required<RetryConfig> {
|
|
90
99
|
// Skip entries whose value is `undefined` so a partial override doesn't
|
|
91
100
|
// clobber a default or global value. Pre-spread filter is required because
|
package/src/testing/FakeMail.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PluginApi } from "@c9up/helix";
|
|
2
2
|
import { BaseMail } from "../BaseMail.js";
|
|
3
3
|
import type { MailMessage, MailSendOutcome, MailTransport } from "../Mail.js";
|
|
4
4
|
|
|
@@ -340,8 +340,17 @@ export interface FakeableMailer {
|
|
|
340
340
|
* frame) and torn down when that test ends — so capture never leaks between
|
|
341
341
|
* tests. Uses the manager's own `fake()`/`restore()` (the Adonis pattern).
|
|
342
342
|
*/
|
|
343
|
-
|
|
344
|
-
|
|
343
|
+
/** The slice of helix's `PluginApi` this plugin uses. */
|
|
344
|
+
export type MailPluginHost = Pick<PluginApi, "context">;
|
|
345
|
+
|
|
346
|
+
export function mailFake(
|
|
347
|
+
mailer: FakeableMailer,
|
|
348
|
+
): (api: MailPluginHost) => void {
|
|
349
|
+
// Typed by what it touches, not by the whole `PluginApi`: a test wiring the
|
|
350
|
+
// plugin had to build every field of it — `config`, `cliArgs`, `runner`,
|
|
351
|
+
// `emitter`, `cleanup` — to exercise a function that reads one. Same shape
|
|
352
|
+
// `@c9up/helix-plugin-ream` uses for its own host.
|
|
353
|
+
return (api: MailPluginHost) => {
|
|
345
354
|
api.context.getter("mail", (ctx) => {
|
|
346
355
|
const fake = mailer.fake();
|
|
347
356
|
ctx.cleanup(() => mailer.restore());
|
|
@@ -165,9 +165,12 @@ export class BrevoTransport implements MailTransport {
|
|
|
165
165
|
function parseContact(input: string): BrevoContact {
|
|
166
166
|
const s = stripCrlf(input).trim();
|
|
167
167
|
const match = s.match(/^(.*)<([^>]+)>\s*$/);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
// Both groups are required by the pattern, so a match carries both —
|
|
169
|
+
// named rather than indexed, which is what says so.
|
|
170
|
+
const [, rawName, rawEmail] = match ?? [];
|
|
171
|
+
if (rawEmail !== undefined) {
|
|
172
|
+
const email = rawEmail.trim();
|
|
173
|
+
const name = (rawName ?? "").trim().replace(/^"|"$/g, "").trim();
|
|
171
174
|
return name ? { email, name } : { email };
|
|
172
175
|
}
|
|
173
176
|
return { email: s };
|