@growth-labs/mailer 0.4.0 → 0.4.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.
@@ -20,6 +20,12 @@ export declare function _resetSchemaProbeCache(): void;
20
20
  * than silent.
21
21
  */
22
22
  export declare function probeMailerSchema(db: D1DatabaseLike | undefined, d1Binding: string): Promise<ProbeResult>;
23
+ /**
24
+ * Probe only `gl_email_sends`. Realm queue consumers keep subscriber tables in
25
+ * each site D1, so the realm D1 must be allowed to contain sends without
26
+ * subscribers.
27
+ */
28
+ export declare function probeMailerSendsSchema(db: D1DatabaseLike | undefined, d1Binding: string): Promise<ProbeResult>;
23
29
  /**
24
30
  * Helper: build the standard 503 response mailer routes return on schema
25
31
  * miss. The body shape is stable so observability dashboards can match on
@@ -1 +1 @@
1
- {"version":3,"file":"schema-probe.d.ts","sourceRoot":"","sources":["../../src/_internal/schema-probe.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,wBAAwB,6BAA6B,CAAA;AAElE,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,OAAO,CAAA;CAAE,CAAA;AAEzC,UAAU,mBAAmB;IAC5B,KAAK,CAAC,CAAC,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;CACvC;AAED,UAAU,cAAc;IACvB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAAA;CAC3C;AAID,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACtC,EAAE,EAAE,cAAc,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAkBtB;AAgBD;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,QAAQ,CAQhD"}
1
+ {"version":3,"file":"schema-probe.d.ts","sourceRoot":"","sources":["../../src/_internal/schema-probe.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,wBAAwB,6BAA6B,CAAA;AAElE,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,OAAO,CAAA;CAAE,CAAA;AAEzC,UAAU,mBAAmB;IAC5B,KAAK,CAAC,CAAC,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;CACvC;AAED,UAAU,cAAc;IACvB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAAA;CAC3C;AAKD,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACtC,EAAE,EAAE,cAAc,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAkBtB;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,cAAc,GAAG,SAAS,EAC9B,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAiBtB;AA4BD;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,QAAQ,CAQhD"}
@@ -9,9 +9,11 @@
9
9
  // body, observability gets one loud error per instance startup.
10
10
  export const GL_MAILER_SCHEMA_MISSING = 'GL_MAILER_SCHEMA_MISSING';
11
11
  let _cached = null;
12
+ let _sendsCached = null;
12
13
  /** @internal Reset the module-scoped cache — tests only. */
13
14
  export function _resetSchemaProbeCache() {
14
15
  _cached = null;
16
+ _sendsCached = null;
15
17
  }
16
18
  /**
17
19
  * Probe the configured D1 binding for `gl_subscribers` AND `gl_email_sends`.
@@ -43,6 +45,31 @@ export async function probeMailerSchema(db, d1Binding) {
43
45
  return _cached;
44
46
  }
45
47
  }
48
+ /**
49
+ * Probe only `gl_email_sends`. Realm queue consumers keep subscriber tables in
50
+ * each site D1, so the realm D1 must be allowed to contain sends without
51
+ * subscribers.
52
+ */
53
+ export async function probeMailerSendsSchema(db, d1Binding) {
54
+ if (_sendsCached)
55
+ return _sendsCached;
56
+ if (!db) {
57
+ logSendsSchemaMissing(d1Binding, 'D1 binding is not bound');
58
+ _sendsCached = { ok: false };
59
+ return _sendsCached;
60
+ }
61
+ try {
62
+ await db.prepare('SELECT 1 FROM gl_email_sends LIMIT 1').first();
63
+ _sendsCached = { ok: true };
64
+ return _sendsCached;
65
+ }
66
+ catch (err) {
67
+ const message = err instanceof Error ? err.message : String(err);
68
+ logSendsSchemaMissing(d1Binding, message);
69
+ _sendsCached = { ok: false };
70
+ return _sendsCached;
71
+ }
72
+ }
46
73
  function logSchemaMissing(d1Binding, underlying) {
47
74
  console.error(`[${GL_MAILER_SCHEMA_MISSING}] @growth-labs/mailer: D1 binding "${d1Binding}" is ` +
48
75
  'missing one or both of the gl_subscribers / gl_email_sends tables.\n' +
@@ -54,6 +81,15 @@ function logSchemaMissing(d1Binding, underlying) {
54
81
  'Mailer routes return 503 until the schema is present. ' +
55
82
  `Underlying error: ${underlying}`);
56
83
  }
84
+ function logSendsSchemaMissing(d1Binding, underlying) {
85
+ console.error(`[${GL_MAILER_SCHEMA_MISSING}] @growth-labs/mailer: D1 binding "${d1Binding}" is ` +
86
+ 'missing the gl_email_sends table.\n' +
87
+ 'Remediation:\n' +
88
+ ' 1. Add a sends-only migration for @growth-labs/mailer/schema/sends\n' +
89
+ ` 2. Run: pnpm exec wrangler d1 migrations apply ${d1Binding} --remote\n` +
90
+ 'Realm queue consumers ack messages until the schema is present. ' +
91
+ `Underlying error: ${underlying}`);
92
+ }
57
93
  /**
58
94
  * Helper: build the standard 503 response mailer routes return on schema
59
95
  * miss. The body shape is stable so observability dashboards can match on
@@ -1 +1 @@
1
- {"version":3,"file":"schema-probe.js","sourceRoot":"","sources":["../../src/_internal/schema-probe.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAC9E,6DAA6D;AAC7D,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,gEAAgE;AAEhE,MAAM,CAAC,MAAM,wBAAwB,GAAG,0BAA0B,CAAA;AAYlE,IAAI,OAAO,GAAuB,IAAI,CAAA;AAEtC,4DAA4D;AAC5D,MAAM,UAAU,sBAAsB;IACrC,OAAO,GAAG,IAAI,CAAA;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,EAA8B,EAC9B,SAAiB;IAEjB,IAAI,OAAO;QAAE,OAAO,OAAO,CAAA;IAC3B,IAAI,CAAC,EAAE,EAAE,CAAC;QACT,gBAAgB,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAA;QACtD,OAAO,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;QACvB,OAAO,OAAO,CAAA;IACf,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC,KAAK,EAAE,CAAA;QAChE,MAAM,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC,KAAK,EAAE,CAAA;QAChE,OAAO,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;QACtB,OAAO,OAAO,CAAA;IACf,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChE,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QACpC,OAAO,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,CAAA;QACvB,OAAO,OAAO,CAAA;IACf,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB,EAAE,UAAkB;IAC9D,OAAO,CAAC,KAAK,CACZ,IAAI,wBAAwB,sCAAsC,SAAS,OAAO;QACjF,sEAAsE;QACtE,gBAAgB;QAChB,gEAAgE;QAChE,yEAAyE;QACzE,oDAAoD,SAAS,aAAa;QAC1E,iEAAiE;QACjE,wDAAwD;QACxD,qBAAqB,UAAU,EAAE,CAClC,CAAA;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACpC,OAAO,QAAQ,CAAC,IAAI,CACnB;QACC,KAAK,EAAE,kCAAkC;QACzC,IAAI,EAAE,wBAAwB;KAC9B,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CACf,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"schema-probe.js","sourceRoot":"","sources":["../../src/_internal/schema-probe.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,10 @@
1
- import type { ResolvedMailerOptions } from '../options.js';
2
- import type { EmailQueueMessage } from '../types.js';
3
- export declare function handleEmailQueue(batch: MessageBatch<EmailQueueMessage>, env: Record<string, unknown>, options: ResolvedMailerOptions): Promise<void>;
1
+ import type { EmailQueueMessage, SiteConfigLookup } from '../types.js';
2
+ export type { SiteConfigLookup, SiteMailerConfig } from '../types.js';
3
+ export interface MailerConsumerOptions {
4
+ d1Binding: string;
5
+ senderBinding: string;
6
+ analyticsBinding?: string;
7
+ siteConfigLookup: SiteConfigLookup;
8
+ }
9
+ export declare function handleEmailQueue(batch: MessageBatch<EmailQueueMessage>, env: Record<string, unknown>, options: MailerConsumerOptions): Promise<void>;
4
10
  //# sourceMappingURL=consumer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../../src/queue/consumer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,aAAa,CAAA;AA2BtE,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,YAAY,CAAC,iBAAiB,CAAC,EACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAuIf"}
1
+ {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../../src/queue/consumer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAoB,MAAM,aAAa,CAAA;AAMxF,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAErE,MAAM,WAAW,qBAAqB;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,gBAAgB,CAAA;CAClC;AAuBD,wBAAsB,gBAAgB,CACrC,KAAK,EAAE,YAAY,CAAC,iBAAiB,CAAC,EACtC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,EAAE,qBAAqB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA8Jf"}
@@ -1,13 +1,16 @@
1
1
  import { drizzle } from 'drizzle-orm/d1';
2
- import { probeMailerSchema } from '../_internal/schema-probe.js';
2
+ import { probeMailerSendsSchema } from '../_internal/schema-probe.js';
3
3
  import { emitMailerAnalyticsEvent } from '../utils/analytics.js';
4
4
  import { updateSendStatus } from '../utils/bounce.js';
5
5
  import { CloudflareEmailProvider, sleep } from '../utils/providers.js';
6
- function applyOverride(options, override) {
6
+ function applySiteConfig(config) {
7
7
  return {
8
- siteUrl: override?.siteUrl ?? options.siteUrl,
9
- unsubscribePath: override?.unsubscribePath ?? options.unsubscribePath,
10
- preferencesPath: override?.preferencesPath ?? options.preferencesPath,
8
+ siteUrl: config.siteUrl,
9
+ unsubscribePath: config.unsubscribePath ?? '/api/newsletter/unsubscribe',
10
+ preferencesPath: config.preferencesPath ?? '/email/preferences',
11
+ senderName: config.senderName,
12
+ fromAddress: config.fromAddress,
13
+ replyTo: config.replyTo,
11
14
  };
12
15
  }
13
16
  export async function handleEmailQueue(batch, env, options) {
@@ -25,7 +28,7 @@ export async function handleEmailQueue(batch, env, options) {
25
28
  // GL_MAILER_SCHEMA_MISSING and we ack every message in the batch without
26
29
  // retry. Re-queueing without the schema would cycle indefinitely and burn
27
30
  // Cloudflare Queue retry budget.
28
- const schemaProbe = await probeMailerSchema(d1, options.d1Binding);
31
+ const schemaProbe = await probeMailerSendsSchema(d1, options.d1Binding);
29
32
  if (!schemaProbe.ok) {
30
33
  console.error('[mailer] gl_email_sends not found in env.' +
31
34
  options.d1Binding +
@@ -41,20 +44,29 @@ export async function handleEmailQueue(batch, env, options) {
41
44
  const db = drizzle(d1);
42
45
  const provider = new CloudflareEmailProvider(sender);
43
46
  for (const message of batch.messages) {
44
- const override = options.siteConfigLookup && message.body.siteId
45
- ? await options.siteConfigLookup(message.body.siteId, env)
46
- : null;
47
- const effective = applyOverride(options, override);
47
+ const siteConfig = await options.siteConfigLookup(message.body.siteId, env);
48
+ if (!siteConfig) {
49
+ console.error(`[mailer] No SiteMailerConfig for siteId=${message.body.siteId}; acking without send.`);
50
+ message.ack();
51
+ continue;
52
+ }
53
+ const effective = applySiteConfig(siteConfig);
48
54
  const { recipients, htmlTemplate, subject, from, replyTo, headers, type } = message.body;
49
- const effectiveFrom = override?.fromAddress
50
- ? formatFromHeader(override.senderName ?? options.senderName, override.fromAddress)
55
+ if (type !== 'transactional' && !effective.siteUrl) {
56
+ console.error(`[mailer] SiteMailerConfig for siteId=${message.body.siteId} is missing siteUrl; acking without send.`);
57
+ message.ack();
58
+ continue;
59
+ }
60
+ const effectiveFrom = effective.fromAddress
61
+ ? formatFromHeader(effective.senderName ?? effective.fromAddress, effective.fromAddress)
51
62
  : from;
52
- const effectiveReplyTo = override?.replyTo ?? replyTo;
63
+ const effectiveReplyTo = effective.replyTo ?? replyTo;
53
64
  for (const recipient of recipients) {
54
65
  let html = htmlTemplate;
55
66
  if (type !== 'transactional') {
56
- const unsubscribeUrl = `${effective.siteUrl}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}`;
57
- const preferencesUrl = `${effective.siteUrl}${effective.preferencesPath}?token=${recipient.preferencesToken}`;
67
+ const siteUrl = effective.siteUrl ?? '';
68
+ const unsubscribeUrl = `${siteUrl}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}`;
69
+ const preferencesUrl = `${siteUrl}${effective.preferencesPath}?token=${recipient.preferencesToken}`;
58
70
  html = html
59
71
  .replaceAll('{{TRACKING_ID}}', recipient.trackingId)
60
72
  .replaceAll('{{UNSUBSCRIBE_URL}}', unsubscribeUrl)
@@ -63,7 +75,7 @@ export async function handleEmailQueue(batch, env, options) {
63
75
  const recipientHeaders = type !== 'transactional'
64
76
  ? {
65
77
  ...headers,
66
- 'List-Unsubscribe': `<${effective.siteUrl}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}>`,
78
+ 'List-Unsubscribe': `<${effective.siteUrl ?? ''}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}>`,
67
79
  'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
68
80
  }
69
81
  : headers;
@@ -94,7 +106,7 @@ export async function handleEmailQueue(batch, env, options) {
94
106
  await updateSendStatus(db, recipient.trackingId, 'sent', {
95
107
  sentAt: new Date().toISOString(),
96
108
  });
97
- emitMailerAnalyticsEvent(options, env, 'newsletter_sent', {
109
+ emitMailerAnalyticsEvent(analyticsOptions(options, effective, message.body.siteId), env, 'newsletter_sent', {
98
110
  contentSlug: recipient.trackingId,
99
111
  label: {
100
112
  trackingId: recipient.trackingId,
@@ -111,7 +123,7 @@ export async function handleEmailQueue(batch, env, options) {
111
123
  bouncedAt: new Date().toISOString(),
112
124
  bounceType: 'hard',
113
125
  });
114
- emitMailerAnalyticsEvent(options, env, 'newsletter_send_failed', {
126
+ emitMailerAnalyticsEvent(analyticsOptions(options, effective, message.body.siteId), env, 'newsletter_send_failed', {
115
127
  contentSlug: recipient.trackingId,
116
128
  label: {
117
129
  trackingId: recipient.trackingId,
@@ -132,4 +144,11 @@ export async function handleEmailQueue(batch, env, options) {
132
144
  function formatFromHeader(senderName, fromAddress) {
133
145
  return `${senderName} <${fromAddress}>`;
134
146
  }
147
+ function analyticsOptions(options, effective, siteId) {
148
+ return {
149
+ siteUrl: effective.siteUrl ?? `https://${siteId}`,
150
+ analyticsEnabled: Boolean(options.analyticsBinding),
151
+ analyticsBinding: options.analyticsBinding ?? 'ANALYTICS',
152
+ };
153
+ }
135
154
  //# sourceMappingURL=consumer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consumer.js","sourceRoot":"","sources":["../../src/queue/consumer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"consumer.js","sourceRoot":"","sources":["../../src/queue/consumer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAErE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD,OAAO,EAAE,uBAAuB,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAqBtE,SAAS,eAAe,CAAC,MAAwB;IAChD,OAAO;QACN,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,6BAA6B;QACxE,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,oBAAoB;QAC/D,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;KACvB,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,KAAsC,EACtC,GAA4B,EAC5B,OAA8B;IAE9B,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAA2B,CAAA;IAC3D,IAAI,CAAC,EAAE,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACd,gBAAgB,OAAO,CAAC,SAAS,iBAAiB;YACjD,qFAAqF,CACtF,CAAA;IACF,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAsC,CAAA;IAC9E,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACd,gBAAgB,OAAO,CAAC,aAAa,iBAAiB;YACrD,kGAAkG,CACnG,CAAA;IACF,CAAC;IAED,uEAAuE;IACvE,yEAAyE;IACzE,0EAA0E;IAC1E,iCAAiC;IACjC,MAAM,WAAW,GAAG,MAAM,sBAAsB,CAAC,EAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IACvE,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CACZ,2CAA2C;YAC1C,OAAO,CAAC,SAAS;YACjB,sDAAsD;YACtD,SAAS;YACT,KAAK,CAAC,QAAQ,CAAC,MAAM;YACrB,mCAAmC,CACpC,CAAA;QACD,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,EAAE,CAAA;QACd,CAAC;QACD,OAAM;IACP,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAA;IACtB,MAAM,QAAQ,GAAG,IAAI,uBAAuB,CAAC,MAAM,CAAC,CAAA;IAEpD,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC3E,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CACZ,2CAA2C,OAAO,CAAC,IAAI,CAAC,MAAM,wBAAwB,CACtF,CAAA;YACD,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,SAAQ;QACT,CAAC;QACD,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;QAE7C,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAA;QACxF,IAAI,IAAI,KAAK,eAAe,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YACpD,OAAO,CAAC,KAAK,CACZ,wCAAwC,OAAO,CAAC,IAAI,CAAC,MAAM,2CAA2C,CACtG,CAAA;YACD,OAAO,CAAC,GAAG,EAAE,CAAA;YACb,SAAQ;QACT,CAAC;QAED,MAAM,aAAa,GAAG,SAAS,CAAC,WAAW;YAC1C,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,IAAI,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,WAAW,CAAC;YACxF,CAAC,CAAC,IAAI,CAAA;QACP,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAO,IAAI,OAAO,CAAA;QAErD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACpC,IAAI,IAAI,GAAG,YAAY,CAAA;YACvB,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;gBAC9B,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,IAAI,EAAE,CAAA;gBACvC,MAAM,cAAc,GAAG,GAAG,OAAO,GAAG,SAAS,CAAC,eAAe,UAAU,SAAS,CAAC,gBAAgB,EAAE,CAAA;gBACnG,MAAM,cAAc,GAAG,GAAG,OAAO,GAAG,SAAS,CAAC,eAAe,UAAU,SAAS,CAAC,gBAAgB,EAAE,CAAA;gBACnG,IAAI,GAAG,IAAI;qBACT,UAAU,CAAC,iBAAiB,EAAE,SAAS,CAAC,UAAU,CAAC;qBACnD,UAAU,CAAC,qBAAqB,EAAE,cAAc,CAAC;qBACjD,UAAU,CAAC,qBAAqB,EAAE,cAAc,CAAC,CAAA;YACpD,CAAC;YAED,MAAM,gBAAgB,GACrB,IAAI,KAAK,eAAe;gBACvB,CAAC,CAAC;oBACA,GAAG,OAAO;oBACV,kBAAkB,EAAE,IAAI,SAAS,CAAC,OAAO,IAAI,EAAE,GAAG,SAAS,CAAC,eAAe,UAAU,SAAS,CAAC,gBAAgB,GAAG;oBAClH,uBAAuB,EAAE,4BAA4B;iBACrD;gBACF,CAAC,CAAC,OAAO,CAAA;YAEX,IAAI,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;gBAChC,EAAE,EAAE,SAAS,CAAC,KAAK;gBACnB,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,gBAAgB;gBACzB,OAAO;gBACP,IAAI;gBACJ,OAAO,EAAE,gBAAgB;aACzB,CAAC,CAAA;YAEF,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACzC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;oBAC/C,MAAM,KAAK,CAAC,CAAC,IAAI,OAAO,GAAG,IAAI,CAAC,CAAA;oBAChC,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;wBAC5B,EAAE,EAAE,SAAS,CAAC,KAAK;wBACnB,IAAI,EAAE,aAAa;wBACnB,OAAO,EAAE,gBAAgB;wBACzB,OAAO;wBACP,IAAI;wBACJ,OAAO,EAAE,gBAAgB;qBACzB,CAAC,CAAA;oBACF,IAAI,MAAM,CAAC,OAAO;wBAAE,MAAK;gBAC1B,CAAC;YACF,CAAC;YAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE;oBACxD,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBAChC,CAAC,CAAA;gBACF,wBAAwB,CACvB,gBAAgB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EACzD,GAAG,EACH,iBAAiB,EACjB;oBACC,WAAW,EAAE,SAAS,CAAC,UAAU;oBACjC,KAAK,EAAE;wBACN,UAAU,EAAE,SAAS,CAAC,UAAU;wBAChC,YAAY,EAAE,SAAS,CAAC,YAAY;wBACpC,KAAK,EAAE,SAAS,CAAC,KAAK;wBACtB,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU;wBACnC,IAAI;wBACJ,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM;qBAC3B;iBACD,CACD,CAAA;YACF,CAAC;iBAAM,CAAC;gBACP,MAAM,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE;oBAC3D,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;oBACnC,UAAU,EAAE,MAAM;iBAClB,CAAC,CAAA;gBACF,wBAAwB,CACvB,gBAAgB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EACzD,GAAG,EACH,wBAAwB,EACxB;oBACC,WAAW,EAAE,SAAS,CAAC,UAAU;oBACjC,KAAK,EAAE;wBACN,UAAU,EAAE,SAAS,CAAC,UAAU;wBAChC,YAAY,EAAE,SAAS,CAAC,YAAY;wBACpC,KAAK,EAAE,SAAS,CAAC,KAAK;wBACtB,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU;wBACnC,IAAI;wBACJ,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM;wBAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;qBACnB;iBACD,CACD,CAAA;gBACD,OAAO,CAAC,KAAK,CAAC,4BAA4B,SAAS,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;YAC9E,CAAC;QACF,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAA;IACd,CAAC;AACF,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,WAAmB;IAChE,OAAO,GAAG,UAAU,KAAK,WAAW,GAAG,CAAA;AACxC,CAAC;AAED,SAAS,gBAAgB,CACxB,OAA8B,EAC9B,SAA2B,EAC3B,MAAc;IAMd,OAAO;QACN,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,WAAW,MAAM,EAAE;QACjD,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;QACnD,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,WAAW;KACzD,CAAA;AACF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -39,12 +39,9 @@ export interface EmailQueueMessage {
39
39
  campaignId?: string;
40
40
  }
41
41
  /**
42
- * Per-site config override applied at consumer time. Returned from
43
- * SiteConfigLookup. All fields are optional only the ones present
44
- * will override the consumer's resolved options for that message.
45
- *
46
- * Bindings (d1Binding, queueBinding, senderBinding) and route paths
47
- * are NOT overridable per-site; they're realm-wide.
42
+ * Per-site config resolved at consumer time. Realm consumers keep bindings in
43
+ * their own Worker config and load sender / URL metadata from this object for
44
+ * every queued message.
48
45
  */
49
46
  export interface SiteMailerConfig {
50
47
  siteUrl?: string;
@@ -63,8 +60,8 @@ export interface SiteMailerConfig {
63
60
  }
64
61
  /**
65
62
  * Per-message lookup, called by the realm consumer with the message's
66
- * `siteId`. Returns the per-site config to apply, or `null` to skip the
67
- * override and use the consumer's options as-is.
63
+ * `siteId`. Returns the per-site config to apply, or `null` when the consumer
64
+ * should ack the message without sending because the registry entry is absent.
68
65
  */
69
66
  export type SiteConfigLookup = (siteId: string, env: Record<string, unknown>) => Promise<SiteMailerConfig | null>;
70
67
  export interface QueueRecipient {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,gBAAgB,CAAA;IACxB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,qBAAqB,CAAA;IACnC,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,GAAG,SAAS,GAAG,YAAY,CAAA;AAE/F,MAAM,WAAW,qBAAqB;IACrC,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAID,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CACjB;AAID,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAA;IAC7C,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAID;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,UAAU,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;CACD;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC9B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KACxB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;AAErC,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;CACxB;AAID,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAA;IAC7C,MAAM,EAAE,eAAe,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,eAAe,GACxB,QAAQ,GACR,MAAM,GACN,WAAW,GACX,QAAQ,GACR,SAAS,GACT,SAAS,GACT,YAAY,CAAA;AAIf,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;CAClB;AAID,MAAM,MAAM,YAAY,GACrB,cAAc,GACd,SAAS,GACT,UAAU,GACV,QAAQ,GACR,eAAe,GACf,qBAAqB,CAAA;AAExB,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;AAID,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;CACf"}
@@ -1,4 +1,3 @@
1
- import type { ResolvedMailerOptions } from '../options.js';
2
1
  export type MailerAnalyticsEvent = 'newsletter_subscribed' | 'newsletter_confirmed' | 'newsletter_unsubscribed' | 'newsletter_opened' | 'newsletter_clicked' | 'newsletter_webhook_received' | 'newsletter_delivered' | 'newsletter_bounced' | 'newsletter_complained' | 'newsletter_sent' | 'newsletter_send_failed';
3
2
  interface AnalyticsContext {
4
3
  locals?: {
@@ -7,6 +6,11 @@ interface AnalyticsContext {
7
6
  };
8
7
  };
9
8
  }
9
+ export interface MailerAnalyticsRuntimeOptions {
10
+ siteUrl: string;
11
+ analyticsEnabled: boolean;
12
+ analyticsBinding: string;
13
+ }
10
14
  interface EmitMailerAnalyticsOptions {
11
15
  request?: Request;
12
16
  context?: AnalyticsContext;
@@ -14,8 +18,8 @@ interface EmitMailerAnalyticsOptions {
14
18
  contentSlug?: string;
15
19
  eventValue?: number;
16
20
  }
17
- export declare function emitMailerAnalyticsEvent(options: ResolvedMailerOptions, bindingsEnv: Record<string, unknown>, eventName: MailerAnalyticsEvent, emitOptions?: EmitMailerAnalyticsOptions): boolean;
18
- export declare function buildMailerAnalyticsDataPoint(options: ResolvedMailerOptions, eventName: MailerAnalyticsEvent, emitOptions?: EmitMailerAnalyticsOptions): {
21
+ export declare function emitMailerAnalyticsEvent(options: MailerAnalyticsRuntimeOptions, bindingsEnv: Record<string, unknown>, eventName: MailerAnalyticsEvent, emitOptions?: EmitMailerAnalyticsOptions): boolean;
22
+ export declare function buildMailerAnalyticsDataPoint(options: MailerAnalyticsRuntimeOptions, eventName: MailerAnalyticsEvent, emitOptions?: EmitMailerAnalyticsOptions): {
19
23
  blobs: string[];
20
24
  doubles: number[];
21
25
  indexes: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAE1D,MAAM,MAAM,oBAAoB,GAC7B,uBAAuB,GACvB,sBAAsB,GACtB,yBAAyB,GACzB,mBAAmB,GACnB,oBAAoB,GACpB,6BAA6B,GAC7B,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,iBAAiB,GACjB,wBAAwB,CAAA;AAM3B,UAAU,gBAAgB;IACzB,MAAM,CAAC,EAAE;QACR,SAAS,CAAC,EAAE;YACX,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;SAC1C,CAAA;KACD,CAAA;CACD;AAED,UAAU,0BAA0B;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,qBAAqB,EAC9B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,SAAS,EAAE,oBAAoB,EAC/B,WAAW,GAAE,0BAA+B,GAC1C,OAAO,CAeT;AAED,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAE,oBAAoB,EAC/B,WAAW,GAAE,0BAA+B,GAC1C;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CA+B3D"}
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAC7B,uBAAuB,GACvB,sBAAsB,GACtB,yBAAyB,GACzB,mBAAmB,GACnB,oBAAoB,GACpB,6BAA6B,GAC7B,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,iBAAiB,GACjB,wBAAwB,CAAA;AAM3B,UAAU,gBAAgB;IACzB,MAAM,CAAC,EAAE;QACR,SAAS,CAAC,EAAE;YACX,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;SAC1C,CAAA;KACD,CAAA;CACD;AAED,MAAM,WAAW,6BAA6B;IAC7C,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,OAAO,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;CACxB;AAED,UAAU,0BAA0B;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,6BAA6B,EACtC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,SAAS,EAAE,oBAAoB,EAC/B,WAAW,GAAE,0BAA+B,GAC1C,OAAO,CAeT;AAED,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE,6BAA6B,EACtC,SAAS,EAAE,oBAAoB,EAC/B,WAAW,GAAE,0BAA+B,GAC1C;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CA+B3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/utils/analytics.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/mailer",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -21,10 +21,12 @@ interface D1DatabaseLike {
21
21
  }
22
22
 
23
23
  let _cached: ProbeResult | null = null
24
+ let _sendsCached: ProbeResult | null = null
24
25
 
25
26
  /** @internal Reset the module-scoped cache — tests only. */
26
27
  export function _resetSchemaProbeCache(): void {
27
28
  _cached = null
29
+ _sendsCached = null
28
30
  }
29
31
 
30
32
  /**
@@ -59,6 +61,33 @@ export async function probeMailerSchema(
59
61
  }
60
62
  }
61
63
 
64
+ /**
65
+ * Probe only `gl_email_sends`. Realm queue consumers keep subscriber tables in
66
+ * each site D1, so the realm D1 must be allowed to contain sends without
67
+ * subscribers.
68
+ */
69
+ export async function probeMailerSendsSchema(
70
+ db: D1DatabaseLike | undefined,
71
+ d1Binding: string,
72
+ ): Promise<ProbeResult> {
73
+ if (_sendsCached) return _sendsCached
74
+ if (!db) {
75
+ logSendsSchemaMissing(d1Binding, 'D1 binding is not bound')
76
+ _sendsCached = { ok: false }
77
+ return _sendsCached
78
+ }
79
+ try {
80
+ await db.prepare('SELECT 1 FROM gl_email_sends LIMIT 1').first()
81
+ _sendsCached = { ok: true }
82
+ return _sendsCached
83
+ } catch (err) {
84
+ const message = err instanceof Error ? err.message : String(err)
85
+ logSendsSchemaMissing(d1Binding, message)
86
+ _sendsCached = { ok: false }
87
+ return _sendsCached
88
+ }
89
+ }
90
+
62
91
  function logSchemaMissing(d1Binding: string, underlying: string): void {
63
92
  console.error(
64
93
  `[${GL_MAILER_SCHEMA_MISSING}] @growth-labs/mailer: D1 binding "${d1Binding}" is ` +
@@ -73,6 +102,18 @@ function logSchemaMissing(d1Binding: string, underlying: string): void {
73
102
  )
74
103
  }
75
104
 
105
+ function logSendsSchemaMissing(d1Binding: string, underlying: string): void {
106
+ console.error(
107
+ `[${GL_MAILER_SCHEMA_MISSING}] @growth-labs/mailer: D1 binding "${d1Binding}" is ` +
108
+ 'missing the gl_email_sends table.\n' +
109
+ 'Remediation:\n' +
110
+ ' 1. Add a sends-only migration for @growth-labs/mailer/schema/sends\n' +
111
+ ` 2. Run: pnpm exec wrangler d1 migrations apply ${d1Binding} --remote\n` +
112
+ 'Realm queue consumers ack messages until the schema is present. ' +
113
+ `Underlying error: ${underlying}`,
114
+ )
115
+ }
116
+
76
117
  /**
77
118
  * Helper: build the standard 503 response mailer routes return on schema
78
119
  * miss. The body shape is stable so observability dashboards can match on
@@ -1,37 +1,45 @@
1
1
  import { drizzle } from 'drizzle-orm/d1'
2
- import { probeMailerSchema } from '../_internal/schema-probe.js'
3
- import type { ResolvedMailerOptions } from '../options.js'
4
- import type { EmailQueueMessage, SiteMailerConfig } from '../types.js'
2
+ import { probeMailerSendsSchema } from '../_internal/schema-probe.js'
3
+ import type { EmailQueueMessage, SiteConfigLookup, SiteMailerConfig } from '../types.js'
5
4
  import { emitMailerAnalyticsEvent } from '../utils/analytics.js'
6
5
  import { updateSendStatus } from '../utils/bounce.js'
7
6
  import type { CloudflareEmailSender } from '../utils/providers.js'
8
7
  import { CloudflareEmailProvider, sleep } from '../utils/providers.js'
9
8
 
10
- /**
11
- * Effective options for a single message — options merged with any
12
- * SiteMailerConfig override returned by `siteConfigLookup`.
13
- */
9
+ export type { SiteConfigLookup, SiteMailerConfig } from '../types.js'
10
+
11
+ export interface MailerConsumerOptions {
12
+ d1Binding: string
13
+ senderBinding: string
14
+ analyticsBinding?: string
15
+ siteConfigLookup: SiteConfigLookup
16
+ }
17
+
18
+ /** Effective options for a single message, resolved from `siteConfigLookup`. */
14
19
  interface EffectiveOptions {
15
- siteUrl: string
20
+ siteUrl?: string
16
21
  unsubscribePath: string
17
22
  preferencesPath: string
23
+ senderName?: string
24
+ fromAddress?: string
25
+ replyTo?: string
18
26
  }
19
27
 
20
- function applyOverride(
21
- options: ResolvedMailerOptions,
22
- override: SiteMailerConfig | null,
23
- ): EffectiveOptions {
28
+ function applySiteConfig(config: SiteMailerConfig): EffectiveOptions {
24
29
  return {
25
- siteUrl: override?.siteUrl ?? options.siteUrl,
26
- unsubscribePath: override?.unsubscribePath ?? options.unsubscribePath,
27
- preferencesPath: override?.preferencesPath ?? options.preferencesPath,
30
+ siteUrl: config.siteUrl,
31
+ unsubscribePath: config.unsubscribePath ?? '/api/newsletter/unsubscribe',
32
+ preferencesPath: config.preferencesPath ?? '/email/preferences',
33
+ senderName: config.senderName,
34
+ fromAddress: config.fromAddress,
35
+ replyTo: config.replyTo,
28
36
  }
29
37
  }
30
38
 
31
39
  export async function handleEmailQueue(
32
40
  batch: MessageBatch<EmailQueueMessage>,
33
41
  env: Record<string, unknown>,
34
- options: ResolvedMailerOptions,
42
+ options: MailerConsumerOptions,
35
43
  ): Promise<void> {
36
44
  const d1 = env[options.d1Binding] as D1Database | undefined
37
45
  if (!d1) {
@@ -53,7 +61,7 @@ export async function handleEmailQueue(
53
61
  // GL_MAILER_SCHEMA_MISSING and we ack every message in the batch without
54
62
  // retry. Re-queueing without the schema would cycle indefinitely and burn
55
63
  // Cloudflare Queue retry budget.
56
- const schemaProbe = await probeMailerSchema(d1, options.d1Binding)
64
+ const schemaProbe = await probeMailerSendsSchema(d1, options.d1Binding)
57
65
  if (!schemaProbe.ok) {
58
66
  console.error(
59
67
  '[mailer] gl_email_sends not found in env.' +
@@ -73,23 +81,36 @@ export async function handleEmailQueue(
73
81
  const provider = new CloudflareEmailProvider(sender)
74
82
 
75
83
  for (const message of batch.messages) {
76
- const override =
77
- options.siteConfigLookup && message.body.siteId
78
- ? await options.siteConfigLookup(message.body.siteId, env)
79
- : null
80
- const effective = applyOverride(options, override)
84
+ const siteConfig = await options.siteConfigLookup(message.body.siteId, env)
85
+ if (!siteConfig) {
86
+ console.error(
87
+ `[mailer] No SiteMailerConfig for siteId=${message.body.siteId}; acking without send.`,
88
+ )
89
+ message.ack()
90
+ continue
91
+ }
92
+ const effective = applySiteConfig(siteConfig)
81
93
 
82
94
  const { recipients, htmlTemplate, subject, from, replyTo, headers, type } = message.body
83
- const effectiveFrom = override?.fromAddress
84
- ? formatFromHeader(override.senderName ?? options.senderName, override.fromAddress)
95
+ if (type !== 'transactional' && !effective.siteUrl) {
96
+ console.error(
97
+ `[mailer] SiteMailerConfig for siteId=${message.body.siteId} is missing siteUrl; acking without send.`,
98
+ )
99
+ message.ack()
100
+ continue
101
+ }
102
+
103
+ const effectiveFrom = effective.fromAddress
104
+ ? formatFromHeader(effective.senderName ?? effective.fromAddress, effective.fromAddress)
85
105
  : from
86
- const effectiveReplyTo = override?.replyTo ?? replyTo
106
+ const effectiveReplyTo = effective.replyTo ?? replyTo
87
107
 
88
108
  for (const recipient of recipients) {
89
109
  let html = htmlTemplate
90
110
  if (type !== 'transactional') {
91
- const unsubscribeUrl = `${effective.siteUrl}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}`
92
- const preferencesUrl = `${effective.siteUrl}${effective.preferencesPath}?token=${recipient.preferencesToken}`
111
+ const siteUrl = effective.siteUrl ?? ''
112
+ const unsubscribeUrl = `${siteUrl}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}`
113
+ const preferencesUrl = `${siteUrl}${effective.preferencesPath}?token=${recipient.preferencesToken}`
93
114
  html = html
94
115
  .replaceAll('{{TRACKING_ID}}', recipient.trackingId)
95
116
  .replaceAll('{{UNSUBSCRIBE_URL}}', unsubscribeUrl)
@@ -100,7 +121,7 @@ export async function handleEmailQueue(
100
121
  type !== 'transactional'
101
122
  ? {
102
123
  ...headers,
103
- 'List-Unsubscribe': `<${effective.siteUrl}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}>`,
124
+ 'List-Unsubscribe': `<${effective.siteUrl ?? ''}${effective.unsubscribePath}?token=${recipient.unsubscribeToken}>`,
104
125
  'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
105
126
  }
106
127
  : headers
@@ -133,34 +154,44 @@ export async function handleEmailQueue(
133
154
  await updateSendStatus(db, recipient.trackingId, 'sent', {
134
155
  sentAt: new Date().toISOString(),
135
156
  })
136
- emitMailerAnalyticsEvent(options, env, 'newsletter_sent', {
137
- contentSlug: recipient.trackingId,
138
- label: {
139
- trackingId: recipient.trackingId,
140
- subscriberId: recipient.subscriberId,
141
- email: recipient.email,
142
- campaignId: message.body.campaignId,
143
- type,
144
- siteId: message.body.siteId,
157
+ emitMailerAnalyticsEvent(
158
+ analyticsOptions(options, effective, message.body.siteId),
159
+ env,
160
+ 'newsletter_sent',
161
+ {
162
+ contentSlug: recipient.trackingId,
163
+ label: {
164
+ trackingId: recipient.trackingId,
165
+ subscriberId: recipient.subscriberId,
166
+ email: recipient.email,
167
+ campaignId: message.body.campaignId,
168
+ type,
169
+ siteId: message.body.siteId,
170
+ },
145
171
  },
146
- })
172
+ )
147
173
  } else {
148
174
  await updateSendStatus(db, recipient.trackingId, 'bounced', {
149
175
  bouncedAt: new Date().toISOString(),
150
176
  bounceType: 'hard',
151
177
  })
152
- emitMailerAnalyticsEvent(options, env, 'newsletter_send_failed', {
153
- contentSlug: recipient.trackingId,
154
- label: {
155
- trackingId: recipient.trackingId,
156
- subscriberId: recipient.subscriberId,
157
- email: recipient.email,
158
- campaignId: message.body.campaignId,
159
- type,
160
- siteId: message.body.siteId,
161
- error: result.error,
178
+ emitMailerAnalyticsEvent(
179
+ analyticsOptions(options, effective, message.body.siteId),
180
+ env,
181
+ 'newsletter_send_failed',
182
+ {
183
+ contentSlug: recipient.trackingId,
184
+ label: {
185
+ trackingId: recipient.trackingId,
186
+ subscriberId: recipient.subscriberId,
187
+ email: recipient.email,
188
+ campaignId: message.body.campaignId,
189
+ type,
190
+ siteId: message.body.siteId,
191
+ error: result.error,
192
+ },
162
193
  },
163
- })
194
+ )
164
195
  console.error(`[mailer] Send failed for ${recipient.email}: ${result.error}`)
165
196
  }
166
197
  }
@@ -172,3 +203,19 @@ export async function handleEmailQueue(
172
203
  function formatFromHeader(senderName: string, fromAddress: string): string {
173
204
  return `${senderName} <${fromAddress}>`
174
205
  }
206
+
207
+ function analyticsOptions(
208
+ options: MailerConsumerOptions,
209
+ effective: EffectiveOptions,
210
+ siteId: string,
211
+ ): {
212
+ siteUrl: string
213
+ analyticsEnabled: boolean
214
+ analyticsBinding: string
215
+ } {
216
+ return {
217
+ siteUrl: effective.siteUrl ?? `https://${siteId}`,
218
+ analyticsEnabled: Boolean(options.analyticsBinding),
219
+ analyticsBinding: options.analyticsBinding ?? 'ANALYTICS',
220
+ }
221
+ }
package/src/types.ts CHANGED
@@ -52,12 +52,9 @@ export interface EmailQueueMessage {
52
52
  // ─── Realm-level multi-tenant config lookup ───
53
53
 
54
54
  /**
55
- * Per-site config override applied at consumer time. Returned from
56
- * SiteConfigLookup. All fields are optional only the ones present
57
- * will override the consumer's resolved options for that message.
58
- *
59
- * Bindings (d1Binding, queueBinding, senderBinding) and route paths
60
- * are NOT overridable per-site; they're realm-wide.
55
+ * Per-site config resolved at consumer time. Realm consumers keep bindings in
56
+ * their own Worker config and load sender / URL metadata from this object for
57
+ * every queued message.
61
58
  */
62
59
  export interface SiteMailerConfig {
63
60
  siteUrl?: string
@@ -77,8 +74,8 @@ export interface SiteMailerConfig {
77
74
 
78
75
  /**
79
76
  * Per-message lookup, called by the realm consumer with the message's
80
- * `siteId`. Returns the per-site config to apply, or `null` to skip the
81
- * override and use the consumer's options as-is.
77
+ * `siteId`. Returns the per-site config to apply, or `null` when the consumer
78
+ * should ack the message without sending because the registry entry is absent.
82
79
  */
83
80
  export type SiteConfigLookup = (
84
81
  siteId: string,
@@ -1,5 +1,3 @@
1
- import type { ResolvedMailerOptions } from '../options.js'
2
-
3
1
  export type MailerAnalyticsEvent =
4
2
  | 'newsletter_subscribed'
5
3
  | 'newsletter_confirmed'
@@ -25,6 +23,12 @@ interface AnalyticsContext {
25
23
  }
26
24
  }
27
25
 
26
+ export interface MailerAnalyticsRuntimeOptions {
27
+ siteUrl: string
28
+ analyticsEnabled: boolean
29
+ analyticsBinding: string
30
+ }
31
+
28
32
  interface EmitMailerAnalyticsOptions {
29
33
  request?: Request
30
34
  context?: AnalyticsContext
@@ -34,7 +38,7 @@ interface EmitMailerAnalyticsOptions {
34
38
  }
35
39
 
36
40
  export function emitMailerAnalyticsEvent(
37
- options: ResolvedMailerOptions,
41
+ options: MailerAnalyticsRuntimeOptions,
38
42
  bindingsEnv: Record<string, unknown>,
39
43
  eventName: MailerAnalyticsEvent,
40
44
  emitOptions: EmitMailerAnalyticsOptions = {},
@@ -56,7 +60,7 @@ export function emitMailerAnalyticsEvent(
56
60
  }
57
61
 
58
62
  export function buildMailerAnalyticsDataPoint(
59
- options: ResolvedMailerOptions,
63
+ options: MailerAnalyticsRuntimeOptions,
60
64
  eventName: MailerAnalyticsEvent,
61
65
  emitOptions: EmitMailerAnalyticsOptions = {},
62
66
  ): { blobs: string[]; doubles: number[]; indexes: string[] } {