mailery 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +162 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +162 -8
- package/dist/index.js.map +1 -1
- package/dist/{null-CfzvqNEp.d.cts → null-DDg3ojHe.d.cts} +16 -1
- package/dist/{null-CfzvqNEp.d.ts → null-DDg3ojHe.d.ts} +16 -1
- package/dist/testing.cjs +70 -7
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +70 -7
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-
|
|
2
|
-
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-
|
|
1
|
+
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-DDg3ojHe.cjs';
|
|
2
|
+
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-DDg3ojHe.cjs';
|
|
3
3
|
import { ObjectId, Db, Filter } from 'mongodb';
|
|
4
4
|
import { Request, Router } from 'express';
|
|
5
5
|
import Handlebars from 'handlebars';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-
|
|
2
|
-
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-
|
|
1
|
+
import { R as RunnerContext, N as NormalizedEvent, C as ContactAdapter, a as Contact, A as AdapterFilter, M as MailProvider, S as SendArgs, b as SendResult, c as MailTesterFeedback, d as Mailer, T as TemplateDoc, e as SuppressionScope, D as DeliveryWindow, F as FlowStep, f as SegmentFilter, P as Predicate } from './null-DDg3ojHe.js';
|
|
2
|
+
export { g as AuditLogDoc, B as BroadcastDoc, h as BroadcastStatus, i as CircuitBreakerThresholds, j as Collections, k as ContactTagDoc, E as EventDoc, l as FlowDoc, m as FlowGoal, n as FlowRunDoc, o as FlowRunStatus, p as FlowVersionDoc, H as HealthDoc, q as HealthStatus, L as LeadDoc, r as MailerConfig, s as NullProvider, O as OutboxDoc, t as RESERVED_VAR_KEYS, u as RedisOptions, v as SegmentDefinition, w as SendDoc, x as SendStatus, y as SenderDomainConfig, z as SenderDomainRegistry, G as SenderDomainValidation, I as SubscriptionDoc, J as SubscriptionStatus, K as SuppressionDoc, Q as SuppressionReason, U as TemplateKind, V as TemplateVersionDoc, W as VarsAdapter, X as VarsResolveInfo, Y as WebhookEventDoc, Z as defineVars, _ as ensureIndexes, $ as getCollections, a0 as validateSenderDomain, a1 as varsJsonSchema } from './null-DDg3ojHe.js';
|
|
3
3
|
import { ObjectId, Db, Filter } from 'mongodb';
|
|
4
4
|
import { Request, Router } from 'express';
|
|
5
5
|
import Handlebars from 'handlebars';
|
package/dist/index.js
CHANGED
|
@@ -1051,6 +1051,9 @@ var QUEUE_NAMES2 = {
|
|
|
1051
1051
|
send: "mailer-send",
|
|
1052
1052
|
webhook: "mailer-webhook"
|
|
1053
1053
|
};
|
|
1054
|
+
var DEFAULT_COLLECTION = "_mailerJobs";
|
|
1055
|
+
var DEFAULT_FAILED_RETENTION_DAYS = 7;
|
|
1056
|
+
var FAILED_SWEEP_INTERVAL_MS = 60 * 60 * 1e3;
|
|
1054
1057
|
var AgendaDriver = class _AgendaDriver {
|
|
1055
1058
|
queues;
|
|
1056
1059
|
agenda;
|
|
@@ -1068,7 +1071,7 @@ var AgendaDriver = class _AgendaDriver {
|
|
|
1068
1071
|
"mailery: queue driver 'agenda' requires the 'agenda' and '@agendajs/mongo-backend' peer dependencies. Run `npm install agenda @agendajs/mongo-backend bottleneck`."
|
|
1069
1072
|
);
|
|
1070
1073
|
}
|
|
1071
|
-
const collectionName = opts.collectionName ??
|
|
1074
|
+
const collectionName = opts.collectionName ?? collectionFor(opts.prefix);
|
|
1072
1075
|
const backend = new backendMod.MongoBackend({
|
|
1073
1076
|
mongo: opts.db,
|
|
1074
1077
|
collection: collectionName
|
|
@@ -1078,17 +1081,29 @@ var AgendaDriver = class _AgendaDriver {
|
|
|
1078
1081
|
processEvery: `${opts.processEverySeconds ?? 5} seconds`,
|
|
1079
1082
|
defaultLockLifetime: (opts.lockLifetimeSeconds ?? 10 * 60) * 1e3,
|
|
1080
1083
|
maxConcurrency: 50,
|
|
1081
|
-
defaultConcurrency: 5
|
|
1084
|
+
defaultConcurrency: 5,
|
|
1085
|
+
// Drop succeeded one-shot jobs instead of retaining them forever.
|
|
1086
|
+
// Agenda guards this on `!nextRunAt`, so repeating jobs survive.
|
|
1087
|
+
removeOnComplete: true
|
|
1082
1088
|
});
|
|
1083
|
-
|
|
1089
|
+
const retentionDays = opts.failedJobRetentionDays ?? DEFAULT_FAILED_RETENTION_DAYS;
|
|
1090
|
+
try {
|
|
1091
|
+
await opts.db.collection(collectionName).createIndex({ failedAt: 1 }, { sparse: true });
|
|
1092
|
+
} catch (err) {
|
|
1093
|
+
console.error("mailery: could not index the Agenda jobs collection on failedAt", err);
|
|
1094
|
+
}
|
|
1095
|
+
return new _AgendaDriver(agenda, agendaMod, opts.db, collectionName, retentionDays);
|
|
1084
1096
|
}
|
|
1085
1097
|
db;
|
|
1086
1098
|
collName;
|
|
1087
|
-
|
|
1099
|
+
failedRetentionDays;
|
|
1100
|
+
sweepTimer = null;
|
|
1101
|
+
constructor(agenda, agendaMod, db, collectionName, failedRetentionDays) {
|
|
1088
1102
|
this.agenda = agenda;
|
|
1089
1103
|
this.agendaMod = agendaMod;
|
|
1090
1104
|
this.db = db;
|
|
1091
1105
|
this.collName = collectionName;
|
|
1106
|
+
this.failedRetentionDays = failedRetentionDays;
|
|
1092
1107
|
this.queues = {
|
|
1093
1108
|
tick: this.makeQueueAPI(QUEUE_NAMES2.tick),
|
|
1094
1109
|
advance: this.makeQueueAPI(QUEUE_NAMES2.advance),
|
|
@@ -1169,9 +1184,45 @@ var AgendaDriver = class _AgendaDriver {
|
|
|
1169
1184
|
if (!this.started) {
|
|
1170
1185
|
await this.agenda.start();
|
|
1171
1186
|
this.started = true;
|
|
1187
|
+
this.startFailedJobSweep();
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Agenda's auto-remove only fires on success, so failed documents would
|
|
1192
|
+
* otherwise be retained forever. Runs once on worker start, then hourly.
|
|
1193
|
+
*/
|
|
1194
|
+
startFailedJobSweep() {
|
|
1195
|
+
if (this.failedRetentionDays <= 0 || this.sweepTimer) return;
|
|
1196
|
+
void this.sweepFailedJobs();
|
|
1197
|
+
this.sweepTimer = setInterval(() => void this.sweepFailedJobs(), FAILED_SWEEP_INTERVAL_MS);
|
|
1198
|
+
this.sweepTimer.unref?.();
|
|
1199
|
+
}
|
|
1200
|
+
/** Delete failed, fully-retired job documents older than the retention window. */
|
|
1201
|
+
async sweepFailedJobs() {
|
|
1202
|
+
const cutoff = new Date(Date.now() - this.failedRetentionDays * 24 * 3600 * 1e3);
|
|
1203
|
+
try {
|
|
1204
|
+
const res = await this.jobsCollection().deleteMany({
|
|
1205
|
+
failedAt: { $lt: cutoff },
|
|
1206
|
+
// Never touch the repeating tick.
|
|
1207
|
+
repeatInterval: { $in: [null, void 0] },
|
|
1208
|
+
// Leave anything still scheduled for a retry, and anything a worker
|
|
1209
|
+
// currently holds a lock on.
|
|
1210
|
+
$and: [
|
|
1211
|
+
{ $or: [{ nextRunAt: null }, { nextRunAt: { $exists: false } }, { nextRunAt: { $lt: cutoff } }] },
|
|
1212
|
+
{ $or: [{ lockedAt: null }, { lockedAt: { $exists: false } }, { lockedAt: { $lt: cutoff } }] }
|
|
1213
|
+
]
|
|
1214
|
+
});
|
|
1215
|
+
return res.deletedCount ?? 0;
|
|
1216
|
+
} catch (err) {
|
|
1217
|
+
console.error("mailery: failed-job sweep failed", err);
|
|
1218
|
+
return 0;
|
|
1172
1219
|
}
|
|
1173
1220
|
}
|
|
1174
1221
|
async stopWorkers() {
|
|
1222
|
+
if (this.sweepTimer) {
|
|
1223
|
+
clearInterval(this.sweepTimer);
|
|
1224
|
+
this.sweepTimer = null;
|
|
1225
|
+
}
|
|
1175
1226
|
if (!this.started) return;
|
|
1176
1227
|
await this.agenda.stop();
|
|
1177
1228
|
this.started = false;
|
|
@@ -1185,6 +1236,15 @@ var AgendaDriver = class _AgendaDriver {
|
|
|
1185
1236
|
await this.stopWorkers();
|
|
1186
1237
|
}
|
|
1187
1238
|
};
|
|
1239
|
+
function collectionFor(prefix) {
|
|
1240
|
+
if (!prefix) return DEFAULT_COLLECTION;
|
|
1241
|
+
if (!/^[A-Za-z0-9_-]+$/.test(prefix)) {
|
|
1242
|
+
throw new Error(
|
|
1243
|
+
`mailery: queue prefix "${prefix}" must contain only letters, digits, '_' or '-' \u2014 it becomes part of a MongoDB collection name.`
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
return `${DEFAULT_COLLECTION}_${prefix}`;
|
|
1247
|
+
}
|
|
1188
1248
|
|
|
1189
1249
|
// src/server/queues/noop.ts
|
|
1190
1250
|
function noopQueueAPI() {
|
|
@@ -1221,7 +1281,9 @@ async function createQueueDriver(config, fallbackDb) {
|
|
|
1221
1281
|
db: config.db ?? fallbackDb,
|
|
1222
1282
|
processEverySeconds: config.processEverySeconds,
|
|
1223
1283
|
lockLifetimeSeconds: config.lockLifetimeSeconds,
|
|
1224
|
-
collectionName: config.collectionName
|
|
1284
|
+
collectionName: config.collectionName,
|
|
1285
|
+
prefix: config.prefix,
|
|
1286
|
+
failedJobRetentionDays: config.failedJobRetentionDays
|
|
1225
1287
|
});
|
|
1226
1288
|
case "noop":
|
|
1227
1289
|
return new NoopDriver();
|
|
@@ -3977,7 +4039,8 @@ var Mailer = class _Mailer {
|
|
|
3977
4039
|
* MAILER_MONGODB_URI — Mongo connection string (required)
|
|
3978
4040
|
* MAILER_MONGODB_DB — database name (optional; defaults to the URI default)
|
|
3979
4041
|
* MAILER_REDIS_URL — Redis connection URL (required)
|
|
3980
|
-
* MAILER_QUEUE_PREFIX —
|
|
4042
|
+
* MAILER_QUEUE_PREFIX — namespaces this instance (optional). Bull: Redis key
|
|
4043
|
+
* prefix. Agenda: jobs collection suffix.
|
|
3981
4044
|
* MAILER_PUBLIC_URL — base for tracking/unsub URLs (required)
|
|
3982
4045
|
* MAILER_UNSUBSCRIBE_SECRET — HMAC key (required)
|
|
3983
4046
|
* MAILER_SENDER_ADDRESS — postal address for CAN-SPAM (optional)
|
|
@@ -4026,7 +4089,7 @@ var Mailer = class _Mailer {
|
|
|
4026
4089
|
}
|
|
4027
4090
|
const defaultProvider = env.MAILER_DEFAULT_PROVIDER ?? Object.keys(providers)[0];
|
|
4028
4091
|
const driverEnv = env.MAILER_QUEUE_DRIVER ?? "bull";
|
|
4029
|
-
const queue = driverEnv === "agenda" ? { driver: "agenda" } : driverEnv === "noop" ? { driver: "noop" } : {
|
|
4092
|
+
const queue = driverEnv === "agenda" ? { driver: "agenda", prefix: env.MAILER_QUEUE_PREFIX } : driverEnv === "noop" ? { driver: "noop" } : {
|
|
4030
4093
|
driver: "bull",
|
|
4031
4094
|
redis: { url: required("MAILER_REDIS_URL") },
|
|
4032
4095
|
prefix: env.MAILER_QUEUE_PREFIX
|
|
@@ -4691,6 +4754,40 @@ ${input.plainText}`);
|
|
|
4691
4754
|
});
|
|
4692
4755
|
}
|
|
4693
4756
|
}
|
|
4757
|
+
const offDomain = findOffDomainLinkHosts(input.html, input.fromEmail);
|
|
4758
|
+
if (offDomain.majority && offDomain.hosts.length > 0) {
|
|
4759
|
+
issues.push({
|
|
4760
|
+
rule: "offdomain_links",
|
|
4761
|
+
severity: "warning",
|
|
4762
|
+
message: `Most links point away from the From domain: ${offDomain.hosts.join(", ")}.`,
|
|
4763
|
+
hint: "Link domains that match the sending domain build reputation. Route links through your own domain (or a tracking subdomain of it) where you can."
|
|
4764
|
+
});
|
|
4765
|
+
}
|
|
4766
|
+
const insecure = findInsecureLinkHosts(input.html);
|
|
4767
|
+
if (insecure.length > 0) {
|
|
4768
|
+
issues.push({
|
|
4769
|
+
rule: "insecure_link",
|
|
4770
|
+
severity: "warning",
|
|
4771
|
+
message: `Link uses plain http://: ${insecure.join(", ")}.`,
|
|
4772
|
+
hint: "Mixed-content links get rewritten or warned about by some clients, and http:// correlates with stale spam templates. Use https://."
|
|
4773
|
+
});
|
|
4774
|
+
}
|
|
4775
|
+
if (countImagesMissingAlt(input.html) > 0) {
|
|
4776
|
+
issues.push({
|
|
4777
|
+
rule: "image_missing_alt",
|
|
4778
|
+
severity: "warning",
|
|
4779
|
+
message: "One or more images have no alt text.",
|
|
4780
|
+
hint: "Most clients block images by default on first open. Alt text is what the recipient actually sees, and screen readers need it."
|
|
4781
|
+
});
|
|
4782
|
+
}
|
|
4783
|
+
if (hasImageOnlyLink(input.html)) {
|
|
4784
|
+
issues.push({
|
|
4785
|
+
rule: "image_only_link",
|
|
4786
|
+
severity: "warning",
|
|
4787
|
+
message: "A link wraps an image with no accompanying text.",
|
|
4788
|
+
hint: "With images blocked, an image-only call-to-action is invisible and unclickable. Add a text label inside the link."
|
|
4789
|
+
});
|
|
4790
|
+
}
|
|
4694
4791
|
const linkCount = countMatches(input.html, /<a\s[^>]*\bhref\s*=/gi);
|
|
4695
4792
|
if (linkCount > 10) {
|
|
4696
4793
|
issues.push({
|
|
@@ -4745,6 +4842,63 @@ function hasBareUrlInVisibleText(html) {
|
|
|
4745
4842
|
const stripped = html.replace(/<a\b[^>]*>.*?<\/a>/gis, " ").replace(/<style\b[^>]*>.*?<\/style>/gis, " ").replace(/<script\b[^>]*>.*?<\/script>/gis, " ").replace(/<head\b[^>]*>.*?<\/head>/gis, " ");
|
|
4746
4843
|
return /https?:\/\/[^\s<>"']+/i.test(stripped);
|
|
4747
4844
|
}
|
|
4845
|
+
function findOffDomainLinkHosts(html, fromEmail) {
|
|
4846
|
+
const fromDomain = fromEmail.split("@")[1]?.toLowerCase();
|
|
4847
|
+
if (!fromDomain) return { hosts: [], majority: false };
|
|
4848
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
4849
|
+
let total = 0;
|
|
4850
|
+
let off = 0;
|
|
4851
|
+
for (const href of extractHrefs(html)) {
|
|
4852
|
+
if (href.includes("{{")) continue;
|
|
4853
|
+
const host = hostnameOf(href);
|
|
4854
|
+
if (!host) continue;
|
|
4855
|
+
total++;
|
|
4856
|
+
if (sameSite(host, fromDomain)) continue;
|
|
4857
|
+
off++;
|
|
4858
|
+
hosts.add(host);
|
|
4859
|
+
}
|
|
4860
|
+
return { hosts: Array.from(hosts), majority: total > 0 && off * 2 > total };
|
|
4861
|
+
}
|
|
4862
|
+
function sameSite(a, b) {
|
|
4863
|
+
if (a === b) return true;
|
|
4864
|
+
if (a.endsWith(`.${b}`) || b.endsWith(`.${a}`)) return true;
|
|
4865
|
+
return lastLabels(a) === lastLabels(b);
|
|
4866
|
+
}
|
|
4867
|
+
function lastLabels(host) {
|
|
4868
|
+
return host.split(".").slice(-2).join(".");
|
|
4869
|
+
}
|
|
4870
|
+
function findInsecureLinkHosts(html) {
|
|
4871
|
+
const hits = /* @__PURE__ */ new Set();
|
|
4872
|
+
for (const href of extractHrefs(html)) {
|
|
4873
|
+
if (!/^http:\/\//i.test(href)) continue;
|
|
4874
|
+
const host = hostnameOf(href);
|
|
4875
|
+
if (host) hits.add(host);
|
|
4876
|
+
}
|
|
4877
|
+
return Array.from(hits);
|
|
4878
|
+
}
|
|
4879
|
+
function countImagesMissingAlt(html) {
|
|
4880
|
+
let missing = 0;
|
|
4881
|
+
const re = /<img\b[^>]*>/gi;
|
|
4882
|
+
let m;
|
|
4883
|
+
while (m = re.exec(html)) {
|
|
4884
|
+
const tag = m[0];
|
|
4885
|
+
const alt = /\balt\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i.exec(tag);
|
|
4886
|
+
const value = alt ? alt[1] ?? alt[2] ?? alt[3] ?? "" : "";
|
|
4887
|
+
if (value.trim().length === 0) missing++;
|
|
4888
|
+
}
|
|
4889
|
+
return missing;
|
|
4890
|
+
}
|
|
4891
|
+
function hasImageOnlyLink(html) {
|
|
4892
|
+
const re = /<a\b[^>]*>(.*?)<\/a>/gis;
|
|
4893
|
+
let m;
|
|
4894
|
+
while (m = re.exec(html)) {
|
|
4895
|
+
const inner = m[1];
|
|
4896
|
+
if (!/<img\b/i.test(inner)) continue;
|
|
4897
|
+
const text = inner.replace(/<[^>]*>/g, "").replace(/ /gi, " ").trim();
|
|
4898
|
+
if (text.length === 0) return true;
|
|
4899
|
+
}
|
|
4900
|
+
return false;
|
|
4901
|
+
}
|
|
4748
4902
|
function findSpamSignals(text) {
|
|
4749
4903
|
const out = /* @__PURE__ */ new Set();
|
|
4750
4904
|
for (const { pattern, phrase } of SPAM_PHRASES) {
|
|
@@ -7608,7 +7762,7 @@ var DEDUPE_POLICIES = [
|
|
|
7608
7762
|
];
|
|
7609
7763
|
|
|
7610
7764
|
// src/server/index.ts
|
|
7611
|
-
var VERSION = "0.
|
|
7765
|
+
var VERSION = "0.12.1" ;
|
|
7612
7766
|
|
|
7613
7767
|
export { DEDUPE_POLICIES, FLOW_STEP_KINDS, Mailer, MongoContactAdapter, NullProvider, PREDICATE_KINDS, RESERVED_VAR_KEYS, SEGMENT_FILTER_KINDS, SendGridProvider, VERSION, applyTracking, applyWebhookEvent, compileMailyTemplate, compileTemplate, computeDeliveryTime, createAdminRouter, createPublicRouter, defaultFlowStep, defaultPredicate, defaultSegmentFilter, defineVars, derivePlaintext, dispatchSend, ensureIndexes, getCollections, predicateKind, processNewlyFiredEventTriggers, processOneRunStep, renderTemplate, runTick, sha256Hex, signUnsubscribeToken, sweepStrandedFlowRuns, validateSenderDomain, varsJsonSchema, verifyUnsubscribeToken };
|
|
7614
7768
|
//# sourceMappingURL=index.js.map
|