@marlinjai/mail-contract 0.10.0 → 0.11.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/dist/index.d.mts +2345 -987
- package/dist/index.d.ts +2345 -987
- package/dist/index.js +900 -640
- package/dist/index.mjs +878 -640
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -209,6 +209,7 @@ __export(index_exports, {
|
|
|
209
209
|
InviteListQuery: () => InviteListQuery,
|
|
210
210
|
InviteStatus: () => InviteStatus,
|
|
211
211
|
JsonValue: () => JsonValue,
|
|
212
|
+
LETTER_ONLY_MERGE_FIELDS: () => LETTER_ONLY_MERGE_FIELDS,
|
|
212
213
|
LETTER_RECIPIENT_REFUSAL: () => LETTER_RECIPIENT_REFUSAL,
|
|
213
214
|
LIST_UNSUBSCRIBE_POST_VALUE: () => LIST_UNSUBSCRIBE_POST_VALUE,
|
|
214
215
|
LOCALE_TAG_PATTERN: () => LOCALE_TAG_PATTERN,
|
|
@@ -277,7 +278,10 @@ __export(index_exports, {
|
|
|
277
278
|
MailingLanguageReport: () => MailingLanguageReport,
|
|
278
279
|
MailingLanguageStatus: () => MailingLanguageStatus,
|
|
279
280
|
MailingListQuery: () => MailingListQuery,
|
|
281
|
+
MailingMerge: () => MailingMerge,
|
|
280
282
|
MailingMetadata: () => MailingMetadata,
|
|
283
|
+
MailingResolveRequest: () => MailingResolveRequest,
|
|
284
|
+
MailingResolveResult: () => MailingResolveResult,
|
|
281
285
|
MailingRetryFailedRequest: () => MailingRetryFailedRequest,
|
|
282
286
|
MailingScheduleFailedData: () => MailingScheduleFailedData,
|
|
283
287
|
MailingScheduleRequest: () => MailingScheduleRequest,
|
|
@@ -302,6 +306,8 @@ __export(index_exports, {
|
|
|
302
306
|
MessageOutcome: () => MessageOutcome,
|
|
303
307
|
MessageSentData: () => MessageSentData,
|
|
304
308
|
MessageSummary: () => MessageSummary,
|
|
309
|
+
MessageValues: () => MessageValues,
|
|
310
|
+
NAME_ON_BROADCAST_REFUSAL: () => NAME_ON_BROADCAST_REFUSAL,
|
|
305
311
|
NotifyRecipients: () => NotifyRecipients,
|
|
306
312
|
NotifyStep: () => NotifyStep,
|
|
307
313
|
ON_BEHALF_OF_HEADER: () => ON_BEHALF_OF_HEADER,
|
|
@@ -337,6 +343,8 @@ __export(index_exports, {
|
|
|
337
343
|
REQUEST_ID_HEADER: () => REQUEST_ID_HEADER,
|
|
338
344
|
RESEND_EVENT_TYPES: () => RESEND_EVENT_TYPES,
|
|
339
345
|
RESERVED_MERGE_FIELDS: () => RESERVED_MERGE_FIELDS,
|
|
346
|
+
RESOLVE_PROBLEMS: () => RESOLVE_PROBLEMS,
|
|
347
|
+
RESOLVE_REJECTIONS: () => RESOLVE_REJECTIONS,
|
|
340
348
|
RETRYABLE_ERRORS: () => RETRYABLE_ERRORS,
|
|
341
349
|
RETRY_AFTER_HEADER: () => RETRY_AFTER_HEADER,
|
|
342
350
|
RE_ENTRY_MODES: () => RE_ENTRY_MODES,
|
|
@@ -349,6 +357,9 @@ __export(index_exports, {
|
|
|
349
357
|
RecipientStatus: () => RecipientStatus,
|
|
350
358
|
RemoteImage: () => RemoteImage,
|
|
351
359
|
ResendSigningSecret: () => ResendSigningSecret,
|
|
360
|
+
ResolveProblem: () => ResolveProblem,
|
|
361
|
+
ResolvedRecipient: () => ResolvedRecipient,
|
|
362
|
+
ResolvedValue: () => ResolvedValue,
|
|
352
363
|
SERVICE_FILLED_MERGE_FIELDS: () => SERVICE_FILLED_MERGE_FIELDS,
|
|
353
364
|
SIGNUP_FORM_FIELDS: () => SIGNUP_FORM_FIELDS,
|
|
354
365
|
SKIP_REASONS: () => SKIP_REASONS,
|
|
@@ -435,10 +446,13 @@ __export(index_exports, {
|
|
|
435
446
|
USAGE_METRICS: () => USAGE_METRICS,
|
|
436
447
|
USAGE_WARNING_HEADER: () => USAGE_WARNING_HEADER,
|
|
437
448
|
USAGE_WARNING_RATIO: () => USAGE_WARNING_RATIO,
|
|
449
|
+
UnfilledLink: () => UnfilledLink,
|
|
438
450
|
Usage: () => Usage,
|
|
439
451
|
UsageMetric: () => UsageMetric,
|
|
440
452
|
UsageWarning: () => UsageWarning,
|
|
453
|
+
VALUE_LAYERS: () => VALUE_LAYERS,
|
|
441
454
|
ValidationIssue: () => ValidationIssue,
|
|
455
|
+
ValueLayer: () => ValueLayer,
|
|
442
456
|
VariantAnalytics: () => VariantAnalytics,
|
|
443
457
|
WEBHOOK_DELIVERY_STATUSES: () => WEBHOOK_DELIVERY_STATUSES,
|
|
444
458
|
WEBHOOK_EVENT_ID_HEADER: () => WEBHOOK_EVENT_ID_HEADER,
|
|
@@ -502,6 +516,7 @@ __export(index_exports, {
|
|
|
502
516
|
editMainInsertions: () => editMainInsertions,
|
|
503
517
|
effectivePreviewPicks: () => effectivePreviewPicks,
|
|
504
518
|
emptyFlow: () => emptyFlow,
|
|
519
|
+
emptyLinkValues: () => emptyLinkValues,
|
|
505
520
|
errorBody: () => errorBody,
|
|
506
521
|
escapeMergeHtml: () => escapeMergeHtml,
|
|
507
522
|
exportFilename: () => exportFilename,
|
|
@@ -532,6 +547,8 @@ __export(index_exports, {
|
|
|
532
547
|
languageInsertions: () => languageInsertions,
|
|
533
548
|
languageName: () => languageName,
|
|
534
549
|
languageTabs: () => languageTabs,
|
|
550
|
+
letterOnlyValues: () => letterOnlyValues,
|
|
551
|
+
linkTokens: () => linkTokens,
|
|
535
552
|
mainInsertionText: () => mainInsertionText,
|
|
536
553
|
matchLocale: () => matchLocale,
|
|
537
554
|
matchRoute: () => matchRoute,
|
|
@@ -552,6 +569,8 @@ __export(index_exports, {
|
|
|
552
569
|
previewInsertions: () => previewInsertions,
|
|
553
570
|
previewPersonalization: () => previewPersonalization,
|
|
554
571
|
primaryLanguage: () => primaryLanguage,
|
|
572
|
+
printedFields: () => printedFields,
|
|
573
|
+
rawMergeValue: () => rawMergeValue,
|
|
555
574
|
reachable: () => reachable,
|
|
556
575
|
readyWithoutInsertions: () => readyWithoutInsertions,
|
|
557
576
|
readyWithoutSubject: () => readyWithoutSubject,
|
|
@@ -568,6 +587,7 @@ __export(index_exports, {
|
|
|
568
587
|
renameTokenInDocument: () => renameTokenInDocument,
|
|
569
588
|
renameTokenInText: () => renameTokenInText,
|
|
570
589
|
resolveInsertions: () => resolveInsertions,
|
|
590
|
+
resolveValue: () => resolveValue,
|
|
571
591
|
restorePatch: () => restorePatch,
|
|
572
592
|
routes: () => routes,
|
|
573
593
|
sameJson: () => sameJson,
|
|
@@ -594,6 +614,8 @@ __export(index_exports, {
|
|
|
594
614
|
unknownRefusedInsertions: () => unknownRefusedInsertions,
|
|
595
615
|
unplacedInsertions: () => unplacedInsertions,
|
|
596
616
|
validateAutomation: () => validateAutomation,
|
|
617
|
+
valueNames: () => valueNames,
|
|
618
|
+
valuesRead: () => valuesRead,
|
|
597
619
|
verifyWebhook: () => verifyWebhook
|
|
598
620
|
});
|
|
599
621
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -677,6 +699,12 @@ var ERROR_STATUS = {
|
|
|
677
699
|
invalid_mjml: 422,
|
|
678
700
|
missing_unsubscribe_url: 422,
|
|
679
701
|
mailing_not_ready: 422,
|
|
702
|
+
/**
|
|
703
|
+
* A value placed inside a link's address comes out empty for at least one
|
|
704
|
+
* recipient, so the mailing does not start; `details.values` lists each such
|
|
705
|
+
* value with how many recipients it is empty for.
|
|
706
|
+
*/
|
|
707
|
+
unfilled_link: 422,
|
|
680
708
|
unknown_topic: 422,
|
|
681
709
|
unknown_provider: 422,
|
|
682
710
|
/**
|
|
@@ -745,10 +773,10 @@ var API_VERSION_PREFIX = "/v1";
|
|
|
745
773
|
var HEALTH_PATH = "/healthz";
|
|
746
774
|
|
|
747
775
|
// src/workspace.ts
|
|
748
|
-
var
|
|
776
|
+
var import_zod11 = require("zod");
|
|
749
777
|
|
|
750
778
|
// src/automations.ts
|
|
751
|
-
var
|
|
779
|
+
var import_zod10 = require("zod");
|
|
752
780
|
|
|
753
781
|
// src/templates.ts
|
|
754
782
|
var import_zod5 = require("zod");
|
|
@@ -769,11 +797,11 @@ var RESERVED_MERGE_FIELDS = {
|
|
|
769
797
|
};
|
|
770
798
|
var MERGE_FIELD_PATTERN = /\{\{\s*([a-z][a-z0-9_]*)\s*(?:\|([^}]*))?\}\}/g;
|
|
771
799
|
function findMergeFields(html) {
|
|
772
|
-
const
|
|
800
|
+
const uses2 = [];
|
|
773
801
|
for (const match of html.matchAll(MERGE_FIELD_PATTERN)) {
|
|
774
|
-
|
|
802
|
+
uses2.push({ name: match[1], fallback: match[2] === void 0 ? null : match[2].trim() });
|
|
775
803
|
}
|
|
776
|
-
return
|
|
804
|
+
return uses2;
|
|
777
805
|
}
|
|
778
806
|
function missingRequiredMergeFields(html) {
|
|
779
807
|
const used = new Set(findMergeFields(html).map((u) => u.name));
|
|
@@ -1456,10 +1484,10 @@ function exportFilename(name, format) {
|
|
|
1456
1484
|
}
|
|
1457
1485
|
|
|
1458
1486
|
// src/platform.ts
|
|
1459
|
-
var
|
|
1487
|
+
var import_zod9 = require("zod");
|
|
1460
1488
|
|
|
1461
1489
|
// src/mailings.ts
|
|
1462
|
-
var
|
|
1490
|
+
var import_zod8 = require("zod");
|
|
1463
1491
|
|
|
1464
1492
|
// src/ab-test.ts
|
|
1465
1493
|
var import_zod6 = require("zod");
|
|
@@ -1510,6 +1538,167 @@ function testGroupSize(total, fraction, variants) {
|
|
|
1510
1538
|
return Math.min(total, Math.max(variants, Math.ceil(total * fraction)));
|
|
1511
1539
|
}
|
|
1512
1540
|
|
|
1541
|
+
// src/values.ts
|
|
1542
|
+
var import_zod7 = require("zod");
|
|
1543
|
+
var MAX_MERGE_DEFAULTS = 50;
|
|
1544
|
+
var MAX_MERGE_DEFAULT_LENGTH = 2e3;
|
|
1545
|
+
var MergeFieldName = import_zod7.z.string().regex(/^[a-z][a-z0-9_]*$/, "a merge-field name: lowercase letters, digits and underscores, starting with a letter").max(64);
|
|
1546
|
+
var MergeDefaultValue = import_zod7.z.union([import_zod7.z.string().max(MAX_MERGE_DEFAULT_LENGTH), import_zod7.z.number().finite(), import_zod7.z.boolean()]);
|
|
1547
|
+
var MailingMerge = import_zod7.z.record(MergeFieldName, MergeDefaultValue).refine((m) => Object.keys(m).length <= MAX_MERGE_DEFAULTS, `at most ${MAX_MERGE_DEFAULTS} values on a mailing`).refine((m) => !Object.keys(m).some((k) => SERVICE_FILLED_MERGE_FIELDS.includes(k)), {
|
|
1548
|
+
message: `the service fills ${SERVICE_FILLED_MERGE_FIELDS.join(" and ")}; a mailing cannot set them`
|
|
1549
|
+
});
|
|
1550
|
+
var LETTER_ONLY_MERGE_FIELDS = ["first_name", "last_name"];
|
|
1551
|
+
var NAME_ON_BROADCAST_REFUSAL = "name_on_broadcast";
|
|
1552
|
+
function letterOnlyValues(merge) {
|
|
1553
|
+
return LETTER_ONLY_MERGE_FIELDS.filter((name) => ownEntry(merge, name) !== void 0);
|
|
1554
|
+
}
|
|
1555
|
+
var VALUE_LAYERS = ["recipient", "mailing", "contact", "workspace", "fallback", "empty"];
|
|
1556
|
+
var ValueLayer = import_zod7.z.enum(VALUE_LAYERS);
|
|
1557
|
+
var ResolvedValue = import_zod7.z.object({ text: import_zod7.z.string(), layer: ValueLayer });
|
|
1558
|
+
var MessageValues = import_zod7.z.record(ResolvedValue);
|
|
1559
|
+
function scalarText(value) {
|
|
1560
|
+
if (typeof value === "string") return value;
|
|
1561
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
1562
|
+
if (typeof value === "boolean") return String(value);
|
|
1563
|
+
return null;
|
|
1564
|
+
}
|
|
1565
|
+
function isNameField(name) {
|
|
1566
|
+
return name === "first_name" || name === "last_name";
|
|
1567
|
+
}
|
|
1568
|
+
function rawMergeValue(name, sources) {
|
|
1569
|
+
const own = ownEntry(sources.recipient, name);
|
|
1570
|
+
if (scalarText(own) !== null) return { value: own, layer: "recipient" };
|
|
1571
|
+
const held = ownEntry(sources.mailing, name);
|
|
1572
|
+
if (scalarText(held) !== null) return { value: held, layer: "mailing" };
|
|
1573
|
+
if (isNameField(name)) {
|
|
1574
|
+
const stored = sources.contact?.[name];
|
|
1575
|
+
return typeof stored === "string" ? { value: stored, layer: "contact" } : null;
|
|
1576
|
+
}
|
|
1577
|
+
const property = ownEntry(sources.contact?.properties, name);
|
|
1578
|
+
if (scalarText(property) !== null) return { value: property, layer: "contact" };
|
|
1579
|
+
const byDefault = ownEntry(sources.workspace, name);
|
|
1580
|
+
return scalarText(byDefault) !== null ? { value: byDefault, layer: "workspace" } : null;
|
|
1581
|
+
}
|
|
1582
|
+
function resolveValue(name, fallback, sources) {
|
|
1583
|
+
const found = rawMergeValue(name, sources);
|
|
1584
|
+
const text = found === null ? null : scalarText(found.value);
|
|
1585
|
+
if (found !== null && text !== null && text.trim() !== "") return { text, layer: found.layer };
|
|
1586
|
+
const instead = fallback?.trim() ?? "";
|
|
1587
|
+
return instead === "" ? { text: "", layer: "empty" } : { text: instead, layer: "fallback" };
|
|
1588
|
+
}
|
|
1589
|
+
function pattern2() {
|
|
1590
|
+
return new RegExp(MERGE_FIELD_PATTERN.source, "g");
|
|
1591
|
+
}
|
|
1592
|
+
function isServiceFilled(name) {
|
|
1593
|
+
return SERVICE_FILLED_MERGE_FIELDS.includes(name);
|
|
1594
|
+
}
|
|
1595
|
+
function uses(text) {
|
|
1596
|
+
return [...text.matchAll(pattern2())].map((m) => ({ name: m[1], fallback: m[2] === void 0 ? null : m[2].trim() }));
|
|
1597
|
+
}
|
|
1598
|
+
function valueNames(texts, insertions) {
|
|
1599
|
+
const names = [];
|
|
1600
|
+
const add = (name) => {
|
|
1601
|
+
if (!isServiceFilled(name) && !names.includes(name)) names.push(name);
|
|
1602
|
+
};
|
|
1603
|
+
for (const text of texts) {
|
|
1604
|
+
for (const use of uses(text ?? "")) {
|
|
1605
|
+
const def = ownEntry(insertions, use.name);
|
|
1606
|
+
if (!def) {
|
|
1607
|
+
add(use.name);
|
|
1608
|
+
continue;
|
|
1609
|
+
}
|
|
1610
|
+
add(def.by);
|
|
1611
|
+
for (const inner of [...Object.values(def.choices), def.filled ?? "", def.otherwise]) for (const u of uses(inner)) add(u.name);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
return names;
|
|
1615
|
+
}
|
|
1616
|
+
function printedFields(texts, insertions, chosen2) {
|
|
1617
|
+
const out = [];
|
|
1618
|
+
const add = (use) => {
|
|
1619
|
+
if (isServiceFilled(use.name)) return;
|
|
1620
|
+
if (!out.some((o) => o.name === use.name && o.fallback === use.fallback)) out.push(use);
|
|
1621
|
+
};
|
|
1622
|
+
for (const text of texts) {
|
|
1623
|
+
for (const use of uses(text ?? "")) {
|
|
1624
|
+
if (!ownEntry(insertions, use.name)) add(use);
|
|
1625
|
+
else for (const inner of uses(ownEntry(chosen2, use.name)?.text ?? "")) add(inner);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
return out;
|
|
1629
|
+
}
|
|
1630
|
+
function valuesRead(texts, insertions, chosen2, resolve) {
|
|
1631
|
+
const out = {};
|
|
1632
|
+
const read = (use) => {
|
|
1633
|
+
if (isServiceFilled(use.name)) return;
|
|
1634
|
+
const value = resolve(use.name, use.fallback);
|
|
1635
|
+
const seen = ownEntry(out, use.name);
|
|
1636
|
+
if (seen === void 0 || value.layer === "empty" && seen.layer !== "empty") out[use.name] = value;
|
|
1637
|
+
};
|
|
1638
|
+
for (const text of texts) {
|
|
1639
|
+
for (const use of uses(text ?? "")) {
|
|
1640
|
+
const def = ownEntry(insertions, use.name);
|
|
1641
|
+
if (!def) {
|
|
1642
|
+
read(use);
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
read({ name: def.by, fallback: null });
|
|
1646
|
+
for (const inner of uses(ownEntry(chosen2, use.name)?.text ?? "")) read(inner);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
return out;
|
|
1650
|
+
}
|
|
1651
|
+
var HREF = /\bhref\s*=\s*(?:"([^"]*)"|'([^']*)')/gi;
|
|
1652
|
+
function linkTokens(html) {
|
|
1653
|
+
const out = [];
|
|
1654
|
+
for (const match of html.matchAll(HREF)) {
|
|
1655
|
+
for (const use of uses(match[1] ?? match[2] ?? "")) {
|
|
1656
|
+
if (isServiceFilled(use.name)) continue;
|
|
1657
|
+
if (!out.some((o) => o.name === use.name && o.fallback === use.fallback)) out.push(use);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return out;
|
|
1661
|
+
}
|
|
1662
|
+
function emptyLinkValues(tokens, p) {
|
|
1663
|
+
const empty = [];
|
|
1664
|
+
for (const token of tokens) {
|
|
1665
|
+
const ins = ownEntry(p.insertions, token.name);
|
|
1666
|
+
const text = ins ? ins.text.replace(pattern2(), (_m, name, fallback) => p.value(name, fallback)) : p.value(token.name, token.fallback ?? void 0);
|
|
1667
|
+
if (text.trim() === "" && !empty.includes(token.name)) empty.push(token.name);
|
|
1668
|
+
}
|
|
1669
|
+
return empty;
|
|
1670
|
+
}
|
|
1671
|
+
var UnfilledLink = import_zod7.z.object({
|
|
1672
|
+
/** The value, or the insertion, that comes out empty. */
|
|
1673
|
+
value: import_zod7.z.string(),
|
|
1674
|
+
/** How many recipients it is empty for. */
|
|
1675
|
+
recipients: import_zod7.z.number().int().min(1)
|
|
1676
|
+
});
|
|
1677
|
+
var RESOLVE_PROBLEMS = ["unfilled_link", "empty_value", "insertion_miss"];
|
|
1678
|
+
var ResolveProblem = import_zod7.z.object({
|
|
1679
|
+
kind: import_zod7.z.enum(RESOLVE_PROBLEMS),
|
|
1680
|
+
severity: import_zod7.z.enum(["blocking", "note"]),
|
|
1681
|
+
value: import_zod7.z.string(),
|
|
1682
|
+
message: import_zod7.z.string()
|
|
1683
|
+
});
|
|
1684
|
+
var ResolvedRecipient = import_zod7.z.object({
|
|
1685
|
+
/** The recipient's index in the request; null for the reader with nothing of their own. */
|
|
1686
|
+
index: import_zod7.z.number().int().min(0).nullable(),
|
|
1687
|
+
/** The address the message would go to; null for the reader with nothing of their own. */
|
|
1688
|
+
email: Email.nullable(),
|
|
1689
|
+
/** The contact found for the recipient; null when the address has none yet (a send creates it, empty). */
|
|
1690
|
+
contact_id: Id.nullable(),
|
|
1691
|
+
/** The language version this recipient would get. */
|
|
1692
|
+
locale: LocaleTag,
|
|
1693
|
+
/** The subject line as they would read it. */
|
|
1694
|
+
subject: import_zod7.z.string(),
|
|
1695
|
+
values: MessageValues,
|
|
1696
|
+
/** The choice each insertion would make; null when the content has none. */
|
|
1697
|
+
insertions: InsertionChoices.nullable(),
|
|
1698
|
+
problems: import_zod7.z.array(ResolveProblem)
|
|
1699
|
+
});
|
|
1700
|
+
var RESOLVE_REJECTIONS = ["unknown_contact", "duplicate_in_batch"];
|
|
1701
|
+
|
|
1513
1702
|
// src/mailings.ts
|
|
1514
1703
|
var MAILING_STATUSES = [
|
|
1515
1704
|
"draft",
|
|
@@ -1520,9 +1709,9 @@ var MAILING_STATUSES = [
|
|
|
1520
1709
|
"partially_failed",
|
|
1521
1710
|
"cancelled"
|
|
1522
1711
|
];
|
|
1523
|
-
var MailingStatus =
|
|
1712
|
+
var MailingStatus = import_zod8.z.enum(MAILING_STATUSES);
|
|
1524
1713
|
var MAILING_ACTIONS = ["send", "schedule", "unschedule", "pause", "resume", "cancel", "retry-failed"];
|
|
1525
|
-
var MailingAction =
|
|
1714
|
+
var MailingAction = import_zod8.z.enum(MAILING_ACTIONS);
|
|
1526
1715
|
var MAILING_TRANSITIONS = {
|
|
1527
1716
|
draft: ["send", "schedule", "cancel"],
|
|
1528
1717
|
scheduled: ["send", "schedule", "unschedule", "cancel"],
|
|
@@ -1537,23 +1726,23 @@ function canTransition(status, action) {
|
|
|
1537
1726
|
}
|
|
1538
1727
|
var EDITABLE_MAILING_STATUSES = ["draft", "scheduled"];
|
|
1539
1728
|
var TERMINAL_MAILING_STATUSES = ["sent", "cancelled"];
|
|
1540
|
-
var MailingMetadata =
|
|
1541
|
-
var MailingCounts =
|
|
1542
|
-
total:
|
|
1543
|
-
queued:
|
|
1544
|
-
sending:
|
|
1545
|
-
sent:
|
|
1546
|
-
failed:
|
|
1547
|
-
skipped:
|
|
1729
|
+
var MailingMetadata = import_zod8.z.record(import_zod8.z.string().max(500)).refine((v) => Object.keys(v).length <= 20, "at most 20 keys").refine((v) => Object.keys(v).every((k) => k.length >= 1 && k.length <= 64), "keys are 1 to 64 characters");
|
|
1730
|
+
var MailingCounts = import_zod8.z.object({
|
|
1731
|
+
total: import_zod8.z.number().int().min(0),
|
|
1732
|
+
queued: import_zod8.z.number().int().min(0),
|
|
1733
|
+
sending: import_zod8.z.number().int().min(0),
|
|
1734
|
+
sent: import_zod8.z.number().int().min(0),
|
|
1735
|
+
failed: import_zod8.z.number().int().min(0),
|
|
1736
|
+
skipped: import_zod8.z.number().int().min(0)
|
|
1548
1737
|
});
|
|
1549
1738
|
var MAILING_KINDS = ["broadcast", "automation", "notification"];
|
|
1550
|
-
var MailingKind =
|
|
1551
|
-
var Mailing =
|
|
1739
|
+
var MailingKind = import_zod8.z.enum(MAILING_KINDS);
|
|
1740
|
+
var Mailing = import_zod8.z.object({
|
|
1552
1741
|
id: Id,
|
|
1553
1742
|
kind: MailingKind,
|
|
1554
|
-
name:
|
|
1555
|
-
subject:
|
|
1556
|
-
preheader:
|
|
1743
|
+
name: import_zod8.z.string().max(200).nullable(),
|
|
1744
|
+
subject: import_zod8.z.string().min(1).max(998),
|
|
1745
|
+
preheader: import_zod8.z.string().max(500).nullable(),
|
|
1557
1746
|
/**
|
|
1558
1747
|
* The template the document was taken from, if any. The snapshot is what is
|
|
1559
1748
|
* sent in the main language; the template's other language versions are
|
|
@@ -1595,6 +1784,12 @@ var Mailing = import_zod7.z.object({
|
|
|
1595
1784
|
status: MailingStatus,
|
|
1596
1785
|
counts: MailingCounts,
|
|
1597
1786
|
metadata: MailingMetadata,
|
|
1787
|
+
/**
|
|
1788
|
+
* The values held on this mailing (see `MailingMerge`): the same for
|
|
1789
|
+
* everyone who gets it, above the contact's stored name and properties and
|
|
1790
|
+
* the workspace's defaults, below the recipient's own. Empty by default.
|
|
1791
|
+
*/
|
|
1792
|
+
merge: MailingMerge.default({}),
|
|
1598
1793
|
scheduled_at: Timestamp.nullable(),
|
|
1599
1794
|
/** The A/B test on subject or content (S4), null when there is none. */
|
|
1600
1795
|
ab_test: AbTestState.nullable(),
|
|
@@ -1606,15 +1801,15 @@ var Mailing = import_zod7.z.object({
|
|
|
1606
1801
|
* recipients refused as dead addresses in one run (see the provider's
|
|
1607
1802
|
* `rejections.anomaly`). Resuming clears it and starts a new run.
|
|
1608
1803
|
*/
|
|
1609
|
-
pause_reason:
|
|
1804
|
+
pause_reason: import_zod8.z.string().nullable().default(null),
|
|
1610
1805
|
created_at: Timestamp,
|
|
1611
1806
|
updated_at: Timestamp
|
|
1612
1807
|
});
|
|
1613
1808
|
var MailingSummary = Mailing.omit({ document: true });
|
|
1614
1809
|
var MailingContent = {
|
|
1615
|
-
name:
|
|
1616
|
-
subject:
|
|
1617
|
-
preheader:
|
|
1810
|
+
name: import_zod8.z.string().max(200).optional(),
|
|
1811
|
+
subject: import_zod8.z.string().min(1).max(998),
|
|
1812
|
+
preheader: import_zod8.z.string().max(500).optional(),
|
|
1618
1813
|
/** See `Mailing.send_locale`. */
|
|
1619
1814
|
send_locale: LocaleTag.nullable().optional(),
|
|
1620
1815
|
/**
|
|
@@ -1625,9 +1820,11 @@ var MailingContent = {
|
|
|
1625
1820
|
*/
|
|
1626
1821
|
topic: Slug.nullable().optional(),
|
|
1627
1822
|
provider_id: Id,
|
|
1628
|
-
metadata: MailingMetadata.optional()
|
|
1823
|
+
metadata: MailingMetadata.optional(),
|
|
1824
|
+
/** See `Mailing.merge`. `first_name` and `last_name` only on a letter (no topic). */
|
|
1825
|
+
merge: MailingMerge.optional()
|
|
1629
1826
|
};
|
|
1630
|
-
var MailingCreate =
|
|
1827
|
+
var MailingCreate = import_zod8.z.object({
|
|
1631
1828
|
...MailingContent,
|
|
1632
1829
|
subject: MailingContent.subject.optional(),
|
|
1633
1830
|
document: TemplateDocument.optional(),
|
|
@@ -1643,15 +1840,22 @@ var MailingCreate = import_zod7.z.object({
|
|
|
1643
1840
|
message: "a mailing made from a document needs a subject",
|
|
1644
1841
|
path: ["subject"]
|
|
1645
1842
|
});
|
|
1646
|
-
var MailingUpdate =
|
|
1647
|
-
name:
|
|
1843
|
+
var MailingUpdate = import_zod8.z.object({
|
|
1844
|
+
name: import_zod8.z.string().max(200).nullable().optional(),
|
|
1648
1845
|
subject: MailingContent.subject.optional(),
|
|
1649
|
-
preheader:
|
|
1846
|
+
preheader: import_zod8.z.string().max(500).nullable().optional(),
|
|
1650
1847
|
/** Null turns a draft into a letter, which it can only be with at most one recipient. */
|
|
1651
1848
|
topic: Slug.nullable().optional(),
|
|
1652
1849
|
send_locale: LocaleTag.nullable().optional(),
|
|
1653
1850
|
provider_id: Id.optional(),
|
|
1654
1851
|
metadata: MailingMetadata.optional(),
|
|
1852
|
+
/**
|
|
1853
|
+
* Replaces the mailing's values whole (see `Mailing.merge`). Giving a
|
|
1854
|
+
* mailing that holds `first_name` or `last_name` a topic is refused
|
|
1855
|
+
* (`name_on_broadcast`) unless the same call replaces its values without
|
|
1856
|
+
* them.
|
|
1857
|
+
*/
|
|
1858
|
+
merge: MailingMerge.optional(),
|
|
1655
1859
|
document: TemplateDocument.optional()
|
|
1656
1860
|
}).refine((v) => Object.keys(v).length > 0, "at least one field");
|
|
1657
1861
|
var MailingListQuery = PageQuery.extend({
|
|
@@ -1660,30 +1864,30 @@ var MailingListQuery = PageQuery.extend({
|
|
|
1660
1864
|
kind: MailingKind.optional(),
|
|
1661
1865
|
automation_id: Id.optional()
|
|
1662
1866
|
});
|
|
1663
|
-
var MailingSendRequest =
|
|
1664
|
-
var MailingRetryFailedRequest =
|
|
1867
|
+
var MailingSendRequest = import_zod8.z.object({}).strict();
|
|
1868
|
+
var MailingRetryFailedRequest = import_zod8.z.object({
|
|
1665
1869
|
/**
|
|
1666
1870
|
* Also requeue recipients whose outcome is unknown after a crash. They may
|
|
1667
1871
|
* already have received the message, so this is a human's decision, never a
|
|
1668
1872
|
* default.
|
|
1669
1873
|
*/
|
|
1670
|
-
include_outcome_unknown:
|
|
1874
|
+
include_outcome_unknown: import_zod8.z.boolean().optional()
|
|
1671
1875
|
}).strict();
|
|
1672
|
-
var MailingActionRequest =
|
|
1673
|
-
var MailingTestRequest =
|
|
1876
|
+
var MailingActionRequest = import_zod8.z.object({}).strict();
|
|
1877
|
+
var MailingTestRequest = import_zod8.z.object({
|
|
1674
1878
|
to: Email,
|
|
1675
1879
|
merge: Properties.optional(),
|
|
1676
1880
|
locale: LocaleTag.optional()
|
|
1677
1881
|
});
|
|
1678
|
-
var MailingTestResult =
|
|
1882
|
+
var MailingTestResult = import_zod8.z.object({
|
|
1679
1883
|
message_id: Id,
|
|
1680
|
-
provider_message_id:
|
|
1884
|
+
provider_message_id: import_zod8.z.string().nullable()
|
|
1681
1885
|
});
|
|
1682
1886
|
var RECIPIENT_STATUSES = ["queued", "sending", "sent", "failed", "skipped"];
|
|
1683
|
-
var RecipientStatus =
|
|
1887
|
+
var RecipientStatus = import_zod8.z.enum(RECIPIENT_STATUSES);
|
|
1684
1888
|
var SKIP_REASONS = ["suppressed", "not_subscribed", "contact_erased", "cancelled", "outcome_unknown"];
|
|
1685
|
-
var SkipReason =
|
|
1686
|
-
var Recipient =
|
|
1889
|
+
var SkipReason = import_zod8.z.enum(SKIP_REASONS);
|
|
1890
|
+
var Recipient = import_zod8.z.object({
|
|
1687
1891
|
id: Id,
|
|
1688
1892
|
mailing_id: Id,
|
|
1689
1893
|
contact_id: Id.nullable(),
|
|
@@ -1691,55 +1895,55 @@ var Recipient = import_zod7.z.object({
|
|
|
1691
1895
|
merge: Properties,
|
|
1692
1896
|
status: RecipientStatus,
|
|
1693
1897
|
skip_reason: SkipReason.nullable(),
|
|
1694
|
-
attempts:
|
|
1898
|
+
attempts: import_zod8.z.number().int().min(0),
|
|
1695
1899
|
message_id: Id.nullable(),
|
|
1696
|
-
last_error:
|
|
1900
|
+
last_error: import_zod8.z.string().nullable(),
|
|
1697
1901
|
created_at: Timestamp,
|
|
1698
1902
|
updated_at: Timestamp
|
|
1699
1903
|
});
|
|
1700
1904
|
var MAX_RECIPIENTS_PER_BATCH = 1e3;
|
|
1701
1905
|
var MAX_LETTER_RECIPIENTS = 1;
|
|
1702
1906
|
var LETTER_RECIPIENT_REFUSAL = "letter_has_one_recipient";
|
|
1703
|
-
var RecipientInput =
|
|
1907
|
+
var RecipientInput = import_zod8.z.object({
|
|
1704
1908
|
contact_id: Id.optional(),
|
|
1705
|
-
external_id:
|
|
1909
|
+
external_id: import_zod8.z.string().min(1).max(255).optional(),
|
|
1706
1910
|
email: Email.optional(),
|
|
1707
1911
|
merge: Properties.optional()
|
|
1708
1912
|
}).refine((v) => v.contact_id !== void 0 || v.external_id !== void 0 || v.email !== void 0, {
|
|
1709
1913
|
message: "contact_id, external_id or email is required",
|
|
1710
1914
|
path: ["email"]
|
|
1711
1915
|
});
|
|
1712
|
-
var RecipientBatch =
|
|
1713
|
-
recipients:
|
|
1916
|
+
var RecipientBatch = import_zod8.z.object({
|
|
1917
|
+
recipients: import_zod8.z.array(RecipientInput).min(1).max(MAX_RECIPIENTS_PER_BATCH)
|
|
1714
1918
|
});
|
|
1715
1919
|
var RECIPIENT_REJECTIONS = ["unknown_contact", "duplicate_in_batch"];
|
|
1716
|
-
var RecipientBatchResult =
|
|
1920
|
+
var RecipientBatchResult = import_zod8.z.object({
|
|
1717
1921
|
/** Newly queued. */
|
|
1718
|
-
added:
|
|
1922
|
+
added: import_zod8.z.number().int().min(0),
|
|
1719
1923
|
/** Already on the mailing from an earlier batch: left unchanged. */
|
|
1720
|
-
already_present:
|
|
1924
|
+
already_present: import_zod8.z.number().int().min(0),
|
|
1721
1925
|
/** Items not added, by their index in the request. */
|
|
1722
|
-
rejected:
|
|
1926
|
+
rejected: import_zod8.z.array(import_zod8.z.object({ index: import_zod8.z.number().int().min(0), reason: import_zod8.z.enum(RECIPIENT_REJECTIONS) }))
|
|
1723
1927
|
});
|
|
1724
1928
|
var RecipientListQuery = PageQuery.extend({
|
|
1725
1929
|
status: RecipientStatus.optional(),
|
|
1726
1930
|
skip_reason: SkipReason.optional()
|
|
1727
1931
|
});
|
|
1728
1932
|
var MESSAGE_OUTCOMES = ["sent", "failed"];
|
|
1729
|
-
var MessageOutcome =
|
|
1730
|
-
var MessageSummary =
|
|
1933
|
+
var MessageOutcome = import_zod8.z.enum(MESSAGE_OUTCOMES);
|
|
1934
|
+
var MessageSummary = import_zod8.z.object({
|
|
1731
1935
|
id: Id,
|
|
1732
1936
|
mailing_id: Id.nullable(),
|
|
1733
1937
|
recipient_id: Id.nullable(),
|
|
1734
1938
|
contact_id: Id.nullable(),
|
|
1735
1939
|
to: Email,
|
|
1736
|
-
subject:
|
|
1940
|
+
subject: import_zod8.z.string(),
|
|
1737
1941
|
provider_id: Id,
|
|
1738
|
-
provider_message_id:
|
|
1942
|
+
provider_message_id: import_zod8.z.string().nullable(),
|
|
1739
1943
|
outcome: MessageOutcome,
|
|
1740
|
-
error:
|
|
1741
|
-
is_test:
|
|
1742
|
-
recipient_count:
|
|
1944
|
+
error: import_zod8.z.string().nullable(),
|
|
1945
|
+
is_test: import_zod8.z.boolean(),
|
|
1946
|
+
recipient_count: import_zod8.z.number().int().min(1),
|
|
1743
1947
|
/** The language version the message was sent in; null for messages archived before languages existed. */
|
|
1744
1948
|
locale: LocaleTag.nullable(),
|
|
1745
1949
|
/**
|
|
@@ -1749,24 +1953,32 @@ var MessageSummary = import_zod7.z.object({
|
|
|
1749
1953
|
* "otherwise" text. Null when the message had no insertions.
|
|
1750
1954
|
*/
|
|
1751
1955
|
insertions: InsertionChoices.nullable(),
|
|
1956
|
+
/**
|
|
1957
|
+
* The values the message was written with, by name: the text each one
|
|
1958
|
+
* printed and the layer it came from (see `MessageValues`), recorded when it
|
|
1959
|
+
* was sent, so a later change to a default never rewrites what a reader got.
|
|
1960
|
+
* Null for a message archived before values were recorded, and for a signup
|
|
1961
|
+
* form's confirmation, which belongs to no mailing.
|
|
1962
|
+
*/
|
|
1963
|
+
values: MessageValues.nullable().default(null),
|
|
1752
1964
|
created_at: Timestamp
|
|
1753
1965
|
});
|
|
1754
|
-
var Message = MessageSummary.extend({ html:
|
|
1755
|
-
var MailingLanguageStatus =
|
|
1756
|
-
var MailingLanguage =
|
|
1966
|
+
var Message = MessageSummary.extend({ html: import_zod8.z.string() });
|
|
1967
|
+
var MailingLanguageStatus = import_zod8.z.enum(["main", "ready", "draft", "not_a_workspace_language"]);
|
|
1968
|
+
var MailingLanguage = import_zod8.z.object({
|
|
1757
1969
|
locale: LocaleTag,
|
|
1758
1970
|
status: MailingLanguageStatus,
|
|
1759
1971
|
/** Queued recipients who will get this version. */
|
|
1760
|
-
planned:
|
|
1972
|
+
planned: import_zod8.z.number().int().min(0),
|
|
1761
1973
|
/** Messages already sent in this language (tests excluded). */
|
|
1762
|
-
sent:
|
|
1974
|
+
sent: import_zod8.z.number().int().min(0)
|
|
1763
1975
|
});
|
|
1764
|
-
var MailingLanguageReport =
|
|
1976
|
+
var MailingLanguageReport = import_zod8.z.object({
|
|
1765
1977
|
main_locale: LocaleTag,
|
|
1766
1978
|
send_locale: LocaleTag.nullable(),
|
|
1767
|
-
languages:
|
|
1768
|
-
fallback:
|
|
1769
|
-
no_language:
|
|
1979
|
+
languages: import_zod8.z.array(MailingLanguage),
|
|
1980
|
+
fallback: import_zod8.z.array(import_zod8.z.object({ wanted: import_zod8.z.string(), planned: import_zod8.z.number().int().min(1) })),
|
|
1981
|
+
no_language: import_zod8.z.number().int().min(0),
|
|
1770
1982
|
/**
|
|
1771
1983
|
* Values that no choice of an insertion takes, so the "otherwise" text goes
|
|
1772
1984
|
* out (docs/plans/2026-09-25-translated-insertions.md, decision 3): per
|
|
@@ -1775,41 +1987,56 @@ var MailingLanguageReport = import_zod7.z.object({
|
|
|
1775
1987
|
* template's keys never produces one; a non-empty list means the client and
|
|
1776
1988
|
* the template have drifted apart.
|
|
1777
1989
|
*/
|
|
1778
|
-
insertion_misses:
|
|
1779
|
-
|
|
1780
|
-
insertion:
|
|
1781
|
-
value:
|
|
1782
|
-
planned:
|
|
1783
|
-
sent:
|
|
1990
|
+
insertion_misses: import_zod8.z.array(
|
|
1991
|
+
import_zod8.z.object({
|
|
1992
|
+
insertion: import_zod8.z.string(),
|
|
1993
|
+
value: import_zod8.z.string(),
|
|
1994
|
+
planned: import_zod8.z.number().int().min(0),
|
|
1995
|
+
sent: import_zod8.z.number().int().min(0)
|
|
1784
1996
|
})
|
|
1785
1997
|
)
|
|
1786
1998
|
});
|
|
1999
|
+
var MailingResolveRequest = import_zod8.z.object({
|
|
2000
|
+
recipients: import_zod8.z.array(RecipientInput).max(MAX_RECIPIENTS_PER_BATCH).optional()
|
|
2001
|
+
});
|
|
2002
|
+
var MailingResolveResult = import_zod8.z.object({
|
|
2003
|
+
/** Every value the mailing's content can read, in order of first appearance, without `email` and `unsubscribe_url`. */
|
|
2004
|
+
names: import_zod8.z.array(import_zod8.z.string()),
|
|
2005
|
+
/** The values and insertions placed inside a link's address: one of them empty for anybody refuses the send. */
|
|
2006
|
+
link_values: import_zod8.z.array(import_zod8.z.string()),
|
|
2007
|
+
/** One entry per resolved recipient, in the request's order; a single entry with `index: null` when none were given. */
|
|
2008
|
+
recipients: import_zod8.z.array(ResolvedRecipient),
|
|
2009
|
+
/** Items not resolved, by their index in the request, for the reasons `mailings.addRecipients` rejects one. */
|
|
2010
|
+
rejected: import_zod8.z.array(import_zod8.z.object({ index: import_zod8.z.number().int().min(0), reason: import_zod8.z.enum(RESOLVE_REJECTIONS) })),
|
|
2011
|
+
/** What would refuse `mailings.send` for these recipients, as its `unfilled_link` refusal lists it; empty means none. */
|
|
2012
|
+
blocking: import_zod8.z.array(UnfilledLink)
|
|
2013
|
+
});
|
|
1787
2014
|
var MessageListQuery = PageQuery.extend({
|
|
1788
2015
|
mailing_id: Id.optional(),
|
|
1789
2016
|
outcome: MessageOutcome.optional()
|
|
1790
2017
|
});
|
|
1791
2018
|
|
|
1792
2019
|
// src/platform.ts
|
|
1793
|
-
var Tag =
|
|
2020
|
+
var Tag = import_zod9.z.object({
|
|
1794
2021
|
id: Id,
|
|
1795
2022
|
slug: Slug,
|
|
1796
|
-
name:
|
|
1797
|
-
contact_count:
|
|
2023
|
+
name: import_zod9.z.string().min(1).max(120),
|
|
2024
|
+
contact_count: import_zod9.z.number().int().min(0),
|
|
1798
2025
|
created_at: Timestamp
|
|
1799
2026
|
});
|
|
1800
|
-
var TagCreate =
|
|
1801
|
-
var TagAssignment =
|
|
1802
|
-
contact_ids:
|
|
2027
|
+
var TagCreate = import_zod9.z.object({ slug: Slug, name: import_zod9.z.string().min(1).max(120) });
|
|
2028
|
+
var TagAssignment = import_zod9.z.object({
|
|
2029
|
+
contact_ids: import_zod9.z.array(Id).min(1).max(1e3)
|
|
1803
2030
|
});
|
|
1804
2031
|
var CONTACT_PROPERTY_TYPES = ["string", "number", "boolean", "date"];
|
|
1805
|
-
var ContactPropertyType =
|
|
1806
|
-
var ContactPropertyKey =
|
|
1807
|
-
var ContactPropertyDefinition =
|
|
2032
|
+
var ContactPropertyType = import_zod9.z.enum(CONTACT_PROPERTY_TYPES);
|
|
2033
|
+
var ContactPropertyKey = import_zod9.z.string().regex(/^[A-Za-z0-9_.-]{1,64}$/, "letters, digits, dot, underscore and hyphen, 1 to 64");
|
|
2034
|
+
var ContactPropertyDefinition = import_zod9.z.object({
|
|
1808
2035
|
key: ContactPropertyKey,
|
|
1809
|
-
label:
|
|
2036
|
+
label: import_zod9.z.string().min(1).max(120),
|
|
1810
2037
|
type: ContactPropertyType
|
|
1811
2038
|
});
|
|
1812
|
-
var ContactPropertyParams =
|
|
2039
|
+
var ContactPropertyParams = import_zod9.z.object({ key: ContactPropertyKey });
|
|
1813
2040
|
var FILTER_OPERATORS = [
|
|
1814
2041
|
"eq",
|
|
1815
2042
|
"neq",
|
|
@@ -1825,8 +2052,8 @@ var FILTER_OPERATORS = [
|
|
|
1825
2052
|
"in",
|
|
1826
2053
|
"not_in"
|
|
1827
2054
|
];
|
|
1828
|
-
var FilterOperator =
|
|
1829
|
-
var FilterField =
|
|
2055
|
+
var FilterOperator = import_zod9.z.enum(FILTER_OPERATORS);
|
|
2056
|
+
var FilterField = import_zod9.z.string().regex(
|
|
1830
2057
|
/^(email|first_name|last_name|locale|created_at|tag|topic|engagement:(opened|clicked)|property:[A-Za-z0-9_.-]{1,64})$/,
|
|
1831
2058
|
"unknown filter field"
|
|
1832
2059
|
);
|
|
@@ -1842,18 +2069,18 @@ var FILTER_FIELD_OPERATORS = {
|
|
|
1842
2069
|
property: FILTER_OPERATORS
|
|
1843
2070
|
};
|
|
1844
2071
|
var MAX_FILTER_DEPTH = 5;
|
|
1845
|
-
var FilterCondition =
|
|
2072
|
+
var FilterCondition = import_zod9.z.object({ field: FilterField, op: FilterOperator, value: JsonValue.optional() }).strict().refine((c) => (c.op === "exists" || c.op === "not_exists") === (c.value === void 0), {
|
|
1846
2073
|
message: "exists and not_exists take no value; every other operator needs one",
|
|
1847
2074
|
path: ["value"]
|
|
1848
2075
|
}).refine((c) => c.op !== "in" && c.op !== "not_in" || Array.isArray(c.value), {
|
|
1849
2076
|
message: "in and not_in take an array",
|
|
1850
2077
|
path: ["value"]
|
|
1851
2078
|
});
|
|
1852
|
-
var SegmentFilter =
|
|
1853
|
-
() =>
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
2079
|
+
var SegmentFilter = import_zod9.z.lazy(
|
|
2080
|
+
() => import_zod9.z.union([
|
|
2081
|
+
import_zod9.z.object({ and: import_zod9.z.array(SegmentFilter).min(1).max(50) }).strict(),
|
|
2082
|
+
import_zod9.z.object({ or: import_zod9.z.array(SegmentFilter).min(1).max(50) }).strict(),
|
|
2083
|
+
import_zod9.z.object({ not: SegmentFilter }).strict(),
|
|
1857
2084
|
FilterCondition
|
|
1858
2085
|
])
|
|
1859
2086
|
);
|
|
@@ -1941,42 +2168,42 @@ function untypedValueProblem(c, every) {
|
|
|
1941
2168
|
if (orderOp) return every(isFilterNumber, "numbers (define the property to compare dates)");
|
|
1942
2169
|
return every((v) => isScalar(v) || v === null, "strings, numbers, booleans or null");
|
|
1943
2170
|
}
|
|
1944
|
-
var Segment =
|
|
2171
|
+
var Segment = import_zod9.z.object({
|
|
1945
2172
|
id: Id,
|
|
1946
|
-
name:
|
|
2173
|
+
name: import_zod9.z.string().min(1).max(120),
|
|
1947
2174
|
filter: SegmentFilter,
|
|
1948
2175
|
/** Computed on read. */
|
|
1949
|
-
contact_count:
|
|
2176
|
+
contact_count: import_zod9.z.number().int().min(0),
|
|
1950
2177
|
created_at: Timestamp,
|
|
1951
2178
|
updated_at: Timestamp
|
|
1952
2179
|
});
|
|
1953
|
-
var SegmentCreate =
|
|
1954
|
-
var SegmentPreviewRequest =
|
|
1955
|
-
var SegmentPreview =
|
|
1956
|
-
contact_count:
|
|
2180
|
+
var SegmentCreate = import_zod9.z.object({ name: import_zod9.z.string().min(1).max(120), filter: BoundedSegmentFilter });
|
|
2181
|
+
var SegmentPreviewRequest = import_zod9.z.object({ filter: BoundedSegmentFilter });
|
|
2182
|
+
var SegmentPreview = import_zod9.z.object({
|
|
2183
|
+
contact_count: import_zod9.z.number().int().min(0),
|
|
1957
2184
|
/** Up to five matching contacts, for a human to sanity-check the filter. */
|
|
1958
|
-
sample:
|
|
2185
|
+
sample: import_zod9.z.array(import_zod9.z.object({ id: Id, email: Email })).max(5)
|
|
1959
2186
|
});
|
|
1960
|
-
var MailingAudienceFromSegment =
|
|
2187
|
+
var MailingAudienceFromSegment = import_zod9.z.object({ segment_id: Id });
|
|
1961
2188
|
var SIGNUP_FORM_FIELDS = ["first_name", "last_name"];
|
|
1962
2189
|
var HOSTED_PAGE_LOCALES = ["en", "de", "it", "fr", "es"];
|
|
1963
|
-
var SignupFormTranslation =
|
|
1964
|
-
title:
|
|
1965
|
-
consent_text:
|
|
2190
|
+
var SignupFormTranslation = import_zod9.z.object({
|
|
2191
|
+
title: import_zod9.z.string().min(1).max(120),
|
|
2192
|
+
consent_text: import_zod9.z.string().min(1).max(2e3)
|
|
1966
2193
|
});
|
|
1967
|
-
var SignupForm =
|
|
2194
|
+
var SignupForm = import_zod9.z.object({
|
|
1968
2195
|
id: Id,
|
|
1969
|
-
name:
|
|
2196
|
+
name: import_zod9.z.string().min(1).max(120),
|
|
1970
2197
|
/** The heading of the hosted page. */
|
|
1971
|
-
title:
|
|
2198
|
+
title: import_zod9.z.string().min(1).max(120),
|
|
1972
2199
|
/** What the person agrees to, shown above the button and recorded with the confirmation. */
|
|
1973
|
-
consent_text:
|
|
1974
|
-
translations:
|
|
1975
|
-
topics:
|
|
1976
|
-
tags:
|
|
2200
|
+
consent_text: import_zod9.z.string().min(1).max(2e3),
|
|
2201
|
+
translations: import_zod9.z.record(SignupFormTranslation),
|
|
2202
|
+
topics: import_zod9.z.array(Slug).min(1),
|
|
2203
|
+
tags: import_zod9.z.array(Slug),
|
|
1977
2204
|
/** Fields shown besides email. */
|
|
1978
|
-
fields:
|
|
1979
|
-
double_opt_in:
|
|
2205
|
+
fields: import_zod9.z.array(import_zod9.z.enum(SIGNUP_FORM_FIELDS)),
|
|
2206
|
+
double_opt_in: import_zod9.z.literal(true),
|
|
1980
2207
|
/** The provider the confirmation mail is sent through. */
|
|
1981
2208
|
provider_id: Id,
|
|
1982
2209
|
/**
|
|
@@ -1985,11 +2212,11 @@ var SignupForm = import_zod8.z.object({
|
|
|
1985
2212
|
*/
|
|
1986
2213
|
confirmation_template_id: Id.nullable(),
|
|
1987
2214
|
/** Where the person lands after confirming. Null shows the hosted confirmation page. */
|
|
1988
|
-
redirect_url:
|
|
2215
|
+
redirect_url: import_zod9.z.string().url().nullable(),
|
|
1989
2216
|
/** Origins allowed to embed the form and call the submission route from a browser. */
|
|
1990
|
-
allowed_origins:
|
|
2217
|
+
allowed_origins: import_zod9.z.array(import_zod9.z.string().url()).max(20),
|
|
1991
2218
|
/** Bumped on every change; recorded with each confirmation. */
|
|
1992
|
-
version:
|
|
2219
|
+
version: import_zod9.z.number().int().min(1),
|
|
1993
2220
|
created_at: Timestamp,
|
|
1994
2221
|
updated_at: Timestamp
|
|
1995
2222
|
});
|
|
@@ -2004,56 +2231,56 @@ var SignupFormCreate = SignupForm.omit({
|
|
|
2004
2231
|
tags: SignupForm.shape.tags.optional(),
|
|
2005
2232
|
fields: SignupForm.shape.fields.optional(),
|
|
2006
2233
|
confirmation_template_id: Id.nullable().optional(),
|
|
2007
|
-
redirect_url:
|
|
2234
|
+
redirect_url: import_zod9.z.string().url().nullable().optional(),
|
|
2008
2235
|
allowed_origins: SignupForm.shape.allowed_origins.optional()
|
|
2009
2236
|
});
|
|
2010
|
-
var SignupFormEmbed =
|
|
2011
|
-
hosted_url:
|
|
2237
|
+
var SignupFormEmbed = import_zod9.z.object({
|
|
2238
|
+
hosted_url: import_zod9.z.string().url(),
|
|
2012
2239
|
/** A plain HTML form posting to the hosted page; works without JavaScript. */
|
|
2013
|
-
html:
|
|
2240
|
+
html: import_zod9.z.string(),
|
|
2014
2241
|
/** A small optional script that adds the time check and submits in place. */
|
|
2015
|
-
script_url:
|
|
2242
|
+
script_url: import_zod9.z.string().url(),
|
|
2016
2243
|
/** Where a browser fetches a fresh `form_token` from (GET, public, CORS for `allowed_origins`). */
|
|
2017
|
-
token_url:
|
|
2244
|
+
token_url: import_zod9.z.string().url()
|
|
2018
2245
|
});
|
|
2019
|
-
var SignupSubmission =
|
|
2246
|
+
var SignupSubmission = import_zod9.z.object({
|
|
2020
2247
|
email: Email,
|
|
2021
|
-
first_name:
|
|
2022
|
-
last_name:
|
|
2023
|
-
locale:
|
|
2248
|
+
first_name: import_zod9.z.string().max(200).optional(),
|
|
2249
|
+
last_name: import_zod9.z.string().max(200).optional(),
|
|
2250
|
+
locale: import_zod9.z.string().min(2).max(35).optional(),
|
|
2024
2251
|
/** Honeypot: must be empty. */
|
|
2025
|
-
website:
|
|
2252
|
+
website: import_zod9.z.string().max(0).optional(),
|
|
2026
2253
|
/**
|
|
2027
2254
|
* The signed render time from the form's token URL: a submission sooner than a
|
|
2028
2255
|
* human could fill the form, or long after, is refused.
|
|
2029
2256
|
*/
|
|
2030
|
-
form_token:
|
|
2257
|
+
form_token: import_zod9.z.string().min(1).max(512)
|
|
2031
2258
|
});
|
|
2032
2259
|
var IMPORT_STATUSES = ["uploaded", "validating", "validated", "committing", "completed", "failed", "cancelled"];
|
|
2033
|
-
var ImportStatus =
|
|
2260
|
+
var ImportStatus = import_zod9.z.enum(IMPORT_STATUSES);
|
|
2034
2261
|
var IMPORT_TERMINAL_STATUSES = ["completed", "failed", "cancelled"];
|
|
2035
|
-
var ImportColumnMapping =
|
|
2036
|
-
|
|
2262
|
+
var ImportColumnMapping = import_zod9.z.record(
|
|
2263
|
+
import_zod9.z.string().regex(/^(email|external_id|first_name|last_name|locale|property:[A-Za-z0-9_.-]{1,64}|ignore)$/)
|
|
2037
2264
|
);
|
|
2038
2265
|
var IMPORT_FILE_FIELD = "file";
|
|
2039
2266
|
var MAX_IMPORT_BYTES = 50 * 1024 * 1024;
|
|
2040
2267
|
var MAX_IMPORT_ROWS = 2e5;
|
|
2041
|
-
var ImportMappingRequest =
|
|
2268
|
+
var ImportMappingRequest = import_zod9.z.object({
|
|
2042
2269
|
/** CSV header -> contact field. Exactly one column maps to `email`. */
|
|
2043
2270
|
mapping: ImportColumnMapping.refine(
|
|
2044
2271
|
(m) => Object.values(m).filter((v) => v === "email").length === 1,
|
|
2045
2272
|
"exactly one column maps to email"
|
|
2046
2273
|
),
|
|
2047
|
-
topics:
|
|
2048
|
-
tags:
|
|
2274
|
+
topics: import_zod9.z.array(Slug).max(100),
|
|
2275
|
+
tags: import_zod9.z.array(Slug).max(100),
|
|
2049
2276
|
/** Existing contacts get the mapped fields overwritten; false only adds topics, tags and missing fields. */
|
|
2050
|
-
update_existing:
|
|
2277
|
+
update_existing: import_zod9.z.boolean().optional(),
|
|
2051
2278
|
/** The importer states the people consented; the service records who said so and when. */
|
|
2052
|
-
consent_confirmed:
|
|
2279
|
+
consent_confirmed: import_zod9.z.literal(true)
|
|
2053
2280
|
});
|
|
2054
|
-
var ImportCommitRequest =
|
|
2281
|
+
var ImportCommitRequest = import_zod9.z.object({ mapping_version: import_zod9.z.number().int().min(1) });
|
|
2055
2282
|
var IMPORT_ROW_OUTCOMES = ["created", "updated", "unchanged", "suppressed", "skipped"];
|
|
2056
|
-
var ImportRowOutcome =
|
|
2283
|
+
var ImportRowOutcome = import_zod9.z.enum(IMPORT_ROW_OUTCOMES);
|
|
2057
2284
|
var IMPORT_SKIP_REASONS = [
|
|
2058
2285
|
"missing_email",
|
|
2059
2286
|
"invalid_email",
|
|
@@ -2062,90 +2289,90 @@ var IMPORT_SKIP_REASONS = [
|
|
|
2062
2289
|
"external_id_conflict",
|
|
2063
2290
|
"wrong_column_count"
|
|
2064
2291
|
];
|
|
2065
|
-
var ImportSkipReason =
|
|
2066
|
-
var ImportReport =
|
|
2067
|
-
created:
|
|
2068
|
-
updated:
|
|
2069
|
-
unchanged:
|
|
2070
|
-
suppressed:
|
|
2071
|
-
skipped:
|
|
2072
|
-
skipped_by_reason:
|
|
2292
|
+
var ImportSkipReason = import_zod9.z.enum(IMPORT_SKIP_REASONS);
|
|
2293
|
+
var ImportReport = import_zod9.z.object({
|
|
2294
|
+
created: import_zod9.z.number().int().min(0),
|
|
2295
|
+
updated: import_zod9.z.number().int().min(0),
|
|
2296
|
+
unchanged: import_zod9.z.number().int().min(0),
|
|
2297
|
+
suppressed: import_zod9.z.number().int().min(0),
|
|
2298
|
+
skipped: import_zod9.z.number().int().min(0),
|
|
2299
|
+
skipped_by_reason: import_zod9.z.record(ImportSkipReason, import_zod9.z.number().int().min(0)),
|
|
2073
2300
|
/** Rows whose contact was subscribed without some topic, because the address is blocked for it. */
|
|
2074
|
-
topics_withheld:
|
|
2301
|
+
topics_withheld: import_zod9.z.number().int().min(0)
|
|
2075
2302
|
});
|
|
2076
|
-
var ImportJob =
|
|
2303
|
+
var ImportJob = import_zod9.z.object({
|
|
2077
2304
|
id: Id,
|
|
2078
2305
|
status: ImportStatus,
|
|
2079
|
-
file_name:
|
|
2080
|
-
file_bytes:
|
|
2081
|
-
total_rows:
|
|
2306
|
+
file_name: import_zod9.z.string().max(255).nullable(),
|
|
2307
|
+
file_bytes: import_zod9.z.number().int().min(0),
|
|
2308
|
+
total_rows: import_zod9.z.number().int().min(0),
|
|
2082
2309
|
/** The header row, as in the file. */
|
|
2083
|
-
columns:
|
|
2310
|
+
columns: import_zod9.z.array(import_zod9.z.string()),
|
|
2084
2311
|
/** The first rows, for the mapping screen. */
|
|
2085
|
-
sample:
|
|
2312
|
+
sample: import_zod9.z.array(import_zod9.z.array(import_zod9.z.string())).max(5),
|
|
2086
2313
|
/** A mapping guessed from the headers, for the mapping screen to start from. */
|
|
2087
2314
|
suggested_mapping: ImportColumnMapping,
|
|
2088
2315
|
mapping: ImportColumnMapping.nullable(),
|
|
2089
|
-
mapping_version:
|
|
2090
|
-
topics:
|
|
2091
|
-
tags:
|
|
2092
|
-
update_existing:
|
|
2316
|
+
mapping_version: import_zod9.z.number().int().min(0),
|
|
2317
|
+
topics: import_zod9.z.array(Slug),
|
|
2318
|
+
tags: import_zod9.z.array(Slug),
|
|
2319
|
+
update_existing: import_zod9.z.boolean(),
|
|
2093
2320
|
/** The dry run of the current mapping; null before one finished. */
|
|
2094
2321
|
dry_run: ImportReport.nullable(),
|
|
2095
2322
|
/** What the commit has written so far; null before it started. */
|
|
2096
2323
|
result: ImportReport.nullable(),
|
|
2097
2324
|
/** Rows the current phase (dry run or commit) has processed. */
|
|
2098
|
-
processed_rows:
|
|
2325
|
+
processed_rows: import_zod9.z.number().int().min(0),
|
|
2099
2326
|
/** Why a `failed` import failed. */
|
|
2100
|
-
error:
|
|
2327
|
+
error: import_zod9.z.string().nullable(),
|
|
2101
2328
|
created_at: Timestamp,
|
|
2102
2329
|
updated_at: Timestamp,
|
|
2103
2330
|
finished_at: Timestamp.nullable()
|
|
2104
2331
|
});
|
|
2105
|
-
var ImportRow =
|
|
2332
|
+
var ImportRow = import_zod9.z.object({
|
|
2106
2333
|
/** The line in the file, 1 being the first line after the header. */
|
|
2107
|
-
row:
|
|
2108
|
-
email:
|
|
2334
|
+
row: import_zod9.z.number().int().min(1),
|
|
2335
|
+
email: import_zod9.z.string().nullable(),
|
|
2109
2336
|
outcome: ImportRowOutcome,
|
|
2110
2337
|
reason: ImportSkipReason.nullable(),
|
|
2111
2338
|
/** A human explanation for a skipped row (which value, which column). */
|
|
2112
|
-
message:
|
|
2339
|
+
message: import_zod9.z.string().nullable(),
|
|
2113
2340
|
contact_id: Id.nullable()
|
|
2114
2341
|
});
|
|
2115
2342
|
var ImportRowListQuery = PageQuery.extend({ outcome: ImportRowOutcome.optional() });
|
|
2116
|
-
var MailingScheduleRequest =
|
|
2117
|
-
var TrackingSettings =
|
|
2118
|
-
var VariantAnalytics =
|
|
2119
|
-
key:
|
|
2120
|
-
sent:
|
|
2121
|
-
unique_opens:
|
|
2122
|
-
unique_clicks:
|
|
2123
|
-
});
|
|
2124
|
-
var MailingAnalytics =
|
|
2343
|
+
var MailingScheduleRequest = import_zod9.z.object({ send_at: Timestamp });
|
|
2344
|
+
var TrackingSettings = import_zod9.z.object({ opens: import_zod9.z.boolean(), clicks: import_zod9.z.boolean() });
|
|
2345
|
+
var VariantAnalytics = import_zod9.z.object({
|
|
2346
|
+
key: import_zod9.z.string(),
|
|
2347
|
+
sent: import_zod9.z.number().int().min(0),
|
|
2348
|
+
unique_opens: import_zod9.z.number().int().min(0).nullable(),
|
|
2349
|
+
unique_clicks: import_zod9.z.number().int().min(0).nullable()
|
|
2350
|
+
});
|
|
2351
|
+
var MailingAnalytics = import_zod9.z.object({
|
|
2125
2352
|
mailing_id: Id,
|
|
2126
2353
|
counts: MailingCounts,
|
|
2127
2354
|
/** What was tracked for this mailing, fixed when it started; null before it started. */
|
|
2128
2355
|
tracking: TrackingSettings.nullable(),
|
|
2129
2356
|
/** Unique recipients with a human open. Null when opens were not tracked. */
|
|
2130
|
-
unique_opens:
|
|
2357
|
+
unique_opens: import_zod9.z.number().int().min(0).nullable(),
|
|
2131
2358
|
/**
|
|
2132
2359
|
* Recipients whose only opens came from Apple Mail Privacy Protection, which
|
|
2133
2360
|
* loads every image on delivery: counted apart, never as human opens.
|
|
2134
2361
|
*/
|
|
2135
|
-
apple_mpp_opens:
|
|
2362
|
+
apple_mpp_opens: import_zod9.z.number().int().min(0).nullable(),
|
|
2136
2363
|
/** Opens and clicks from security scanners and prefetchers, filtered out of the unique counts. */
|
|
2137
|
-
machine_events:
|
|
2138
|
-
unique_clicks:
|
|
2139
|
-
unsubscribes:
|
|
2140
|
-
bounces:
|
|
2141
|
-
complaints:
|
|
2142
|
-
links:
|
|
2143
|
-
variants:
|
|
2364
|
+
machine_events: import_zod9.z.number().int().min(0).nullable(),
|
|
2365
|
+
unique_clicks: import_zod9.z.number().int().min(0).nullable(),
|
|
2366
|
+
unsubscribes: import_zod9.z.number().int().min(0),
|
|
2367
|
+
bounces: import_zod9.z.number().int().min(0),
|
|
2368
|
+
complaints: import_zod9.z.number().int().min(0),
|
|
2369
|
+
links: import_zod9.z.array(import_zod9.z.object({ url: import_zod9.z.string(), unique_clicks: import_zod9.z.number().int().min(0) })).nullable(),
|
|
2370
|
+
variants: import_zod9.z.array(VariantAnalytics).nullable()
|
|
2144
2371
|
});
|
|
2145
2372
|
|
|
2146
2373
|
// src/automations.ts
|
|
2147
2374
|
var AUTOMATION_FILTER_FIELD_PATTERN = /^(email|first_name|last_name|locale|created_at|tag|topic|segment|engagement:(opened|clicked)|step:(opened|clicked)|property:[A-Za-z0-9_.-]{1,64}|event:[A-Za-z0-9_.-]{1,64})$/;
|
|
2148
|
-
var AutomationFilterField =
|
|
2375
|
+
var AutomationFilterField = import_zod10.z.string().regex(AUTOMATION_FILTER_FIELD_PATTERN, "unknown filter field");
|
|
2149
2376
|
var AUTOMATION_FILTER_FIELD_OPERATORS = {
|
|
2150
2377
|
...FILTER_FIELD_OPERATORS,
|
|
2151
2378
|
segment: ["eq", "neq", "in", "not_in"],
|
|
@@ -2155,18 +2382,18 @@ var AUTOMATION_FILTER_FIELD_OPERATORS = {
|
|
|
2155
2382
|
step: ["eq", "neq"]
|
|
2156
2383
|
};
|
|
2157
2384
|
var automationFilterFamily = filterFieldFamily;
|
|
2158
|
-
var AutomationFilterCondition =
|
|
2385
|
+
var AutomationFilterCondition = import_zod10.z.object({ field: AutomationFilterField, op: FilterOperator, value: JsonValue.optional() }).strict().refine((c) => (c.op === "exists" || c.op === "not_exists") === (c.value === void 0), {
|
|
2159
2386
|
message: "exists and not_exists take no value; every other operator needs one",
|
|
2160
2387
|
path: ["value"]
|
|
2161
2388
|
}).refine((c) => c.op !== "in" && c.op !== "not_in" || Array.isArray(c.value), {
|
|
2162
2389
|
message: "in and not_in take an array",
|
|
2163
2390
|
path: ["value"]
|
|
2164
2391
|
});
|
|
2165
|
-
var AutomationFilter =
|
|
2166
|
-
() =>
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2392
|
+
var AutomationFilter = import_zod10.z.lazy(
|
|
2393
|
+
() => import_zod10.z.union([
|
|
2394
|
+
import_zod10.z.object({ and: import_zod10.z.array(AutomationFilter).min(1).max(50) }).strict(),
|
|
2395
|
+
import_zod10.z.object({ or: import_zod10.z.array(AutomationFilter).min(1).max(50) }).strict(),
|
|
2396
|
+
import_zod10.z.object({ not: AutomationFilter }).strict(),
|
|
2170
2397
|
AutomationFilterCondition
|
|
2171
2398
|
])
|
|
2172
2399
|
);
|
|
@@ -2179,20 +2406,20 @@ function filterConditions(filter) {
|
|
|
2179
2406
|
if ("not" in filter) return filterConditions(filter.not);
|
|
2180
2407
|
return [filter];
|
|
2181
2408
|
}
|
|
2182
|
-
var StepId =
|
|
2183
|
-
var TimeOfDay =
|
|
2184
|
-
var Weekday =
|
|
2185
|
-
var TimezoneName =
|
|
2409
|
+
var StepId = import_zod10.z.string().regex(/^[A-Za-z0-9_-]{1,64}$/, "letters, digits, underscore and hyphen, 1 to 64");
|
|
2410
|
+
var TimeOfDay = import_zod10.z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "HH:MM in 24 hours");
|
|
2411
|
+
var Weekday = import_zod10.z.number().int().min(0).max(6);
|
|
2412
|
+
var TimezoneName = import_zod10.z.string().min(1).max(64).regex(/^(UTC|[A-Za-z][A-Za-z0-9_+-]*(?:\/[A-Za-z0-9_+-]+)+)$/, "an IANA time zone name such as Europe/Berlin");
|
|
2186
2413
|
var MAX_DELAY_SECONDS = 365 * 24 * 60 * 60;
|
|
2187
|
-
var DateOnly =
|
|
2414
|
+
var DateOnly = import_zod10.z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "a calendar date such as 2026-09-20").refine((v) => {
|
|
2188
2415
|
const [y, m, d] = v.split("-").map(Number);
|
|
2189
2416
|
const t = new Date(Date.UTC(y, m - 1, d));
|
|
2190
2417
|
return t.getUTCFullYear() === y && t.getUTCMonth() + 1 === m && t.getUTCDate() === d;
|
|
2191
2418
|
}, "a real calendar date");
|
|
2192
|
-
var OffsetDays =
|
|
2419
|
+
var OffsetDays = import_zod10.z.number().int().min(-365).max(365);
|
|
2193
2420
|
var DATE_PASSED_ANSWERS = ["skip", "stop", "continue"];
|
|
2194
|
-
var DatePassedAnswer =
|
|
2195
|
-
var EventName =
|
|
2421
|
+
var DatePassedAnswer = import_zod10.z.enum(DATE_PASSED_ANSWERS);
|
|
2422
|
+
var EventName = import_zod10.z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,79}$/, "letters, digits, dot, colon, underscore and hyphen, 1 to 80");
|
|
2196
2423
|
var AUTOMATION_TRIGGER_KINDS = [
|
|
2197
2424
|
"topic_subscribed",
|
|
2198
2425
|
"form_confirmed",
|
|
@@ -2205,17 +2432,17 @@ var AUTOMATION_TRIGGER_KINDS = [
|
|
|
2205
2432
|
"segment_entered",
|
|
2206
2433
|
"link_clicked"
|
|
2207
2434
|
];
|
|
2208
|
-
var AutomationTriggerKind =
|
|
2435
|
+
var AutomationTriggerKind = import_zod10.z.enum(AUTOMATION_TRIGGER_KINDS);
|
|
2209
2436
|
var exclude = { exclude: BoundedAutomationFilter.nullish() };
|
|
2210
|
-
var AutomationTrigger =
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2437
|
+
var AutomationTrigger = import_zod10.z.discriminatedUnion("kind", [
|
|
2438
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("topic_subscribed"), topic: Slug, ...exclude }).strict(),
|
|
2439
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("form_confirmed"), form_id: Id, ...exclude }).strict(),
|
|
2440
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("tag_added"), tag: Slug, ...exclude }).strict(),
|
|
2214
2441
|
/** `to` given: only a change that lands on this value fires. Absent: any change of the key. */
|
|
2215
|
-
|
|
2442
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("property_changed"), key: ContactPropertyKey, to: JsonValue.optional(), ...exclude }).strict(),
|
|
2216
2443
|
/** `where` filters the event's own data, so only `event:<key>` leaves belong in it. */
|
|
2217
|
-
|
|
2218
|
-
|
|
2444
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("event"), name: EventName, where: BoundedAutomationFilter.nullish(), ...exclude }).strict(),
|
|
2445
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("manual"), ...exclude }).strict(),
|
|
2219
2446
|
/**
|
|
2220
2447
|
* Every year on a date the contact carries: a birthday, a joining date, a
|
|
2221
2448
|
* renewal. `offset_days` moves it ("three days before"), `at` is the wall
|
|
@@ -2225,8 +2452,8 @@ var AutomationTrigger = import_zod9.z.discriminatedUnion("kind", [
|
|
|
2225
2452
|
* A 29 February date fires on 1 March in a year that has no 29 February, so
|
|
2226
2453
|
* nobody is skipped every fourth year.
|
|
2227
2454
|
*/
|
|
2228
|
-
|
|
2229
|
-
kind:
|
|
2455
|
+
import_zod10.z.object({
|
|
2456
|
+
kind: import_zod10.z.literal("date_anniversary"),
|
|
2230
2457
|
key: ContactPropertyKey,
|
|
2231
2458
|
offset_days: OffsetDays,
|
|
2232
2459
|
at: TimeOfDay,
|
|
@@ -2238,8 +2465,8 @@ var AutomationTrigger = import_zod9.z.discriminatedUnion("kind", [
|
|
|
2238
2465
|
* not ask about a segment or about an event's data: there is no event, and a
|
|
2239
2466
|
* segment is its own trigger kind.
|
|
2240
2467
|
*/
|
|
2241
|
-
|
|
2242
|
-
kind:
|
|
2468
|
+
import_zod10.z.object({
|
|
2469
|
+
kind: import_zod10.z.literal("exact_date"),
|
|
2243
2470
|
on: DateOnly,
|
|
2244
2471
|
at: TimeOfDay,
|
|
2245
2472
|
where: BoundedAutomationFilter.nullish(),
|
|
@@ -2258,7 +2485,7 @@ var AutomationTrigger = import_zod9.z.discriminatedUnion("kind", [
|
|
|
2258
2485
|
* already exists. Entering those people as well is the publish dialog's
|
|
2259
2486
|
* backfill question, answered by a person rather than by the sweep.
|
|
2260
2487
|
*/
|
|
2261
|
-
|
|
2488
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("segment_entered"), segment_id: Id, ...exclude }).strict(),
|
|
2262
2489
|
/**
|
|
2263
2490
|
* S4. When somebody clicks a link in a mailing that has already gone out.
|
|
2264
2491
|
*
|
|
@@ -2268,7 +2495,7 @@ var AutomationTrigger = import_zod9.z.discriminatedUnion("kind", [
|
|
|
2268
2495
|
* tracking off there is no click to hear about, so the validator refuses it
|
|
2269
2496
|
* rather than leaving an automation that can never fire.
|
|
2270
2497
|
*/
|
|
2271
|
-
|
|
2498
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("link_clicked"), mailing_id: Id, url: import_zod10.z.string().min(1).max(2048).optional(), ...exclude }).strict()
|
|
2272
2499
|
]);
|
|
2273
2500
|
var AUTOMATION_DATE_TRIGGER_KINDS = ["date_anniversary", "exact_date"];
|
|
2274
2501
|
var MAX_TRIGGERS = 10;
|
|
@@ -2287,45 +2514,45 @@ var AUTOMATION_STEP_KINDS = [
|
|
|
2287
2514
|
"webhook",
|
|
2288
2515
|
"notify"
|
|
2289
2516
|
];
|
|
2290
|
-
var AutomationStepKind =
|
|
2517
|
+
var AutomationStepKind = import_zod10.z.enum(AUTOMATION_STEP_KINDS);
|
|
2291
2518
|
var next = { next: StepId.nullable() };
|
|
2292
|
-
var Unchosen =
|
|
2293
|
-
var DraftSlug =
|
|
2294
|
-
var DraftPropertyKey =
|
|
2295
|
-
var label2 = { label:
|
|
2296
|
-
var EmailStepLanguage =
|
|
2297
|
-
subject:
|
|
2298
|
-
preheader:
|
|
2519
|
+
var Unchosen = import_zod10.z.literal("");
|
|
2520
|
+
var DraftSlug = import_zod10.z.union([Slug, Unchosen]);
|
|
2521
|
+
var DraftPropertyKey = import_zod10.z.union([ContactPropertyKey, Unchosen]);
|
|
2522
|
+
var label2 = { label: import_zod10.z.string().max(120).nullish() };
|
|
2523
|
+
var EmailStepLanguage = import_zod10.z.object({
|
|
2524
|
+
subject: import_zod10.z.string().min(1).max(998),
|
|
2525
|
+
preheader: import_zod10.z.string().max(500).nullable(),
|
|
2299
2526
|
document: TemplateDocument,
|
|
2300
2527
|
/** This language's insertions, its texts over the template's structure (every text present). */
|
|
2301
2528
|
insertions: Insertions.nullish()
|
|
2302
2529
|
}).strict();
|
|
2303
|
-
var EmailStep =
|
|
2304
|
-
kind:
|
|
2530
|
+
var EmailStep = import_zod10.z.object({
|
|
2531
|
+
kind: import_zod10.z.literal("email"),
|
|
2305
2532
|
...label2,
|
|
2306
2533
|
...next,
|
|
2307
2534
|
template_id: Id.nullish(),
|
|
2308
2535
|
document: TemplateDocument.nullish(),
|
|
2309
2536
|
/** Empty while the step is being written, or when its template has a subject; else `not_chosen` refuses to publish it. */
|
|
2310
|
-
subject:
|
|
2311
|
-
preheader:
|
|
2537
|
+
subject: import_zod10.z.string().max(998),
|
|
2538
|
+
preheader: import_zod10.z.string().max(500).nullish(),
|
|
2312
2539
|
locale: LocaleTag.nullish(),
|
|
2313
|
-
languages:
|
|
2540
|
+
languages: import_zod10.z.record(LocaleTag, EmailStepLanguage).nullish(),
|
|
2314
2541
|
/** The main language's insertions, snapshot from the template when the automation is published. */
|
|
2315
2542
|
insertions: Insertions.nullish()
|
|
2316
2543
|
}).strict();
|
|
2317
|
-
var DelayStep =
|
|
2318
|
-
kind:
|
|
2544
|
+
var DelayStep = import_zod10.z.object({
|
|
2545
|
+
kind: import_zod10.z.literal("delay"),
|
|
2319
2546
|
...label2,
|
|
2320
2547
|
...next,
|
|
2321
|
-
wait:
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2548
|
+
wait: import_zod10.z.discriminatedUnion("mode", [
|
|
2549
|
+
import_zod10.z.object({ mode: import_zod10.z.literal("duration"), seconds: import_zod10.z.number().int().min(1).max(MAX_DELAY_SECONDS) }).strict(),
|
|
2550
|
+
import_zod10.z.object({ mode: import_zod10.z.literal("time_of_day"), at: TimeOfDay }).strict(),
|
|
2551
|
+
import_zod10.z.object({ mode: import_zod10.z.literal("weekday"), weekday: Weekday, at: TimeOfDay }).strict(),
|
|
2325
2552
|
/** A fixed day has no next occurrence, so `continue` is not one of its answers. */
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
mode:
|
|
2553
|
+
import_zod10.z.object({ mode: import_zod10.z.literal("date"), on: DateOnly, at: TimeOfDay, passed: import_zod10.z.enum(["skip", "stop"]) }).strict(),
|
|
2554
|
+
import_zod10.z.object({
|
|
2555
|
+
mode: import_zod10.z.literal("date_property"),
|
|
2329
2556
|
key: ContactPropertyKey,
|
|
2330
2557
|
offset_days: OffsetDays,
|
|
2331
2558
|
at: TimeOfDay,
|
|
@@ -2333,8 +2560,8 @@ var DelayStep = import_zod9.z.object({
|
|
|
2333
2560
|
}).strict()
|
|
2334
2561
|
])
|
|
2335
2562
|
}).strict();
|
|
2336
|
-
var ConditionStep =
|
|
2337
|
-
kind:
|
|
2563
|
+
var ConditionStep = import_zod10.z.object({
|
|
2564
|
+
kind: import_zod10.z.literal("condition"),
|
|
2338
2565
|
...label2,
|
|
2339
2566
|
filter: BoundedAutomationFilter,
|
|
2340
2567
|
yes: StepId.nullable(),
|
|
@@ -2345,49 +2572,49 @@ var ConditionStep = import_zod9.z.object({
|
|
|
2345
2572
|
* neither half means anything without the other: a window with no answer
|
|
2346
2573
|
* for the end of it would be a silent decision.
|
|
2347
2574
|
*/
|
|
2348
|
-
wait_for:
|
|
2575
|
+
wait_for: import_zod10.z.object({ up_to_s: import_zod10.z.number().int().min(1).max(MAX_DELAY_SECONDS), on_timeout: import_zod10.z.enum(["yes", "no"]) }).strict().nullish()
|
|
2349
2576
|
}).strict();
|
|
2350
|
-
var SplitBranchKey =
|
|
2577
|
+
var SplitBranchKey = import_zod10.z.string().regex(/^[A-Za-z0-9_-]{1,32}$/, "letters, digits, underscore and hyphen, 1 to 32");
|
|
2351
2578
|
var MIN_SPLIT_BRANCHES = 2;
|
|
2352
2579
|
var MAX_SPLIT_BRANCHES = 4;
|
|
2353
|
-
var SplitStep =
|
|
2354
|
-
kind:
|
|
2580
|
+
var SplitStep = import_zod10.z.object({
|
|
2581
|
+
kind: import_zod10.z.literal("split"),
|
|
2355
2582
|
...label2,
|
|
2356
|
-
branches:
|
|
2357
|
-
|
|
2583
|
+
branches: import_zod10.z.array(
|
|
2584
|
+
import_zod10.z.object({
|
|
2358
2585
|
key: SplitBranchKey,
|
|
2359
2586
|
/** A whole percentage. Zero is allowed: a branch kept in the flow but switched off. */
|
|
2360
|
-
weight:
|
|
2587
|
+
weight: import_zod10.z.number().int().min(0).max(100),
|
|
2361
2588
|
next: StepId.nullable()
|
|
2362
2589
|
}).strict()
|
|
2363
2590
|
).min(MIN_SPLIT_BRANCHES).max(MAX_SPLIT_BRANCHES).refine((bs) => new Set(bs.map((b) => b.key)).size === bs.length, "each branch needs its own key").refine((bs) => bs.reduce((sum, b) => sum + b.weight, 0) === 100, "the weights have to come to 100")
|
|
2364
2591
|
}).strict();
|
|
2365
|
-
var GotoStep =
|
|
2592
|
+
var GotoStep = import_zod10.z.object({ kind: import_zod10.z.literal("goto"), ...label2, target: StepId.nullable() }).strict();
|
|
2366
2593
|
var MAX_STEP_VISITS = 20;
|
|
2367
|
-
var WebhookStep =
|
|
2368
|
-
var NotifyRecipients =
|
|
2369
|
-
var NotifyStep =
|
|
2370
|
-
kind:
|
|
2594
|
+
var WebhookStep = import_zod10.z.object({ kind: import_zod10.z.literal("webhook"), ...label2, ...next, endpoint_id: Id.nullable(), payload: JsonValue.nullish() }).strict();
|
|
2595
|
+
var NotifyRecipients = import_zod10.z.union([import_zod10.z.literal("owner"), import_zod10.z.literal("admins"), import_zod10.z.object({ member_id: Id }).strict()]);
|
|
2596
|
+
var NotifyStep = import_zod10.z.object({
|
|
2597
|
+
kind: import_zod10.z.literal("notify"),
|
|
2371
2598
|
...label2,
|
|
2372
2599
|
...next,
|
|
2373
2600
|
to: NotifyRecipients,
|
|
2374
2601
|
/** Empty while the step is being written; `not_chosen` refuses to publish it. */
|
|
2375
|
-
subject:
|
|
2376
|
-
body:
|
|
2602
|
+
subject: import_zod10.z.string().max(998),
|
|
2603
|
+
body: import_zod10.z.string().max(1e4)
|
|
2377
2604
|
}).strict();
|
|
2378
|
-
var AutomationStep =
|
|
2605
|
+
var AutomationStep = import_zod10.z.discriminatedUnion("kind", [
|
|
2379
2606
|
EmailStep,
|
|
2380
2607
|
DelayStep,
|
|
2381
2608
|
ConditionStep,
|
|
2382
|
-
|
|
2383
|
-
|
|
2609
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("add_tag"), ...label2, ...next, tag: DraftSlug }).strict(),
|
|
2610
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("remove_tag"), ...label2, ...next, tag: DraftSlug }).strict(),
|
|
2384
2611
|
/** `value` null clears the property, as a contact upsert does. */
|
|
2385
|
-
|
|
2612
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("set_property"), ...label2, ...next, key: DraftPropertyKey, value: JsonValue }).strict(),
|
|
2386
2613
|
/** Subscribing never lifts a suppression: the service checks that, not the flow. */
|
|
2387
|
-
|
|
2614
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("subscribe_topic"), ...label2, ...next, topic: DraftSlug }).strict(),
|
|
2388
2615
|
/** `topic` unsubscribes from the automation's own topic, `all` from every topic. */
|
|
2389
|
-
|
|
2390
|
-
|
|
2616
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("unsubscribe"), ...label2, ...next, scope: import_zod10.z.enum(["topic", "all"]) }).strict(),
|
|
2617
|
+
import_zod10.z.object({ kind: import_zod10.z.literal("exit"), ...label2 }).strict(),
|
|
2391
2618
|
SplitStep,
|
|
2392
2619
|
GotoStep,
|
|
2393
2620
|
WebhookStep,
|
|
@@ -2411,25 +2638,25 @@ function stepTargets(step) {
|
|
|
2411
2638
|
}
|
|
2412
2639
|
}
|
|
2413
2640
|
var MAX_STEPS = 200;
|
|
2414
|
-
var AutomationFlow =
|
|
2415
|
-
triggers:
|
|
2641
|
+
var AutomationFlow = import_zod10.z.object({
|
|
2642
|
+
triggers: import_zod10.z.array(AutomationTrigger).max(MAX_TRIGGERS),
|
|
2416
2643
|
/** The first step. `null` is an empty flow. */
|
|
2417
2644
|
entry: StepId.nullable(),
|
|
2418
|
-
steps:
|
|
2645
|
+
steps: import_zod10.z.record(StepId, AutomationStep)
|
|
2419
2646
|
}).strict();
|
|
2420
2647
|
var emptyFlow = () => ({ triggers: [], entry: null, steps: {} });
|
|
2421
|
-
var QuietHours =
|
|
2648
|
+
var QuietHours = import_zod10.z.object({
|
|
2422
2649
|
start: TimeOfDay,
|
|
2423
2650
|
end: TimeOfDay,
|
|
2424
|
-
weekdays:
|
|
2651
|
+
weekdays: import_zod10.z.array(Weekday).min(1).max(7).nullish()
|
|
2425
2652
|
}).strict();
|
|
2426
2653
|
var RE_ENTRY_MODES = ["off", "after_exit"];
|
|
2427
|
-
var ReEntryMode =
|
|
2654
|
+
var ReEntryMode = import_zod10.z.enum(RE_ENTRY_MODES);
|
|
2428
2655
|
var MAX_RE_ENTRY_COOLDOWN_SECONDS = 365 * 24 * 60 * 60;
|
|
2429
|
-
var AutomationSettings =
|
|
2656
|
+
var AutomationSettings = import_zod10.z.object({
|
|
2430
2657
|
re_entry: ReEntryMode,
|
|
2431
2658
|
/** Seconds a person must wait after leaving before entering again. Only with `after_exit`. */
|
|
2432
|
-
re_entry_cooldown_s:
|
|
2659
|
+
re_entry_cooldown_s: import_zod10.z.number().int().min(0).max(MAX_RE_ENTRY_COOLDOWN_SECONDS).nullish(),
|
|
2433
2660
|
quiet_hours: QuietHours.nullish(),
|
|
2434
2661
|
/** Checked before every step; when it matches, the run ends. */
|
|
2435
2662
|
exit_filter: BoundedAutomationFilter.nullish()
|
|
@@ -2487,18 +2714,18 @@ var AUTOMATION_ISSUE_CODES = [
|
|
|
2487
2714
|
/** A one-off date that is already over everywhere on earth, so it would fire for nobody. */
|
|
2488
2715
|
"date_in_the_past"
|
|
2489
2716
|
];
|
|
2490
|
-
var AutomationIssueCode =
|
|
2491
|
-
var AutomationIssue =
|
|
2717
|
+
var AutomationIssueCode = import_zod10.z.enum(AUTOMATION_ISSUE_CODES);
|
|
2718
|
+
var AutomationIssue = import_zod10.z.object({
|
|
2492
2719
|
code: AutomationIssueCode,
|
|
2493
2720
|
/** The step the issue is about, when it is about one. */
|
|
2494
2721
|
step_id: StepId.nullable(),
|
|
2495
2722
|
/** Where inside the document, for the canvas to point at a field. */
|
|
2496
|
-
path:
|
|
2497
|
-
message:
|
|
2723
|
+
path: import_zod10.z.array(import_zod10.z.union([import_zod10.z.string(), import_zod10.z.number()])),
|
|
2724
|
+
message: import_zod10.z.string()
|
|
2498
2725
|
});
|
|
2499
|
-
var AutomationValidation =
|
|
2500
|
-
ok:
|
|
2501
|
-
issues:
|
|
2726
|
+
var AutomationValidation = import_zod10.z.object({
|
|
2727
|
+
ok: import_zod10.z.boolean(),
|
|
2728
|
+
issues: import_zod10.z.array(AutomationIssue)
|
|
2502
2729
|
});
|
|
2503
2730
|
function validateAutomation(flow, settings, ctx) {
|
|
2504
2731
|
const issues = [];
|
|
@@ -2889,7 +3116,7 @@ function cycles(flow) {
|
|
|
2889
3116
|
return out.sort();
|
|
2890
3117
|
}
|
|
2891
3118
|
var AUTOMATION_STATUSES = ["draft", "active", "paused", "archived"];
|
|
2892
|
-
var AutomationStatus =
|
|
3119
|
+
var AutomationStatus = import_zod10.z.enum(AUTOMATION_STATUSES);
|
|
2893
3120
|
var AUTOMATION_END_REASONS = [
|
|
2894
3121
|
"completed",
|
|
2895
3122
|
"exit_filter",
|
|
@@ -2908,9 +3135,9 @@ var AUTOMATION_END_REASONS = [
|
|
|
2908
3135
|
"ended_by_hand",
|
|
2909
3136
|
"failed"
|
|
2910
3137
|
];
|
|
2911
|
-
var AutomationEndReason =
|
|
3138
|
+
var AutomationEndReason = import_zod10.z.enum(AUTOMATION_END_REASONS);
|
|
2912
3139
|
var AUTOMATION_WAIT_REASONS = ["delay", "quiet_hours", "plan_limit", "sending", "condition"];
|
|
2913
|
-
var AutomationWaitReason =
|
|
3140
|
+
var AutomationWaitReason = import_zod10.z.enum(AUTOMATION_WAIT_REASONS);
|
|
2914
3141
|
var AUTOMATION_ENTRY_REFUSALS = [
|
|
2915
3142
|
"already_inside",
|
|
2916
3143
|
"re_entry_off",
|
|
@@ -2921,26 +3148,26 @@ var AUTOMATION_ENTRY_REFUSALS = [
|
|
|
2921
3148
|
"not_active",
|
|
2922
3149
|
"unknown_contact"
|
|
2923
3150
|
];
|
|
2924
|
-
var AutomationEntryRefusal =
|
|
2925
|
-
var AutomationCounts =
|
|
2926
|
-
started:
|
|
2927
|
-
in_progress:
|
|
2928
|
-
completed:
|
|
2929
|
-
exited:
|
|
2930
|
-
failed:
|
|
2931
|
-
});
|
|
2932
|
-
var Automation =
|
|
3151
|
+
var AutomationEntryRefusal = import_zod10.z.enum(AUTOMATION_ENTRY_REFUSALS);
|
|
3152
|
+
var AutomationCounts = import_zod10.z.object({
|
|
3153
|
+
started: import_zod10.z.number().int().min(0),
|
|
3154
|
+
in_progress: import_zod10.z.number().int().min(0),
|
|
3155
|
+
completed: import_zod10.z.number().int().min(0),
|
|
3156
|
+
exited: import_zod10.z.number().int().min(0),
|
|
3157
|
+
failed: import_zod10.z.number().int().min(0)
|
|
3158
|
+
});
|
|
3159
|
+
var Automation = import_zod10.z.object({
|
|
2933
3160
|
id: Id,
|
|
2934
|
-
name:
|
|
3161
|
+
name: import_zod10.z.string().min(1).max(200),
|
|
2935
3162
|
status: AutomationStatus,
|
|
2936
3163
|
/** Every automation sends under one topic; there are no transactional automations. */
|
|
2937
3164
|
topic: Slug,
|
|
2938
3165
|
provider_id: Id.nullable(),
|
|
2939
3166
|
settings: AutomationSettings,
|
|
2940
3167
|
/** The flow people are running through, null while the automation has never been published. */
|
|
2941
|
-
published_version:
|
|
3168
|
+
published_version: import_zod10.z.number().int().min(1).nullable(),
|
|
2942
3169
|
/** The flow being edited. Increments on every save, like a template's version. */
|
|
2943
|
-
draft_version:
|
|
3170
|
+
draft_version: import_zod10.z.number().int().min(1),
|
|
2944
3171
|
counts: AutomationCounts,
|
|
2945
3172
|
created_at: Timestamp,
|
|
2946
3173
|
updated_at: Timestamp,
|
|
@@ -2953,16 +3180,16 @@ var AutomationWithFlow = Automation.extend({
|
|
|
2953
3180
|
published_flow: AutomationFlow.nullable()
|
|
2954
3181
|
});
|
|
2955
3182
|
var AutomationSummary = Automation;
|
|
2956
|
-
var AutomationCreate =
|
|
2957
|
-
name:
|
|
3183
|
+
var AutomationCreate = import_zod10.z.object({
|
|
3184
|
+
name: import_zod10.z.string().min(1).max(200),
|
|
2958
3185
|
topic: Slug,
|
|
2959
3186
|
provider_id: Id.optional(),
|
|
2960
3187
|
flow: AutomationFlow.optional(),
|
|
2961
3188
|
settings: AutomationSettings.partial().optional()
|
|
2962
3189
|
});
|
|
2963
|
-
var AutomationUpdate =
|
|
2964
|
-
base_version:
|
|
2965
|
-
name:
|
|
3190
|
+
var AutomationUpdate = import_zod10.z.object({
|
|
3191
|
+
base_version: import_zod10.z.number().int().min(1),
|
|
3192
|
+
name: import_zod10.z.string().min(1).max(200).optional(),
|
|
2966
3193
|
topic: Slug.optional(),
|
|
2967
3194
|
provider_id: Id.optional(),
|
|
2968
3195
|
flow: AutomationFlow.optional(),
|
|
@@ -2975,42 +3202,42 @@ var AutomationListQuery = PageQuery.extend({
|
|
|
2975
3202
|
status: AutomationStatus.optional(),
|
|
2976
3203
|
topic: Slug.optional()
|
|
2977
3204
|
});
|
|
2978
|
-
var AutomationPublishRequest =
|
|
3205
|
+
var AutomationPublishRequest = import_zod10.z.object({
|
|
2979
3206
|
/**
|
|
2980
3207
|
* Answer what this publish would do and change nothing, whatever the flow
|
|
2981
3208
|
* looks like. Without it a publish that has no issues and moves nobody
|
|
2982
3209
|
* simply goes ahead, which is right for an API caller and wrong for a
|
|
2983
3210
|
* dialog that is only showing somebody what they are about to do.
|
|
2984
3211
|
*/
|
|
2985
|
-
dry_run:
|
|
2986
|
-
confirm:
|
|
3212
|
+
dry_run: import_zod10.z.boolean().optional(),
|
|
3213
|
+
confirm: import_zod10.z.boolean().optional(),
|
|
2987
3214
|
/** Per removed step: the step its waiting runs move to, or null to end them. */
|
|
2988
|
-
moves:
|
|
3215
|
+
moves: import_zod10.z.record(StepId, StepId.nullable()).optional(),
|
|
2989
3216
|
/** Also enter everyone who matches a trigger's condition right now. */
|
|
2990
|
-
backfill:
|
|
3217
|
+
backfill: import_zod10.z.boolean().optional()
|
|
2991
3218
|
}).strict();
|
|
2992
|
-
var AutomationPublishMove =
|
|
3219
|
+
var AutomationPublishMove = import_zod10.z.object({
|
|
2993
3220
|
step_id: StepId,
|
|
2994
3221
|
/** Why the step's people have to move: it is gone, or its delay changed. */
|
|
2995
|
-
change:
|
|
2996
|
-
waiting:
|
|
3222
|
+
change: import_zod10.z.enum(["removed", "delay_changed", "kind_changed"]),
|
|
3223
|
+
waiting: import_zod10.z.number().int().min(0),
|
|
2997
3224
|
/** Where they go: a step id, or null to end their runs with `step_removed`. */
|
|
2998
3225
|
destination: StepId.nullable()
|
|
2999
3226
|
});
|
|
3000
|
-
var AutomationPublishResult =
|
|
3001
|
-
published:
|
|
3227
|
+
var AutomationPublishResult = import_zod10.z.object({
|
|
3228
|
+
published: import_zod10.z.boolean(),
|
|
3002
3229
|
automation: Automation,
|
|
3003
3230
|
/** Empty when nothing has to move; non-empty and `published` false asks for a confirmation. */
|
|
3004
|
-
moves:
|
|
3231
|
+
moves: import_zod10.z.array(AutomationPublishMove),
|
|
3005
3232
|
/** How many people the backfill entered, or would enter when it is not confirmed. */
|
|
3006
|
-
backfill:
|
|
3007
|
-
issues:
|
|
3008
|
-
});
|
|
3009
|
-
var AutomationDuplicateRequest =
|
|
3010
|
-
var AutomationEnrollRequest =
|
|
3011
|
-
contact_ids:
|
|
3012
|
-
external_ids:
|
|
3013
|
-
emails:
|
|
3233
|
+
backfill: import_zod10.z.number().int().min(0),
|
|
3234
|
+
issues: import_zod10.z.array(AutomationIssue)
|
|
3235
|
+
});
|
|
3236
|
+
var AutomationDuplicateRequest = import_zod10.z.object({ name: import_zod10.z.string().min(1).max(200).optional() }).strict();
|
|
3237
|
+
var AutomationEnrollRequest = import_zod10.z.object({
|
|
3238
|
+
contact_ids: import_zod10.z.array(Id).min(1).max(1e3).optional(),
|
|
3239
|
+
external_ids: import_zod10.z.array(import_zod10.z.string().min(1).max(255)).min(1).max(1e3).optional(),
|
|
3240
|
+
emails: import_zod10.z.array(Email).min(1).max(1e3).optional(),
|
|
3014
3241
|
segment_id: Id.optional(),
|
|
3015
3242
|
/** Where to start them; the flow's entry step by default. */
|
|
3016
3243
|
step_id: StepId.optional()
|
|
@@ -3018,34 +3245,34 @@ var AutomationEnrollRequest = import_zod9.z.object({
|
|
|
3018
3245
|
(v) => [v.contact_ids, v.external_ids, v.emails, v.segment_id].filter((x) => x !== void 0).length === 1,
|
|
3019
3246
|
"name the people exactly one way: contact_ids, external_ids, emails or segment_id"
|
|
3020
3247
|
);
|
|
3021
|
-
var AutomationEnrollment =
|
|
3248
|
+
var AutomationEnrollment = import_zod10.z.object({
|
|
3022
3249
|
contact_id: Id.nullable(),
|
|
3023
3250
|
email: Email.nullable(),
|
|
3024
|
-
external_id:
|
|
3025
|
-
entered:
|
|
3251
|
+
external_id: import_zod10.z.string().nullable(),
|
|
3252
|
+
entered: import_zod10.z.boolean(),
|
|
3026
3253
|
run_id: Id.nullable(),
|
|
3027
3254
|
reason: AutomationEntryRefusal.nullable()
|
|
3028
3255
|
});
|
|
3029
|
-
var AutomationEnrollResult =
|
|
3030
|
-
entered:
|
|
3031
|
-
refused:
|
|
3032
|
-
results:
|
|
3256
|
+
var AutomationEnrollResult = import_zod10.z.object({
|
|
3257
|
+
entered: import_zod10.z.number().int().min(0),
|
|
3258
|
+
refused: import_zod10.z.number().int().min(0),
|
|
3259
|
+
results: import_zod10.z.array(AutomationEnrollment)
|
|
3033
3260
|
});
|
|
3034
|
-
var AutomationRunStatus =
|
|
3035
|
-
var AutomationRun =
|
|
3261
|
+
var AutomationRunStatus = import_zod10.z.enum(["active", "waiting", "completed", "exited", "failed"]);
|
|
3262
|
+
var AutomationRun = import_zod10.z.object({
|
|
3036
3263
|
id: Id,
|
|
3037
3264
|
automation_id: Id,
|
|
3038
3265
|
contact_id: Id,
|
|
3039
3266
|
email: Email,
|
|
3040
|
-
external_id:
|
|
3041
|
-
version:
|
|
3267
|
+
external_id: import_zod10.z.string().nullable(),
|
|
3268
|
+
version: import_zod10.z.number().int().min(1),
|
|
3042
3269
|
status: AutomationRunStatus,
|
|
3043
3270
|
current_step_id: StepId.nullable(),
|
|
3044
3271
|
next_action_at: Timestamp.nullable(),
|
|
3045
3272
|
wait_reason: AutomationWaitReason.nullable(),
|
|
3046
|
-
end_reason:
|
|
3273
|
+
end_reason: import_zod10.z.string().nullable(),
|
|
3047
3274
|
/** What went wrong the last time this run tried to take its step, null otherwise. */
|
|
3048
|
-
last_error:
|
|
3275
|
+
last_error: import_zod10.z.string().nullable(),
|
|
3049
3276
|
entered_at: Timestamp,
|
|
3050
3277
|
ended_at: Timestamp.nullable()
|
|
3051
3278
|
});
|
|
@@ -3055,13 +3282,13 @@ var AutomationRunListQuery = PageQuery.extend({
|
|
|
3055
3282
|
contact_id: Id.optional()
|
|
3056
3283
|
});
|
|
3057
3284
|
var ContactAutomationRun = AutomationRun.extend({
|
|
3058
|
-
automation:
|
|
3285
|
+
automation: import_zod10.z.object({ id: Id, name: import_zod10.z.string(), status: AutomationStatus })
|
|
3059
3286
|
});
|
|
3060
3287
|
var ContactAutomationListQuery = PageQuery.extend({ status: AutomationRunStatus.optional() });
|
|
3061
|
-
var AutomationStepExecution =
|
|
3288
|
+
var AutomationStepExecution = import_zod10.z.object({
|
|
3062
3289
|
step_id: StepId,
|
|
3063
3290
|
step_kind: AutomationStepKind,
|
|
3064
|
-
visit:
|
|
3291
|
+
visit: import_zod10.z.number().int().min(1),
|
|
3065
3292
|
started_at: Timestamp,
|
|
3066
3293
|
finished_at: Timestamp.nullable(),
|
|
3067
3294
|
/**
|
|
@@ -3073,48 +3300,48 @@ var AutomationStepExecution = import_zod9.z.object({
|
|
|
3073
3300
|
*/
|
|
3074
3301
|
outcome: Properties
|
|
3075
3302
|
});
|
|
3076
|
-
var AutomationJourney =
|
|
3303
|
+
var AutomationJourney = import_zod10.z.object({
|
|
3077
3304
|
run: AutomationRun,
|
|
3078
|
-
steps:
|
|
3305
|
+
steps: import_zod10.z.array(AutomationStepExecution)
|
|
3079
3306
|
});
|
|
3080
|
-
var AutomationStepReport =
|
|
3307
|
+
var AutomationStepReport = import_zod10.z.object({
|
|
3081
3308
|
step_id: StepId,
|
|
3082
3309
|
step_kind: AutomationStepKind,
|
|
3083
|
-
reached:
|
|
3084
|
-
waiting:
|
|
3085
|
-
passed:
|
|
3310
|
+
reached: import_zod10.z.number().int().min(0),
|
|
3311
|
+
waiting: import_zod10.z.number().int().min(0),
|
|
3312
|
+
passed: import_zod10.z.number().int().min(0),
|
|
3086
3313
|
/** Per branch, for a condition: how many took `yes` and how many `no`. */
|
|
3087
|
-
branches:
|
|
3314
|
+
branches: import_zod10.z.record(import_zod10.z.number().int().min(0)),
|
|
3088
3315
|
/** The step mailing's id, for an email step of the published version. */
|
|
3089
3316
|
mailing_id: Id.nullable()
|
|
3090
3317
|
});
|
|
3091
|
-
var AutomationReport =
|
|
3318
|
+
var AutomationReport = import_zod10.z.object({
|
|
3092
3319
|
counts: AutomationCounts,
|
|
3093
3320
|
/** Why the people who left did: `AutomationEndReason` to a count. */
|
|
3094
|
-
end_reasons:
|
|
3321
|
+
end_reasons: import_zod10.z.record(import_zod10.z.number().int().min(0)),
|
|
3095
3322
|
/**
|
|
3096
3323
|
* Why people a trigger named did not enter: `AutomationEntryRefusal` to a
|
|
3097
3324
|
* count. Without it a pause, an exclusion or a missing subscription would
|
|
3098
3325
|
* turn people away invisibly.
|
|
3099
3326
|
*/
|
|
3100
|
-
refusals:
|
|
3101
|
-
steps:
|
|
3102
|
-
});
|
|
3103
|
-
var AutomationExitRunRequest =
|
|
3104
|
-
var AutomationRunParams =
|
|
3105
|
-
var AutomationStepParams =
|
|
3106
|
-
var AutomationTestEmailRequest =
|
|
3107
|
-
var AutomationValidateRequest =
|
|
3108
|
-
var EventCreate =
|
|
3327
|
+
refusals: import_zod10.z.record(import_zod10.z.number().int().min(0)),
|
|
3328
|
+
steps: import_zod10.z.array(AutomationStepReport)
|
|
3329
|
+
});
|
|
3330
|
+
var AutomationExitRunRequest = import_zod10.z.object({ reason: import_zod10.z.string().max(200).optional() }).strict();
|
|
3331
|
+
var AutomationRunParams = import_zod10.z.object({ id: Id, run_id: Id });
|
|
3332
|
+
var AutomationStepParams = import_zod10.z.object({ id: Id, step_id: StepId });
|
|
3333
|
+
var AutomationTestEmailRequest = import_zod10.z.object({ to: Email, merge: Properties.optional(), locale: LocaleTag.optional() }).strict();
|
|
3334
|
+
var AutomationValidateRequest = import_zod10.z.object({ flow: AutomationFlow.optional(), settings: AutomationSettings.partial().optional() }).strict();
|
|
3335
|
+
var EventCreate = import_zod10.z.object({
|
|
3109
3336
|
name: EventName,
|
|
3110
|
-
contact:
|
|
3337
|
+
contact: import_zod10.z.object({ external_id: import_zod10.z.string().min(1).max(255).optional(), email: Email.optional(), id: Id.optional() }).refine((c) => [c.external_id, c.email, c.id].filter((x) => x !== void 0).length === 1, "name the contact exactly one way"),
|
|
3111
3338
|
data: Properties.optional(),
|
|
3112
3339
|
occurred_at: Timestamp.optional(),
|
|
3113
|
-
id:
|
|
3340
|
+
id: import_zod10.z.string().min(1).max(128).optional()
|
|
3114
3341
|
}).strict();
|
|
3115
|
-
var Event =
|
|
3342
|
+
var Event = import_zod10.z.object({
|
|
3116
3343
|
id: Id,
|
|
3117
|
-
client_event_id:
|
|
3344
|
+
client_event_id: import_zod10.z.string().nullable(),
|
|
3118
3345
|
name: EventName,
|
|
3119
3346
|
contact_id: Id,
|
|
3120
3347
|
data: Properties,
|
|
@@ -3125,7 +3352,7 @@ var Event = import_zod9.z.object({
|
|
|
3125
3352
|
* hand. Each is then admitted or refused by the runtime on its own rules
|
|
3126
3353
|
* (consent, exclusions, re-entry), which `automations.report` counts.
|
|
3127
3354
|
*/
|
|
3128
|
-
entered:
|
|
3355
|
+
entered: import_zod10.z.number().int().min(0)
|
|
3129
3356
|
});
|
|
3130
3357
|
var EventListQuery = PageQuery.extend({
|
|
3131
3358
|
name: EventName.optional(),
|
|
@@ -3133,19 +3360,15 @@ var EventListQuery = PageQuery.extend({
|
|
|
3133
3360
|
});
|
|
3134
3361
|
|
|
3135
3362
|
// src/workspace.ts
|
|
3136
|
-
var CompanyId =
|
|
3363
|
+
var CompanyId = import_zod11.z.string().min(1).max(64);
|
|
3137
3364
|
var ASSET_POLICIES = ["any", "service_only"];
|
|
3138
|
-
var AssetPolicy =
|
|
3365
|
+
var AssetPolicy = import_zod11.z.enum(ASSET_POLICIES);
|
|
3139
3366
|
var MAX_ALLOWED_ASSET_HOSTS = 20;
|
|
3140
|
-
var AssetHost =
|
|
3141
|
-
var
|
|
3142
|
-
var MAX_MERGE_DEFAULT_LENGTH = 2e3;
|
|
3143
|
-
var MergeFieldName = import_zod10.z.string().regex(/^[a-z][a-z0-9_]*$/, "a merge-field name: lowercase letters, digits and underscores, starting with a letter").max(64);
|
|
3144
|
-
var MergeDefaultValue = import_zod10.z.union([import_zod10.z.string().max(MAX_MERGE_DEFAULT_LENGTH), import_zod10.z.number().finite(), import_zod10.z.boolean()]);
|
|
3145
|
-
var MergeDefaults = import_zod10.z.record(MergeFieldName, MergeDefaultValue).refine((m) => Object.keys(m).length <= MAX_MERGE_DEFAULTS, `at most ${MAX_MERGE_DEFAULTS} merge defaults`).refine((m) => !Object.keys(m).some((k) => k in RESERVED_MERGE_FIELDS), {
|
|
3367
|
+
var AssetHost = import_zod11.z.string().trim().toLowerCase().min(1).max(253).regex(/^(?=.{1,253}(?::\d{1,5})?$)[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+(:\d{1,5})?$/, "a host name such as example.com");
|
|
3368
|
+
var MergeDefaults = import_zod11.z.record(MergeFieldName, MergeDefaultValue).refine((m) => Object.keys(m).length <= MAX_MERGE_DEFAULTS, `at most ${MAX_MERGE_DEFAULTS} merge defaults`).refine((m) => !Object.keys(m).some((k) => k in RESERVED_MERGE_FIELDS), {
|
|
3146
3369
|
message: `a reserved merge field (${Object.keys(RESERVED_MERGE_FIELDS).join(", ")}) cannot have a workspace default`
|
|
3147
3370
|
});
|
|
3148
|
-
var WorkspaceSettings =
|
|
3371
|
+
var WorkspaceSettings = import_zod11.z.object({
|
|
3149
3372
|
/**
|
|
3150
3373
|
* The workspace's main language (a {@link LocaleTag}, e.g. "de"): the main
|
|
3151
3374
|
* language of a new template, and of the hosted pages when nothing else
|
|
@@ -3158,9 +3381,9 @@ var WorkspaceSettings = import_zod10.z.object({
|
|
|
3158
3381
|
* each; the hosted pages are offered in those of them they support (English,
|
|
3159
3382
|
* German, French, Italian, Spanish). The service stores canonical casing.
|
|
3160
3383
|
*/
|
|
3161
|
-
locales:
|
|
3384
|
+
locales: import_zod11.z.array(LocaleTag).min(1).max(20).refine((l) => new Set(l.map((t) => t.toLowerCase())).size === l.length, "a language appears twice"),
|
|
3162
3385
|
/** Open and click tracking. Off by default, opt-in per workspace. */
|
|
3163
|
-
tracking_enabled:
|
|
3386
|
+
tracking_enabled: import_zod11.z.boolean(),
|
|
3164
3387
|
/** Where images, stylesheets and fonts in a mail may load from. `any` by default. */
|
|
3165
3388
|
asset_policy: AssetPolicy,
|
|
3166
3389
|
/**
|
|
@@ -3168,7 +3391,7 @@ var WorkspaceSettings = import_zod10.z.object({
|
|
|
3168
3391
|
* the workspace's website, typically. Empty by default. Ignored under `any`,
|
|
3169
3392
|
* which allows everything already.
|
|
3170
3393
|
*/
|
|
3171
|
-
allowed_asset_hosts:
|
|
3394
|
+
allowed_asset_hosts: import_zod11.z.array(AssetHost).max(MAX_ALLOWED_ASSET_HOSTS),
|
|
3172
3395
|
/** Merge values every mail of the workspace can use (see `MergeDefaults`). Empty by default. */
|
|
3173
3396
|
merge_defaults: MergeDefaults,
|
|
3174
3397
|
/**
|
|
@@ -3177,10 +3400,10 @@ var WorkspaceSettings = import_zod10.z.object({
|
|
|
3177
3400
|
*/
|
|
3178
3401
|
default_timezone: TimezoneName.nullable()
|
|
3179
3402
|
});
|
|
3180
|
-
var Workspace =
|
|
3403
|
+
var Workspace = import_zod11.z.object({
|
|
3181
3404
|
id: Id,
|
|
3182
3405
|
slug: Slug,
|
|
3183
|
-
name:
|
|
3406
|
+
name: import_zod11.z.string().min(1).max(120),
|
|
3184
3407
|
settings: WorkspaceSettings,
|
|
3185
3408
|
/**
|
|
3186
3409
|
* The auth-brain company (tenant) the workspace was created for, or null for
|
|
@@ -3191,13 +3414,13 @@ var Workspace = import_zod10.z.object({
|
|
|
3191
3414
|
created_at: Timestamp,
|
|
3192
3415
|
updated_at: Timestamp
|
|
3193
3416
|
});
|
|
3194
|
-
var WorkspaceCreate =
|
|
3417
|
+
var WorkspaceCreate = import_zod11.z.object({
|
|
3195
3418
|
slug: Slug,
|
|
3196
|
-
name:
|
|
3419
|
+
name: import_zod11.z.string().min(1).max(120),
|
|
3197
3420
|
settings: WorkspaceSettings.partial().optional(),
|
|
3198
|
-
owner:
|
|
3421
|
+
owner: import_zod11.z.object({
|
|
3199
3422
|
email: Email,
|
|
3200
|
-
name:
|
|
3423
|
+
name: import_zod11.z.string().max(200).nullable().optional()
|
|
3201
3424
|
}),
|
|
3202
3425
|
/**
|
|
3203
3426
|
* The signed-in person's active auth-brain company. The dashboard always
|
|
@@ -3207,49 +3430,49 @@ var WorkspaceCreate = import_zod10.z.object({
|
|
|
3207
3430
|
*/
|
|
3208
3431
|
company_id: CompanyId.optional()
|
|
3209
3432
|
});
|
|
3210
|
-
var WorkspaceUpdate =
|
|
3211
|
-
name:
|
|
3433
|
+
var WorkspaceUpdate = import_zod11.z.object({
|
|
3434
|
+
name: import_zod11.z.string().min(1).max(120),
|
|
3212
3435
|
settings: WorkspaceSettings.partial()
|
|
3213
3436
|
}).partial().refine((v) => Object.keys(v).length > 0, "at least one field");
|
|
3214
|
-
var WorkspaceMove =
|
|
3437
|
+
var WorkspaceMove = import_zod11.z.object({ company_id: CompanyId });
|
|
3215
3438
|
var MEMBER_ROLES = ["owner", "admin", "editor", "viewer"];
|
|
3216
|
-
var MemberRole =
|
|
3439
|
+
var MemberRole = import_zod11.z.enum(MEMBER_ROLES);
|
|
3217
3440
|
var WorkspaceMembership = Workspace.extend({ role: MemberRole });
|
|
3218
|
-
var Member =
|
|
3441
|
+
var Member = import_zod11.z.object({
|
|
3219
3442
|
id: Id,
|
|
3220
3443
|
/** The person's auth-brain subject. */
|
|
3221
|
-
subject:
|
|
3444
|
+
subject: import_zod11.z.string().min(1).max(255),
|
|
3222
3445
|
email: Email,
|
|
3223
|
-
name:
|
|
3446
|
+
name: import_zod11.z.string().max(200).nullable(),
|
|
3224
3447
|
role: MemberRole,
|
|
3225
3448
|
created_at: Timestamp
|
|
3226
3449
|
});
|
|
3227
|
-
var MemberCreate =
|
|
3228
|
-
subject:
|
|
3450
|
+
var MemberCreate = import_zod11.z.object({
|
|
3451
|
+
subject: import_zod11.z.string().min(1).max(255),
|
|
3229
3452
|
email: Email,
|
|
3230
|
-
name:
|
|
3453
|
+
name: import_zod11.z.string().max(200).nullable().optional(),
|
|
3231
3454
|
role: MemberRole
|
|
3232
3455
|
});
|
|
3233
|
-
var MemberUpdate =
|
|
3456
|
+
var MemberUpdate = import_zod11.z.object({ role: MemberRole });
|
|
3234
3457
|
var API_KEY_SCOPES = ["full", "read", "send"];
|
|
3235
|
-
var ApiKeyScope =
|
|
3236
|
-
var ApiKey =
|
|
3458
|
+
var ApiKeyScope = import_zod11.z.enum(API_KEY_SCOPES);
|
|
3459
|
+
var ApiKey = import_zod11.z.object({
|
|
3237
3460
|
id: Id,
|
|
3238
|
-
name:
|
|
3461
|
+
name: import_zod11.z.string().min(1).max(120),
|
|
3239
3462
|
/** The first characters of the key, for recognising it in a list. */
|
|
3240
|
-
prefix:
|
|
3463
|
+
prefix: import_zod11.z.string().min(4).max(32),
|
|
3241
3464
|
scope: ApiKeyScope,
|
|
3242
3465
|
last_used_at: Timestamp.nullable(),
|
|
3243
3466
|
revoked_at: Timestamp.nullable(),
|
|
3244
3467
|
created_at: Timestamp
|
|
3245
3468
|
});
|
|
3246
|
-
var ApiKeyCreate =
|
|
3247
|
-
name:
|
|
3469
|
+
var ApiKeyCreate = import_zod11.z.object({
|
|
3470
|
+
name: import_zod11.z.string().min(1).max(120),
|
|
3248
3471
|
/** Omitted means `full`. */
|
|
3249
3472
|
scope: ApiKeyScope.optional()
|
|
3250
3473
|
});
|
|
3251
|
-
var ApiKeyCreated =
|
|
3252
|
-
key:
|
|
3474
|
+
var ApiKeyCreated = import_zod11.z.object({
|
|
3475
|
+
key: import_zod11.z.string().min(20),
|
|
3253
3476
|
api_key: ApiKey
|
|
3254
3477
|
});
|
|
3255
3478
|
var AUDIT_ACTIONS = [
|
|
@@ -3338,29 +3561,29 @@ var AUDIT_ACTIONS = [
|
|
|
3338
3561
|
"automation.run_ended",
|
|
3339
3562
|
"event.recorded"
|
|
3340
3563
|
];
|
|
3341
|
-
var AuditAction =
|
|
3342
|
-
var AuditActor =
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
type:
|
|
3564
|
+
var AuditAction = import_zod11.z.enum(AUDIT_ACTIONS);
|
|
3565
|
+
var AuditActor = import_zod11.z.discriminatedUnion("type", [
|
|
3566
|
+
import_zod11.z.object({ type: import_zod11.z.literal("member"), member_id: Id, subject: import_zod11.z.string().min(1) }),
|
|
3567
|
+
import_zod11.z.object({
|
|
3568
|
+
type: import_zod11.z.literal("api_key"),
|
|
3346
3569
|
api_key_id: Id,
|
|
3347
3570
|
/**
|
|
3348
3571
|
* Who the client's application said it was acting for, from
|
|
3349
3572
|
* `ON_BEHALF_OF_HEADER`: reported by that application, never verified.
|
|
3350
3573
|
* Absent when the call carried no label.
|
|
3351
3574
|
*/
|
|
3352
|
-
on_behalf_of:
|
|
3575
|
+
on_behalf_of: import_zod11.z.string().min(1).max(ON_BEHALF_OF_MAX_LENGTH).optional()
|
|
3353
3576
|
}),
|
|
3354
3577
|
/** The service itself (the worker, a bounce, the hosted unsubscribe page). */
|
|
3355
|
-
|
|
3578
|
+
import_zod11.z.object({ type: import_zod11.z.literal("system"), reason: import_zod11.z.string().min(1).max(200) })
|
|
3356
3579
|
]);
|
|
3357
|
-
var AuditEntry =
|
|
3580
|
+
var AuditEntry = import_zod11.z.object({
|
|
3358
3581
|
id: Id,
|
|
3359
3582
|
action: AuditAction,
|
|
3360
3583
|
actor: AuditActor,
|
|
3361
|
-
target_type:
|
|
3584
|
+
target_type: import_zod11.z.string().min(1).max(64),
|
|
3362
3585
|
target_id: Id.nullable(),
|
|
3363
|
-
details:
|
|
3586
|
+
details: import_zod11.z.record(import_zod11.z.unknown()),
|
|
3364
3587
|
created_at: Timestamp
|
|
3365
3588
|
});
|
|
3366
3589
|
var AuditQuery = PageQuery.extend({
|
|
@@ -3369,12 +3592,12 @@ var AuditQuery = PageQuery.extend({
|
|
|
3369
3592
|
});
|
|
3370
3593
|
|
|
3371
3594
|
// src/invites.ts
|
|
3372
|
-
var
|
|
3595
|
+
var import_zod12 = require("zod");
|
|
3373
3596
|
var INVITE_STATUSES = ["pending", "accepted", "revoked", "expired"];
|
|
3374
|
-
var InviteStatus =
|
|
3597
|
+
var InviteStatus = import_zod12.z.enum(INVITE_STATUSES);
|
|
3375
3598
|
var DEFAULT_INVITE_TTL_DAYS = 7;
|
|
3376
3599
|
var MAX_INVITE_TTL_DAYS = 30;
|
|
3377
|
-
var Invite =
|
|
3600
|
+
var Invite = import_zod12.z.object({
|
|
3378
3601
|
id: Id,
|
|
3379
3602
|
/** Stored lowercased; only a person signed in with this address can accept. */
|
|
3380
3603
|
email: Email,
|
|
@@ -3382,32 +3605,32 @@ var Invite = import_zod11.z.object({
|
|
|
3382
3605
|
/** Derived from the timestamps below, never stored. */
|
|
3383
3606
|
status: InviteStatus,
|
|
3384
3607
|
/** The member who invited, while they are still one (null after they left). */
|
|
3385
|
-
invited_by:
|
|
3608
|
+
invited_by: import_zod12.z.object({ member_id: Id.nullable(), email: Email.nullable() }),
|
|
3386
3609
|
expires_at: Timestamp,
|
|
3387
3610
|
accepted_at: Timestamp.nullable(),
|
|
3388
3611
|
revoked_at: Timestamp.nullable(),
|
|
3389
3612
|
created_at: Timestamp
|
|
3390
3613
|
});
|
|
3391
|
-
var InviteCreate =
|
|
3614
|
+
var InviteCreate = import_zod12.z.object({
|
|
3392
3615
|
email: Email,
|
|
3393
3616
|
role: MemberRole,
|
|
3394
|
-
expires_in_days:
|
|
3617
|
+
expires_in_days: import_zod12.z.number().int().min(1).max(MAX_INVITE_TTL_DAYS).optional()
|
|
3395
3618
|
});
|
|
3396
|
-
var InviteCreated =
|
|
3619
|
+
var InviteCreated = import_zod12.z.object({
|
|
3397
3620
|
invite: Invite,
|
|
3398
|
-
token:
|
|
3621
|
+
token: import_zod12.z.string().min(32).max(128)
|
|
3399
3622
|
});
|
|
3400
3623
|
var InviteListQuery = PageQuery.extend({
|
|
3401
3624
|
status: InviteStatus.optional()
|
|
3402
3625
|
});
|
|
3403
|
-
var InviteAccept =
|
|
3404
|
-
token:
|
|
3626
|
+
var InviteAccept = import_zod12.z.object({
|
|
3627
|
+
token: import_zod12.z.string().min(32).max(128),
|
|
3405
3628
|
email: Email,
|
|
3406
|
-
name:
|
|
3629
|
+
name: import_zod12.z.string().max(200).nullable().optional()
|
|
3407
3630
|
});
|
|
3408
|
-
var InviteAccepted =
|
|
3631
|
+
var InviteAccepted = import_zod12.z.object({
|
|
3409
3632
|
workspace: WorkspaceMembership,
|
|
3410
|
-
already_member:
|
|
3633
|
+
already_member: import_zod12.z.boolean()
|
|
3411
3634
|
});
|
|
3412
3635
|
var INVITE_REFUSAL_REASONS = ["email_mismatch", "inviter_lacks_role", "expired", "revoked", "accepted"];
|
|
3413
3636
|
|
|
@@ -4037,13 +4260,13 @@ function renameInsertionEverywhere(drafts, from, rawTo) {
|
|
|
4037
4260
|
}
|
|
4038
4261
|
|
|
4039
4262
|
// src/providers.ts
|
|
4040
|
-
var
|
|
4263
|
+
var import_zod13 = require("zod");
|
|
4041
4264
|
var PROVIDER_KINDS = ["smtp", "resend"];
|
|
4042
|
-
var ProviderKind =
|
|
4043
|
-
var ProviderPolicy =
|
|
4044
|
-
daily_recipient_budget:
|
|
4045
|
-
min_interval_ms:
|
|
4046
|
-
max_recipients_per_message:
|
|
4265
|
+
var ProviderKind = import_zod13.z.enum(PROVIDER_KINDS);
|
|
4266
|
+
var ProviderPolicy = import_zod13.z.object({
|
|
4267
|
+
daily_recipient_budget: import_zod13.z.number().int().min(1).max(1e7),
|
|
4268
|
+
min_interval_ms: import_zod13.z.number().int().min(0).max(36e5),
|
|
4269
|
+
max_recipients_per_message: import_zod13.z.number().int().min(1).max(1e3)
|
|
4047
4270
|
});
|
|
4048
4271
|
var ICLOUD_SMTP_POLICY = {
|
|
4049
4272
|
daily_recipient_budget: 800,
|
|
@@ -4051,17 +4274,17 @@ var ICLOUD_SMTP_POLICY = {
|
|
|
4051
4274
|
max_recipients_per_message: 1
|
|
4052
4275
|
};
|
|
4053
4276
|
var SMTP_SECURITY = ["tls", "starttls"];
|
|
4054
|
-
var SmtpConfigBase =
|
|
4055
|
-
host:
|
|
4056
|
-
port:
|
|
4277
|
+
var SmtpConfigBase = import_zod13.z.object({
|
|
4278
|
+
host: import_zod13.z.string().min(1).max(255),
|
|
4279
|
+
port: import_zod13.z.number().int().min(1).max(65535),
|
|
4057
4280
|
/** `tls` connects encrypted (465), `starttls` upgrades (587). Never plaintext. */
|
|
4058
|
-
security:
|
|
4059
|
-
username:
|
|
4281
|
+
security: import_zod13.z.enum(SMTP_SECURITY),
|
|
4282
|
+
username: import_zod13.z.string().min(1).max(255)
|
|
4060
4283
|
});
|
|
4061
|
-
var ResendConfigBase =
|
|
4062
|
-
var ProviderRejections =
|
|
4063
|
-
count:
|
|
4064
|
-
last_error:
|
|
4284
|
+
var ResendConfigBase = import_zod13.z.object({});
|
|
4285
|
+
var ProviderRejections = import_zod13.z.object({
|
|
4286
|
+
count: import_zod13.z.number().int().min(0),
|
|
4287
|
+
last_error: import_zod13.z.string().nullable(),
|
|
4065
4288
|
last_at: Timestamp.nullable(),
|
|
4066
4289
|
/**
|
|
4067
4290
|
* The last time the bounce circuit breaker tripped on one of this provider's
|
|
@@ -4071,59 +4294,59 @@ var ProviderRejections = import_zod12.z.object({
|
|
|
4071
4294
|
* run's bounce blocks were undone and the mailing paused. `sample` is the
|
|
4072
4295
|
* reply that tripped it.
|
|
4073
4296
|
*/
|
|
4074
|
-
anomaly:
|
|
4297
|
+
anomaly: import_zod13.z.object({
|
|
4075
4298
|
at: Timestamp,
|
|
4076
4299
|
/** `mailing`: one mailing was paused. `provider`: 5 refusals in a row with the same reply across the provider's sends (test sends and one-recipient mailings included) within 24 hours. */
|
|
4077
|
-
scope:
|
|
4300
|
+
scope: import_zod13.z.enum(["mailing", "provider"]),
|
|
4078
4301
|
/**
|
|
4079
4302
|
* True while the provider-wide breaker is open: no bounce blocks through
|
|
4080
4303
|
* this provider, test sends refused and mailings not started or resumed
|
|
4081
4304
|
* (`provider_anomaly`), until an admin clears it (`providers.clearAnomaly`).
|
|
4082
4305
|
*/
|
|
4083
|
-
blocking:
|
|
4306
|
+
blocking: import_zod13.z.boolean(),
|
|
4084
4307
|
mailing_id: Id.nullable(),
|
|
4085
|
-
reason:
|
|
4086
|
-
sample:
|
|
4308
|
+
reason: import_zod13.z.string(),
|
|
4309
|
+
sample: import_zod13.z.string()
|
|
4087
4310
|
}).nullable()
|
|
4088
4311
|
});
|
|
4089
|
-
var ProviderEvents =
|
|
4090
|
-
status:
|
|
4091
|
-
source:
|
|
4092
|
-
url:
|
|
4093
|
-
error:
|
|
4312
|
+
var ProviderEvents = import_zod13.z.object({
|
|
4313
|
+
status: import_zod13.z.enum(["active", "needs_secret"]),
|
|
4314
|
+
source: import_zod13.z.enum(["automatic", "manual"]).nullable(),
|
|
4315
|
+
url: import_zod13.z.string().url(),
|
|
4316
|
+
error: import_zod13.z.string().nullable(),
|
|
4094
4317
|
/**
|
|
4095
4318
|
* Events that named an email this provider never sent through the service
|
|
4096
4319
|
* (another workspace or system sharing the Resend account): counted, never
|
|
4097
4320
|
* acted on.
|
|
4098
4321
|
*/
|
|
4099
|
-
unmatched:
|
|
4322
|
+
unmatched: import_zod13.z.number().int().min(0)
|
|
4100
4323
|
});
|
|
4101
4324
|
var RESEND_EVENT_TYPES = ["email.bounced", "email.complained", "email.delivery_delayed"];
|
|
4102
|
-
var ResendSigningSecret =
|
|
4103
|
-
var ProviderEventsSecret =
|
|
4325
|
+
var ResendSigningSecret = import_zod13.z.string().max(200).regex(/^whsec_[A-Za-z0-9+/]{16,}={0,2}$/, "must be the signing secret Resend shows, starting with whsec_");
|
|
4326
|
+
var ProviderEventsSecret = import_zod13.z.object({ signing_secret: ResendSigningSecret });
|
|
4104
4327
|
var ProviderFields = {
|
|
4105
|
-
name:
|
|
4106
|
-
from_name:
|
|
4328
|
+
name: import_zod13.z.string().min(1).max(120),
|
|
4329
|
+
from_name: import_zod13.z.string().min(1).max(120),
|
|
4107
4330
|
from_email: Email,
|
|
4108
4331
|
reply_to: Email.nullable(),
|
|
4109
4332
|
policy: ProviderPolicy
|
|
4110
4333
|
};
|
|
4111
|
-
var Provider =
|
|
4112
|
-
|
|
4334
|
+
var Provider = import_zod13.z.discriminatedUnion("kind", [
|
|
4335
|
+
import_zod13.z.object({
|
|
4113
4336
|
id: Id,
|
|
4114
|
-
kind:
|
|
4337
|
+
kind: import_zod13.z.literal("smtp"),
|
|
4115
4338
|
config: SmtpConfigBase,
|
|
4116
|
-
has_secret:
|
|
4339
|
+
has_secret: import_zod13.z.boolean(),
|
|
4117
4340
|
...ProviderFields,
|
|
4118
4341
|
rejections: ProviderRejections,
|
|
4119
4342
|
created_at: Timestamp,
|
|
4120
4343
|
updated_at: Timestamp
|
|
4121
4344
|
}),
|
|
4122
|
-
|
|
4345
|
+
import_zod13.z.object({
|
|
4123
4346
|
id: Id,
|
|
4124
|
-
kind:
|
|
4347
|
+
kind: import_zod13.z.literal("resend"),
|
|
4125
4348
|
config: ResendConfigBase,
|
|
4126
|
-
has_secret:
|
|
4349
|
+
has_secret: import_zod13.z.boolean(),
|
|
4127
4350
|
...ProviderFields,
|
|
4128
4351
|
rejections: ProviderRejections,
|
|
4129
4352
|
events: ProviderEvents,
|
|
@@ -4131,31 +4354,31 @@ var Provider = import_zod12.z.discriminatedUnion("kind", [
|
|
|
4131
4354
|
updated_at: Timestamp
|
|
4132
4355
|
})
|
|
4133
4356
|
]);
|
|
4134
|
-
var ProviderCreate =
|
|
4135
|
-
|
|
4136
|
-
kind:
|
|
4137
|
-
config: SmtpConfigBase.extend({ password:
|
|
4357
|
+
var ProviderCreate = import_zod13.z.discriminatedUnion("kind", [
|
|
4358
|
+
import_zod13.z.object({
|
|
4359
|
+
kind: import_zod13.z.literal("smtp"),
|
|
4360
|
+
config: SmtpConfigBase.extend({ password: import_zod13.z.string().min(1).max(1024) }),
|
|
4138
4361
|
...ProviderFields
|
|
4139
4362
|
}),
|
|
4140
|
-
|
|
4141
|
-
kind:
|
|
4142
|
-
config: ResendConfigBase.extend({ api_key:
|
|
4363
|
+
import_zod13.z.object({
|
|
4364
|
+
kind: import_zod13.z.literal("resend"),
|
|
4365
|
+
config: ResendConfigBase.extend({ api_key: import_zod13.z.string().min(1).max(1024) }),
|
|
4143
4366
|
...ProviderFields
|
|
4144
4367
|
})
|
|
4145
4368
|
]);
|
|
4146
|
-
var ProviderUpdate =
|
|
4147
|
-
|
|
4148
|
-
kind:
|
|
4149
|
-
config: SmtpConfigBase.extend({ password:
|
|
4369
|
+
var ProviderUpdate = import_zod13.z.discriminatedUnion("kind", [
|
|
4370
|
+
import_zod13.z.object({
|
|
4371
|
+
kind: import_zod13.z.literal("smtp"),
|
|
4372
|
+
config: SmtpConfigBase.extend({ password: import_zod13.z.string().min(1).max(1024).optional() }).partial().optional(),
|
|
4150
4373
|
name: ProviderFields.name.optional(),
|
|
4151
4374
|
from_name: ProviderFields.from_name.optional(),
|
|
4152
4375
|
from_email: ProviderFields.from_email.optional(),
|
|
4153
4376
|
reply_to: ProviderFields.reply_to.optional(),
|
|
4154
4377
|
policy: ProviderPolicy.partial().optional()
|
|
4155
4378
|
}),
|
|
4156
|
-
|
|
4157
|
-
kind:
|
|
4158
|
-
config: ResendConfigBase.extend({ api_key:
|
|
4379
|
+
import_zod13.z.object({
|
|
4380
|
+
kind: import_zod13.z.literal("resend"),
|
|
4381
|
+
config: ResendConfigBase.extend({ api_key: import_zod13.z.string().min(1).max(1024).optional() }).optional(),
|
|
4159
4382
|
name: ProviderFields.name.optional(),
|
|
4160
4383
|
from_name: ProviderFields.from_name.optional(),
|
|
4161
4384
|
from_email: ProviderFields.from_email.optional(),
|
|
@@ -4163,48 +4386,48 @@ var ProviderUpdate = import_zod12.z.discriminatedUnion("kind", [
|
|
|
4163
4386
|
policy: ProviderPolicy.partial().optional()
|
|
4164
4387
|
})
|
|
4165
4388
|
]);
|
|
4166
|
-
var ProviderUsage =
|
|
4389
|
+
var ProviderUsage = import_zod13.z.object({
|
|
4167
4390
|
provider_id: Id,
|
|
4168
|
-
recipients_last_24h:
|
|
4169
|
-
remaining_budget:
|
|
4391
|
+
recipients_last_24h: import_zod13.z.number().int().min(0),
|
|
4392
|
+
remaining_budget: import_zod13.z.number().int().min(0),
|
|
4170
4393
|
/** When enough of the rolling window frees up to send again, if exhausted. */
|
|
4171
4394
|
next_capacity_at: Timestamp.nullable()
|
|
4172
4395
|
});
|
|
4173
|
-
var ProviderVerifyResult =
|
|
4174
|
-
ok:
|
|
4175
|
-
error:
|
|
4396
|
+
var ProviderVerifyResult = import_zod13.z.object({
|
|
4397
|
+
ok: import_zod13.z.boolean(),
|
|
4398
|
+
error: import_zod13.z.string().nullable()
|
|
4176
4399
|
});
|
|
4177
4400
|
|
|
4178
4401
|
// src/contacts.ts
|
|
4179
|
-
var
|
|
4180
|
-
var Topic =
|
|
4402
|
+
var import_zod14 = require("zod");
|
|
4403
|
+
var Topic = import_zod14.z.object({
|
|
4181
4404
|
id: Id,
|
|
4182
4405
|
slug: Slug,
|
|
4183
|
-
name:
|
|
4406
|
+
name: import_zod14.z.string().min(1).max(120),
|
|
4184
4407
|
/** Shown on the hosted preference page. */
|
|
4185
|
-
description:
|
|
4408
|
+
description: import_zod14.z.string().max(1e3).nullable(),
|
|
4186
4409
|
/** Translations of `name` and `description` per locale, for the hosted page. */
|
|
4187
|
-
translations:
|
|
4188
|
-
|
|
4410
|
+
translations: import_zod14.z.record(
|
|
4411
|
+
import_zod14.z.object({ name: import_zod14.z.string().min(1).max(120), description: import_zod14.z.string().max(1e3).nullable() })
|
|
4189
4412
|
),
|
|
4190
4413
|
created_at: Timestamp,
|
|
4191
4414
|
updated_at: Timestamp
|
|
4192
4415
|
});
|
|
4193
|
-
var TopicCreate =
|
|
4416
|
+
var TopicCreate = import_zod14.z.object({
|
|
4194
4417
|
slug: Slug,
|
|
4195
|
-
name:
|
|
4196
|
-
description:
|
|
4418
|
+
name: import_zod14.z.string().min(1).max(120),
|
|
4419
|
+
description: import_zod14.z.string().max(1e3).optional(),
|
|
4197
4420
|
translations: Topic.shape.translations.optional()
|
|
4198
4421
|
});
|
|
4199
4422
|
var TopicUpdate = TopicCreate.omit({ slug: true }).partial().refine((v) => Object.keys(v).length > 0, "at least one field");
|
|
4200
|
-
var Contact =
|
|
4423
|
+
var Contact = import_zod14.z.object({
|
|
4201
4424
|
id: Id,
|
|
4202
|
-
external_id:
|
|
4425
|
+
external_id: import_zod14.z.string().min(1).max(255).nullable(),
|
|
4203
4426
|
/** Stored lowercased, unique per workspace. */
|
|
4204
4427
|
email: Email,
|
|
4205
|
-
first_name:
|
|
4206
|
-
last_name:
|
|
4207
|
-
locale:
|
|
4428
|
+
first_name: import_zod14.z.string().max(200).nullable(),
|
|
4429
|
+
last_name: import_zod14.z.string().max(200).nullable(),
|
|
4430
|
+
locale: import_zod14.z.string().min(2).max(35).nullable(),
|
|
4208
4431
|
/**
|
|
4209
4432
|
* The person's own time zone, an IANA name such as `Europe/Berlin` (A1).
|
|
4210
4433
|
* Every wall clock an automation waits for is read in it, falling back to the
|
|
@@ -4212,65 +4435,65 @@ var Contact = import_zod13.z.object({
|
|
|
4212
4435
|
*/
|
|
4213
4436
|
timezone: TimezoneName.nullable(),
|
|
4214
4437
|
properties: Properties,
|
|
4215
|
-
topics:
|
|
4438
|
+
topics: import_zod14.z.array(Slug),
|
|
4216
4439
|
/** The slugs of the contact's tags (S4). */
|
|
4217
|
-
tags:
|
|
4440
|
+
tags: import_zod14.z.array(Slug),
|
|
4218
4441
|
created_at: Timestamp,
|
|
4219
4442
|
updated_at: Timestamp
|
|
4220
4443
|
});
|
|
4221
|
-
var ContactUpsert =
|
|
4222
|
-
external_id:
|
|
4444
|
+
var ContactUpsert = import_zod14.z.object({
|
|
4445
|
+
external_id: import_zod14.z.string().min(1).max(255).optional(),
|
|
4223
4446
|
email: Email.optional(),
|
|
4224
|
-
first_name:
|
|
4225
|
-
last_name:
|
|
4226
|
-
locale:
|
|
4447
|
+
first_name: import_zod14.z.string().max(200).nullable().optional(),
|
|
4448
|
+
last_name: import_zod14.z.string().max(200).nullable().optional(),
|
|
4449
|
+
locale: import_zod14.z.string().min(2).max(35).nullable().optional(),
|
|
4227
4450
|
timezone: TimezoneName.nullable().optional(),
|
|
4228
4451
|
properties: Properties.optional(),
|
|
4229
|
-
topics:
|
|
4452
|
+
topics: import_zod14.z.array(Slug).max(100).optional()
|
|
4230
4453
|
}).refine((v) => v.external_id !== void 0 || v.email !== void 0, {
|
|
4231
4454
|
message: "external_id or email is required",
|
|
4232
4455
|
path: ["email"]
|
|
4233
4456
|
});
|
|
4234
|
-
var ContactUpsertResult =
|
|
4457
|
+
var ContactUpsertResult = import_zod14.z.object({
|
|
4235
4458
|
contact: Contact,
|
|
4236
|
-
created:
|
|
4459
|
+
created: import_zod14.z.boolean()
|
|
4237
4460
|
});
|
|
4238
4461
|
var ContactListQuery = PageQuery.extend({
|
|
4239
|
-
email:
|
|
4240
|
-
external_id:
|
|
4462
|
+
email: import_zod14.z.string().min(1).max(254).optional(),
|
|
4463
|
+
external_id: import_zod14.z.string().min(1).max(255).optional(),
|
|
4241
4464
|
topic: Slug.optional()
|
|
4242
4465
|
});
|
|
4243
|
-
var ContactErased =
|
|
4244
|
-
ok:
|
|
4245
|
-
erased_messages:
|
|
4246
|
-
erased_recipients:
|
|
4247
|
-
suppressions_kept:
|
|
4466
|
+
var ContactErased = import_zod14.z.object({
|
|
4467
|
+
ok: import_zod14.z.literal(true),
|
|
4468
|
+
erased_messages: import_zod14.z.number().int().min(0),
|
|
4469
|
+
erased_recipients: import_zod14.z.number().int().min(0),
|
|
4470
|
+
suppressions_kept: import_zod14.z.number().int().min(0)
|
|
4248
4471
|
});
|
|
4249
4472
|
var SUPPRESSION_REASONS = ["unsubscribed", "bounced", "complained", "manual"];
|
|
4250
|
-
var SuppressionReason =
|
|
4251
|
-
var Suppression =
|
|
4473
|
+
var SuppressionReason = import_zod14.z.enum(SUPPRESSION_REASONS);
|
|
4474
|
+
var Suppression = import_zod14.z.object({
|
|
4252
4475
|
id: Id,
|
|
4253
4476
|
email: Email,
|
|
4254
4477
|
reason: SuppressionReason,
|
|
4255
4478
|
topic: Slug.nullable(),
|
|
4256
4479
|
source_message_id: Id.nullable(),
|
|
4257
|
-
note:
|
|
4480
|
+
note: import_zod14.z.string().max(1e3).nullable(),
|
|
4258
4481
|
created_at: Timestamp
|
|
4259
4482
|
});
|
|
4260
|
-
var SuppressionCreate =
|
|
4483
|
+
var SuppressionCreate = import_zod14.z.object({
|
|
4261
4484
|
email: Email,
|
|
4262
|
-
reason:
|
|
4485
|
+
reason: import_zod14.z.enum(["manual", "unsubscribed"]),
|
|
4263
4486
|
topic: Slug.nullable().optional(),
|
|
4264
|
-
note:
|
|
4487
|
+
note: import_zod14.z.string().max(1e3).optional()
|
|
4265
4488
|
});
|
|
4266
4489
|
var SuppressionListQuery = PageQuery.extend({
|
|
4267
|
-
email:
|
|
4490
|
+
email: import_zod14.z.string().min(1).max(254).optional(),
|
|
4268
4491
|
reason: SuppressionReason.optional(),
|
|
4269
4492
|
topic: Slug.optional()
|
|
4270
4493
|
});
|
|
4271
4494
|
|
|
4272
4495
|
// src/webhooks.ts
|
|
4273
|
-
var
|
|
4496
|
+
var import_zod15 = require("zod");
|
|
4274
4497
|
var WEBHOOK_EVENT_TYPES = [
|
|
4275
4498
|
"message.sent",
|
|
4276
4499
|
"message.failed",
|
|
@@ -4314,23 +4537,23 @@ var WEBHOOK_EVENT_TYPES = [
|
|
|
4314
4537
|
"template.updated",
|
|
4315
4538
|
"template.deleted"
|
|
4316
4539
|
];
|
|
4317
|
-
var WebhookEventType =
|
|
4318
|
-
var MessageEventBase =
|
|
4540
|
+
var WebhookEventType = import_zod15.z.enum(WEBHOOK_EVENT_TYPES);
|
|
4541
|
+
var MessageEventBase = import_zod15.z.object({
|
|
4319
4542
|
message_id: Id,
|
|
4320
4543
|
mailing_id: Id.nullable(),
|
|
4321
4544
|
mailing_metadata: MailingMetadata.nullable(),
|
|
4322
4545
|
recipient_id: Id.nullable(),
|
|
4323
4546
|
contact_id: Id.nullable(),
|
|
4324
|
-
external_id:
|
|
4547
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4325
4548
|
email: Email,
|
|
4326
|
-
subject:
|
|
4549
|
+
subject: import_zod15.z.string(),
|
|
4327
4550
|
topic: Slug.nullable(),
|
|
4328
|
-
provider_message_id:
|
|
4329
|
-
is_test:
|
|
4551
|
+
provider_message_id: import_zod15.z.string().nullable(),
|
|
4552
|
+
is_test: import_zod15.z.boolean()
|
|
4330
4553
|
});
|
|
4331
4554
|
var MessageSentData = MessageEventBase.extend({
|
|
4332
4555
|
/** The final HTML as sent, so the client can archive it beside its own records. */
|
|
4333
|
-
html:
|
|
4556
|
+
html: import_zod15.z.string(),
|
|
4334
4557
|
sent_at: Timestamp,
|
|
4335
4558
|
/**
|
|
4336
4559
|
* The choice each insertion made (see `Message.insertions`); absent or null
|
|
@@ -4341,20 +4564,20 @@ var MessageSentData = MessageEventBase.extend({
|
|
|
4341
4564
|
insertions: InsertionChoices.nullish()
|
|
4342
4565
|
});
|
|
4343
4566
|
var MessageFailedData = MessageEventBase.extend({
|
|
4344
|
-
error:
|
|
4567
|
+
error: import_zod15.z.string(),
|
|
4345
4568
|
/** False when the provider rejected permanently; the recipient will not be retried. */
|
|
4346
|
-
retryable:
|
|
4569
|
+
retryable: import_zod15.z.boolean(),
|
|
4347
4570
|
failed_at: Timestamp
|
|
4348
4571
|
});
|
|
4349
4572
|
var UNSUBSCRIBE_SOURCES = ["hosted_page", "one_click", "api", "dashboard", "signup_form"];
|
|
4350
|
-
var ContactUnsubscribedData =
|
|
4573
|
+
var ContactUnsubscribedData = import_zod15.z.object({
|
|
4351
4574
|
contact_id: Id.nullable(),
|
|
4352
|
-
external_id:
|
|
4575
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4353
4576
|
email: Email,
|
|
4354
4577
|
/** The topic unsubscribed from; null means every topic. */
|
|
4355
4578
|
topic: Slug.nullable(),
|
|
4356
4579
|
mailing_id: Id.nullable(),
|
|
4357
|
-
source:
|
|
4580
|
+
source: import_zod15.z.enum(UNSUBSCRIBE_SOURCES),
|
|
4358
4581
|
unsubscribed_at: Timestamp
|
|
4359
4582
|
});
|
|
4360
4583
|
var ContactResubscribedData = ContactUnsubscribedData.omit({ unsubscribed_at: true }).extend({
|
|
@@ -4363,142 +4586,142 @@ var ContactResubscribedData = ContactUnsubscribedData.omit({ unsubscribed_at: tr
|
|
|
4363
4586
|
* breaker undid a `bounced` block it judged false (a `contact.bounced` for the
|
|
4364
4587
|
* same address and mailing went out before); `topic` is null.
|
|
4365
4588
|
*/
|
|
4366
|
-
source:
|
|
4589
|
+
source: import_zod15.z.enum([...UNSUBSCRIBE_SOURCES, "bounce_reverted"]),
|
|
4367
4590
|
resubscribed_at: Timestamp
|
|
4368
4591
|
});
|
|
4369
|
-
var ContactBouncedData =
|
|
4592
|
+
var ContactBouncedData = import_zod15.z.object({
|
|
4370
4593
|
contact_id: Id.nullable(),
|
|
4371
|
-
external_id:
|
|
4594
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4372
4595
|
email: Email,
|
|
4373
4596
|
/** `bounced` for a hard bounce, `complained` for a spam complaint. */
|
|
4374
|
-
reason:
|
|
4597
|
+
reason: import_zod15.z.enum(["bounced", "complained"]),
|
|
4375
4598
|
message_id: Id.nullable(),
|
|
4376
|
-
diagnostic:
|
|
4599
|
+
diagnostic: import_zod15.z.string().nullable(),
|
|
4377
4600
|
bounced_at: Timestamp
|
|
4378
4601
|
});
|
|
4379
|
-
var MailingFinishedData =
|
|
4602
|
+
var MailingFinishedData = import_zod15.z.object({
|
|
4380
4603
|
mailing_id: Id,
|
|
4381
4604
|
mailing_metadata: MailingMetadata,
|
|
4382
|
-
status:
|
|
4605
|
+
status: import_zod15.z.enum(["sent", "partially_failed", "cancelled"]),
|
|
4383
4606
|
counts: MailingCounts,
|
|
4384
4607
|
finished_at: Timestamp
|
|
4385
4608
|
});
|
|
4386
|
-
var ContactSubscribedData =
|
|
4609
|
+
var ContactSubscribedData = import_zod15.z.object({
|
|
4387
4610
|
contact_id: Id,
|
|
4388
|
-
external_id:
|
|
4611
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4389
4612
|
email: Email,
|
|
4390
|
-
topics:
|
|
4391
|
-
source:
|
|
4613
|
+
topics: import_zod15.z.array(Slug),
|
|
4614
|
+
source: import_zod15.z.enum(["signup_form", "api", "dashboard", "automation"]),
|
|
4392
4615
|
signup_form_id: Id.nullable(),
|
|
4393
|
-
signup_form_version:
|
|
4616
|
+
signup_form_version: import_zod15.z.number().int().min(1).nullable(),
|
|
4394
4617
|
subscribed_at: Timestamp
|
|
4395
4618
|
});
|
|
4396
|
-
var ImportFinishedData =
|
|
4619
|
+
var ImportFinishedData = import_zod15.z.object({
|
|
4397
4620
|
import_id: Id,
|
|
4398
|
-
status:
|
|
4621
|
+
status: import_zod15.z.enum(["completed", "cancelled", "failed"]),
|
|
4399
4622
|
result: ImportReport.nullable(),
|
|
4400
|
-
error:
|
|
4623
|
+
error: import_zod15.z.string().nullable(),
|
|
4401
4624
|
finished_at: Timestamp
|
|
4402
4625
|
});
|
|
4403
|
-
var MailingScheduledData =
|
|
4626
|
+
var MailingScheduledData = import_zod15.z.object({
|
|
4404
4627
|
mailing_id: Id,
|
|
4405
4628
|
mailing_metadata: MailingMetadata,
|
|
4406
4629
|
scheduled_at: Timestamp.nullable()
|
|
4407
4630
|
});
|
|
4408
|
-
var MailingStartedData =
|
|
4631
|
+
var MailingStartedData = import_zod15.z.object({
|
|
4409
4632
|
mailing_id: Id,
|
|
4410
4633
|
mailing_metadata: MailingMetadata,
|
|
4411
|
-
trigger:
|
|
4412
|
-
recipients:
|
|
4634
|
+
trigger: import_zod15.z.enum(["send", "schedule"]),
|
|
4635
|
+
recipients: import_zod15.z.number().int().min(0),
|
|
4413
4636
|
started_at: Timestamp
|
|
4414
4637
|
});
|
|
4415
|
-
var MailingScheduleFailedData =
|
|
4638
|
+
var MailingScheduleFailedData = import_zod15.z.object({
|
|
4416
4639
|
mailing_id: Id,
|
|
4417
4640
|
mailing_metadata: MailingMetadata,
|
|
4418
|
-
code:
|
|
4419
|
-
message:
|
|
4641
|
+
code: import_zod15.z.string(),
|
|
4642
|
+
message: import_zod15.z.string(),
|
|
4420
4643
|
failed_at: Timestamp
|
|
4421
4644
|
});
|
|
4422
|
-
var MailingAbWinnerSelectedData =
|
|
4645
|
+
var MailingAbWinnerSelectedData = import_zod15.z.object({
|
|
4423
4646
|
mailing_id: Id,
|
|
4424
4647
|
mailing_metadata: MailingMetadata,
|
|
4425
|
-
winner:
|
|
4426
|
-
decided_by:
|
|
4427
|
-
variants:
|
|
4648
|
+
winner: import_zod15.z.string(),
|
|
4649
|
+
decided_by: import_zod15.z.enum(["metric", "manual"]),
|
|
4650
|
+
variants: import_zod15.z.array(VariantAnalytics),
|
|
4428
4651
|
decided_at: Timestamp
|
|
4429
4652
|
});
|
|
4430
|
-
var ContactTaggedData =
|
|
4653
|
+
var ContactTaggedData = import_zod15.z.object({
|
|
4431
4654
|
contact_id: Id,
|
|
4432
|
-
external_id:
|
|
4655
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4433
4656
|
email: Email,
|
|
4434
4657
|
/** Only the tags the contact did not already have. */
|
|
4435
|
-
tags:
|
|
4436
|
-
source:
|
|
4658
|
+
tags: import_zod15.z.array(Slug).min(1),
|
|
4659
|
+
source: import_zod15.z.enum(["api", "dashboard", "signup_form", "import", "automation"]),
|
|
4437
4660
|
tagged_at: Timestamp
|
|
4438
4661
|
});
|
|
4439
|
-
var ContactUpdatedData =
|
|
4662
|
+
var ContactUpdatedData = import_zod15.z.object({
|
|
4440
4663
|
contact_id: Id,
|
|
4441
|
-
external_id:
|
|
4664
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4442
4665
|
email: Email,
|
|
4443
|
-
changed:
|
|
4666
|
+
changed: import_zod15.z.array(import_zod15.z.string()).min(1),
|
|
4444
4667
|
properties: Properties,
|
|
4445
|
-
source:
|
|
4668
|
+
source: import_zod15.z.enum(["api", "dashboard", "signup_form", "import", "automation"]),
|
|
4446
4669
|
updated_at: Timestamp
|
|
4447
4670
|
});
|
|
4448
|
-
var AutomationRunEventBase =
|
|
4671
|
+
var AutomationRunEventBase = import_zod15.z.object({
|
|
4449
4672
|
automation_id: Id,
|
|
4450
|
-
automation_name:
|
|
4673
|
+
automation_name: import_zod15.z.string(),
|
|
4451
4674
|
run_id: Id,
|
|
4452
|
-
version:
|
|
4675
|
+
version: import_zod15.z.number().int().min(1),
|
|
4453
4676
|
contact_id: Id,
|
|
4454
|
-
external_id:
|
|
4677
|
+
external_id: import_zod15.z.string().nullable(),
|
|
4455
4678
|
email: Email
|
|
4456
4679
|
});
|
|
4457
4680
|
var AutomationRunStartedData = AutomationRunEventBase.extend({
|
|
4458
4681
|
/** What let them in: a trigger kind, or `manual` for an explicit enrolment. */
|
|
4459
|
-
trigger_kind:
|
|
4682
|
+
trigger_kind: import_zod15.z.string(),
|
|
4460
4683
|
entered_at: Timestamp
|
|
4461
4684
|
});
|
|
4462
4685
|
var AutomationRunCompletedData = AutomationRunEventBase.extend({
|
|
4463
|
-
last_step_id:
|
|
4686
|
+
last_step_id: import_zod15.z.string().nullable(),
|
|
4464
4687
|
completed_at: Timestamp
|
|
4465
4688
|
});
|
|
4466
4689
|
var AutomationRunExitedData = AutomationRunEventBase.extend({
|
|
4467
4690
|
reason: AutomationEndReason,
|
|
4468
|
-
step_id:
|
|
4691
|
+
step_id: import_zod15.z.string().nullable(),
|
|
4469
4692
|
exited_at: Timestamp
|
|
4470
4693
|
});
|
|
4471
4694
|
var AutomationRunFailedData = AutomationRunEventBase.extend({
|
|
4472
|
-
reason:
|
|
4473
|
-
step_id:
|
|
4695
|
+
reason: import_zod15.z.string(),
|
|
4696
|
+
step_id: import_zod15.z.string().nullable(),
|
|
4474
4697
|
failed_at: Timestamp
|
|
4475
4698
|
});
|
|
4476
4699
|
var AutomationWebhookData = AutomationRunEventBase.extend({
|
|
4477
|
-
step_id:
|
|
4700
|
+
step_id: import_zod15.z.string(),
|
|
4478
4701
|
/** The step's own label, when it was given one, so a receiver can branch on a name. */
|
|
4479
|
-
step_label:
|
|
4702
|
+
step_label: import_zod15.z.string().nullable(),
|
|
4480
4703
|
/** Whatever the step carries, verbatim. Null when it carries nothing. */
|
|
4481
4704
|
payload: JsonValue.nullable(),
|
|
4482
4705
|
fired_at: Timestamp
|
|
4483
4706
|
});
|
|
4484
|
-
var TemplateEventBase =
|
|
4707
|
+
var TemplateEventBase = import_zod15.z.object({
|
|
4485
4708
|
template_id: Id,
|
|
4486
|
-
name:
|
|
4487
|
-
version:
|
|
4488
|
-
source:
|
|
4709
|
+
name: import_zod15.z.string().min(1).max(200),
|
|
4710
|
+
version: import_zod15.z.number().int().min(1),
|
|
4711
|
+
source: import_zod15.z.enum(["api", "dashboard", "mjml_import"])
|
|
4489
4712
|
});
|
|
4490
4713
|
var TemplateCreatedData = TemplateEventBase.extend({ created_at: Timestamp });
|
|
4491
|
-
var TemplateUpdatedData = TemplateEventBase.extend({ archived:
|
|
4714
|
+
var TemplateUpdatedData = TemplateEventBase.extend({ archived: import_zod15.z.boolean(), updated_at: Timestamp });
|
|
4492
4715
|
var TemplateDeletedData = TemplateEventBase.extend({ deleted_at: Timestamp });
|
|
4493
|
-
var envelope = (type, data) =>
|
|
4716
|
+
var envelope = (type, data) => import_zod15.z.object({
|
|
4494
4717
|
/** Unique per event: a receiver deduplicates on it (deliveries may repeat). */
|
|
4495
4718
|
id: Id,
|
|
4496
|
-
type:
|
|
4719
|
+
type: import_zod15.z.literal(type),
|
|
4497
4720
|
created_at: Timestamp,
|
|
4498
4721
|
workspace_id: Id,
|
|
4499
4722
|
data
|
|
4500
4723
|
});
|
|
4501
|
-
var WebhookEvent =
|
|
4724
|
+
var WebhookEvent = import_zod15.z.discriminatedUnion("type", [
|
|
4502
4725
|
envelope("message.sent", MessageSentData),
|
|
4503
4726
|
envelope("message.failed", MessageFailedData),
|
|
4504
4727
|
envelope("contact.unsubscribed", ContactUnsubscribedData),
|
|
@@ -4522,16 +4745,16 @@ var WebhookEvent = import_zod14.z.discriminatedUnion("type", [
|
|
|
4522
4745
|
envelope("template.updated", TemplateUpdatedData),
|
|
4523
4746
|
envelope("template.deleted", TemplateDeletedData)
|
|
4524
4747
|
]);
|
|
4525
|
-
var WebhookEndpoint =
|
|
4748
|
+
var WebhookEndpoint = import_zod15.z.object({
|
|
4526
4749
|
id: Id,
|
|
4527
|
-
url:
|
|
4528
|
-
description:
|
|
4529
|
-
events:
|
|
4530
|
-
enabled:
|
|
4750
|
+
url: import_zod15.z.string().url(),
|
|
4751
|
+
description: import_zod15.z.string().max(500).nullable(),
|
|
4752
|
+
events: import_zod15.z.array(WebhookEventType).min(1),
|
|
4753
|
+
enabled: import_zod15.z.boolean(),
|
|
4531
4754
|
created_at: Timestamp,
|
|
4532
4755
|
updated_at: Timestamp
|
|
4533
4756
|
});
|
|
4534
|
-
var WebhookUrl =
|
|
4757
|
+
var WebhookUrl = import_zod15.z.string().url().refine((u) => {
|
|
4535
4758
|
try {
|
|
4536
4759
|
const url = new URL(u);
|
|
4537
4760
|
if (url.protocol === "https:") return true;
|
|
@@ -4540,35 +4763,35 @@ var WebhookUrl = import_zod14.z.string().url().refine((u) => {
|
|
|
4540
4763
|
return false;
|
|
4541
4764
|
}
|
|
4542
4765
|
}, "must be https (http only for localhost)");
|
|
4543
|
-
var WebhookEndpointCreate =
|
|
4766
|
+
var WebhookEndpointCreate = import_zod15.z.object({
|
|
4544
4767
|
url: WebhookUrl,
|
|
4545
|
-
description:
|
|
4546
|
-
events:
|
|
4547
|
-
enabled:
|
|
4768
|
+
description: import_zod15.z.string().max(500).optional(),
|
|
4769
|
+
events: import_zod15.z.array(WebhookEventType).min(1),
|
|
4770
|
+
enabled: import_zod15.z.boolean().optional()
|
|
4548
4771
|
});
|
|
4549
|
-
var WebhookEndpointUpdate =
|
|
4772
|
+
var WebhookEndpointUpdate = import_zod15.z.object({
|
|
4550
4773
|
url: WebhookUrl,
|
|
4551
|
-
description:
|
|
4552
|
-
events:
|
|
4553
|
-
enabled:
|
|
4774
|
+
description: import_zod15.z.string().max(500).nullable(),
|
|
4775
|
+
events: import_zod15.z.array(WebhookEventType).min(1),
|
|
4776
|
+
enabled: import_zod15.z.boolean()
|
|
4554
4777
|
}).partial().refine((v) => Object.keys(v).length > 0, "at least one field");
|
|
4555
|
-
var WebhookEndpointWithSecret =
|
|
4778
|
+
var WebhookEndpointWithSecret = import_zod15.z.object({
|
|
4556
4779
|
endpoint: WebhookEndpoint,
|
|
4557
|
-
secret:
|
|
4780
|
+
secret: import_zod15.z.string().min(32)
|
|
4558
4781
|
});
|
|
4559
4782
|
var WEBHOOK_DELIVERY_STATUSES = ["pending", "succeeded", "failed"];
|
|
4560
|
-
var WebhookDeliveryStatus =
|
|
4783
|
+
var WebhookDeliveryStatus = import_zod15.z.enum(WEBHOOK_DELIVERY_STATUSES);
|
|
4561
4784
|
var WEBHOOK_MAX_ATTEMPTS = 8;
|
|
4562
4785
|
var WEBHOOK_RETRY_DELAYS_SECONDS = [30, 120, 600, 1800, 3600, 7200, 21600];
|
|
4563
|
-
var WebhookDelivery =
|
|
4786
|
+
var WebhookDelivery = import_zod15.z.object({
|
|
4564
4787
|
id: Id,
|
|
4565
4788
|
endpoint_id: Id,
|
|
4566
4789
|
event_id: Id,
|
|
4567
4790
|
event_type: WebhookEventType,
|
|
4568
4791
|
status: WebhookDeliveryStatus,
|
|
4569
|
-
attempts:
|
|
4570
|
-
last_status_code:
|
|
4571
|
-
last_error:
|
|
4792
|
+
attempts: import_zod15.z.number().int().min(0),
|
|
4793
|
+
last_status_code: import_zod15.z.number().int().min(100).max(599).nullable(),
|
|
4794
|
+
last_error: import_zod15.z.string().nullable(),
|
|
4572
4795
|
next_attempt_at: Timestamp.nullable(),
|
|
4573
4796
|
delivered_at: Timestamp.nullable(),
|
|
4574
4797
|
created_at: Timestamp
|
|
@@ -4577,7 +4800,7 @@ var WebhookDeliveryListQuery = PageQuery.extend({
|
|
|
4577
4800
|
status: WebhookDeliveryStatus.optional(),
|
|
4578
4801
|
event_type: WebhookEventType.optional()
|
|
4579
4802
|
});
|
|
4580
|
-
var WebhookDeliveryParams =
|
|
4803
|
+
var WebhookDeliveryParams = import_zod15.z.object({ id: Id, delivery_id: Id });
|
|
4581
4804
|
|
|
4582
4805
|
// src/webhook-signing.ts
|
|
4583
4806
|
var WEBHOOK_SIGNATURE_HEADER = "x-mail-signature";
|
|
@@ -4644,79 +4867,79 @@ async function verifyWebhook(input) {
|
|
|
4644
4867
|
}
|
|
4645
4868
|
|
|
4646
4869
|
// src/billing.ts
|
|
4647
|
-
var
|
|
4870
|
+
var import_zod16 = require("zod");
|
|
4648
4871
|
var PLAN_IDS = ["free", "starter", "growth", "design_partner"];
|
|
4649
|
-
var PlanId =
|
|
4650
|
-
var PlanLimits =
|
|
4651
|
-
monthly_messages:
|
|
4652
|
-
contacts:
|
|
4653
|
-
members:
|
|
4654
|
-
providers:
|
|
4655
|
-
webhook_endpoints:
|
|
4872
|
+
var PlanId = import_zod16.z.enum(PLAN_IDS);
|
|
4873
|
+
var PlanLimits = import_zod16.z.object({
|
|
4874
|
+
monthly_messages: import_zod16.z.number().int().min(0).nullable(),
|
|
4875
|
+
contacts: import_zod16.z.number().int().min(0).nullable(),
|
|
4876
|
+
members: import_zod16.z.number().int().min(1).nullable(),
|
|
4877
|
+
providers: import_zod16.z.number().int().min(1).nullable(),
|
|
4878
|
+
webhook_endpoints: import_zod16.z.number().int().min(0).nullable(),
|
|
4656
4879
|
/** Automations that may be live (active or paused) at once (A1). */
|
|
4657
|
-
active_automations:
|
|
4880
|
+
active_automations: import_zod16.z.number().int().min(0).nullable(),
|
|
4658
4881
|
/** Steps one automation may hold. Null is the flow's own cap, not unlimited. */
|
|
4659
|
-
automation_steps:
|
|
4882
|
+
automation_steps: import_zod16.z.number().int().min(1).nullable()
|
|
4660
4883
|
});
|
|
4661
|
-
var PlanFeatures =
|
|
4884
|
+
var PlanFeatures = import_zod16.z.object({
|
|
4662
4885
|
/** A/B tests of subject and content on a mailing (S4). */
|
|
4663
|
-
ab_testing:
|
|
4886
|
+
ab_testing: import_zod16.z.boolean(),
|
|
4664
4887
|
/** Open and click tracking, still off until a workspace turns it on (`settings.tracking_enabled`). */
|
|
4665
|
-
tracking:
|
|
4888
|
+
tracking: import_zod16.z.boolean(),
|
|
4666
4889
|
/** Sending and hosting pages on the workspace's own domain (a later phase). */
|
|
4667
|
-
custom_domains:
|
|
4890
|
+
custom_domains: import_zod16.z.boolean(),
|
|
4668
4891
|
/** Automations: flows a person walks through step by step (A1). */
|
|
4669
|
-
automations:
|
|
4892
|
+
automations: import_zod16.z.boolean()
|
|
4670
4893
|
});
|
|
4671
4894
|
var PLAN_FEATURES = ["ab_testing", "tracking", "custom_domains", "automations"];
|
|
4672
|
-
var Plan =
|
|
4895
|
+
var Plan = import_zod16.z.object({
|
|
4673
4896
|
id: PlanId,
|
|
4674
|
-
name:
|
|
4897
|
+
name: import_zod16.z.string().min(1),
|
|
4675
4898
|
/** Price in the smallest currency unit per month; null for plans not sold. */
|
|
4676
|
-
monthly_price_cents:
|
|
4677
|
-
currency:
|
|
4899
|
+
monthly_price_cents: import_zod16.z.number().int().min(0).nullable(),
|
|
4900
|
+
currency: import_zod16.z.string().length(3),
|
|
4678
4901
|
limits: PlanLimits,
|
|
4679
4902
|
features: PlanFeatures
|
|
4680
4903
|
});
|
|
4681
|
-
var CatalogPlan = Plan.extend({ sellable:
|
|
4682
|
-
var Subscription =
|
|
4904
|
+
var CatalogPlan = Plan.extend({ sellable: import_zod16.z.boolean() });
|
|
4905
|
+
var Subscription = import_zod16.z.object({
|
|
4683
4906
|
workspace_id: Id,
|
|
4684
4907
|
plan: PlanId,
|
|
4685
|
-
status:
|
|
4908
|
+
status: import_zod16.z.enum(["active", "trialing", "past_due", "cancelled"]),
|
|
4686
4909
|
current_period_start: Timestamp,
|
|
4687
4910
|
current_period_end: Timestamp,
|
|
4688
|
-
cancel_at_period_end:
|
|
4911
|
+
cancel_at_period_end: import_zod16.z.boolean(),
|
|
4689
4912
|
/**
|
|
4690
4913
|
* A design partner outside billing (plan `design_partner`, no limits, no
|
|
4691
4914
|
* checkout). Set only by an operator, never through the API.
|
|
4692
4915
|
*/
|
|
4693
|
-
billing_exempt:
|
|
4916
|
+
billing_exempt: import_zod16.z.boolean()
|
|
4694
4917
|
});
|
|
4695
4918
|
var USAGE_METRICS = ["messages", "contacts", "members", "providers", "webhook_endpoints", "active_automations"];
|
|
4696
|
-
var UsageMetric =
|
|
4919
|
+
var UsageMetric = import_zod16.z.enum(USAGE_METRICS);
|
|
4697
4920
|
var USAGE_WARNING_RATIO = 0.8;
|
|
4698
|
-
var UsageWarning =
|
|
4921
|
+
var UsageWarning = import_zod16.z.object({
|
|
4699
4922
|
metric: UsageMetric,
|
|
4700
|
-
used:
|
|
4701
|
-
limit:
|
|
4923
|
+
used: import_zod16.z.number().int().min(0),
|
|
4924
|
+
limit: import_zod16.z.number().int().min(0),
|
|
4702
4925
|
/** `approaching`: at or above USAGE_WARNING_RATIO of the limit; `reached`: at or above the limit. */
|
|
4703
|
-
level:
|
|
4926
|
+
level: import_zod16.z.enum(["approaching", "reached"])
|
|
4704
4927
|
});
|
|
4705
|
-
var Usage =
|
|
4928
|
+
var Usage = import_zod16.z.object({
|
|
4706
4929
|
plan: PlanId,
|
|
4707
4930
|
period_start: Timestamp,
|
|
4708
4931
|
period_end: Timestamp,
|
|
4709
|
-
metrics:
|
|
4710
|
-
warnings:
|
|
4932
|
+
metrics: import_zod16.z.record(UsageMetric, import_zod16.z.object({ used: import_zod16.z.number().int().min(0), limit: import_zod16.z.number().int().min(0).nullable() })),
|
|
4933
|
+
warnings: import_zod16.z.array(UsageWarning)
|
|
4711
4934
|
});
|
|
4712
|
-
var CheckoutRequest =
|
|
4713
|
-
plan:
|
|
4714
|
-
success_url:
|
|
4715
|
-
cancel_url:
|
|
4935
|
+
var CheckoutRequest = import_zod16.z.object({
|
|
4936
|
+
plan: import_zod16.z.enum(["starter", "growth"]),
|
|
4937
|
+
success_url: import_zod16.z.string().url(),
|
|
4938
|
+
cancel_url: import_zod16.z.string().url()
|
|
4716
4939
|
});
|
|
4717
|
-
var CheckoutSession =
|
|
4718
|
-
var PortalRequest =
|
|
4719
|
-
var PortalSession =
|
|
4940
|
+
var CheckoutSession = import_zod16.z.object({ url: import_zod16.z.string().url() });
|
|
4941
|
+
var PortalRequest = import_zod16.z.object({ return_url: import_zod16.z.string().url() });
|
|
4942
|
+
var PortalSession = import_zod16.z.object({ url: import_zod16.z.string().url() });
|
|
4720
4943
|
var USAGE_WARNING_HEADER = "x-mail-usage-warning";
|
|
4721
4944
|
function formatUsageWarningHeader(warnings) {
|
|
4722
4945
|
if (warnings.length === 0) return null;
|
|
@@ -4736,7 +4959,7 @@ function parseUsageWarningHeader(value) {
|
|
|
4736
4959
|
}
|
|
4737
4960
|
|
|
4738
4961
|
// src/routes.ts
|
|
4739
|
-
var
|
|
4962
|
+
var import_zod17 = require("zod");
|
|
4740
4963
|
var list = (item) => page(item);
|
|
4741
4964
|
var foundationRoutes = {
|
|
4742
4965
|
"workspaces.create": {
|
|
@@ -4964,7 +5187,7 @@ var templateRoutes = {
|
|
|
4964
5187
|
path: "/v1/templates/:id/export",
|
|
4965
5188
|
params: IdParams,
|
|
4966
5189
|
query: TemplateExportQuery,
|
|
4967
|
-
response:
|
|
5190
|
+
response: import_zod17.z.string(),
|
|
4968
5191
|
responseType: "text",
|
|
4969
5192
|
status: 200,
|
|
4970
5193
|
access: "read",
|
|
@@ -5288,7 +5511,7 @@ var sendingRoutes = {
|
|
|
5288
5511
|
path: "/v1/mailings/:id/export",
|
|
5289
5512
|
params: IdParams,
|
|
5290
5513
|
query: MailingExportQuery,
|
|
5291
|
-
response:
|
|
5514
|
+
response: import_zod17.z.string(),
|
|
5292
5515
|
responseType: "text",
|
|
5293
5516
|
status: 200,
|
|
5294
5517
|
access: "read",
|
|
@@ -5334,6 +5557,21 @@ var sendingRoutes = {
|
|
|
5334
5557
|
access: "write",
|
|
5335
5558
|
phase: "S2"
|
|
5336
5559
|
},
|
|
5560
|
+
/**
|
|
5561
|
+
* A dry run: what each given recipient would be sent (every value's text and
|
|
5562
|
+
* the layer it comes from, each insertion's choice, the problems found),
|
|
5563
|
+
* without adding anybody. Reads only, in any state of the mailing.
|
|
5564
|
+
*/
|
|
5565
|
+
"mailings.resolve": {
|
|
5566
|
+
method: "POST",
|
|
5567
|
+
path: "/v1/mailings/:id/resolve",
|
|
5568
|
+
params: IdParams,
|
|
5569
|
+
body: MailingResolveRequest,
|
|
5570
|
+
response: MailingResolveResult,
|
|
5571
|
+
status: 200,
|
|
5572
|
+
access: "read",
|
|
5573
|
+
phase: "S2"
|
|
5574
|
+
},
|
|
5337
5575
|
"mailings.send": {
|
|
5338
5576
|
method: "POST",
|
|
5339
5577
|
path: "/v1/mailings/:id/send",
|
|
@@ -5521,7 +5759,7 @@ var platformRoutes = {
|
|
|
5521
5759
|
"contactProperties.list": {
|
|
5522
5760
|
method: "GET",
|
|
5523
5761
|
path: "/v1/contact-properties",
|
|
5524
|
-
response:
|
|
5762
|
+
response: import_zod17.z.object({ data: import_zod17.z.array(ContactPropertyDefinition) }),
|
|
5525
5763
|
status: 200,
|
|
5526
5764
|
access: "read",
|
|
5527
5765
|
phase: "S4"
|
|
@@ -5820,7 +6058,7 @@ var billingRoutes = {
|
|
|
5820
6058
|
"billing.plans": {
|
|
5821
6059
|
method: "GET",
|
|
5822
6060
|
path: "/v1/billing/plans",
|
|
5823
|
-
response:
|
|
6061
|
+
response: import_zod17.z.object({ data: import_zod17.z.array(CatalogPlan) }),
|
|
5824
6062
|
status: 200,
|
|
5825
6063
|
access: "read",
|
|
5826
6064
|
phase: "S5"
|
|
@@ -5962,7 +6200,7 @@ var automationRoutes = {
|
|
|
5962
6200
|
method: "POST",
|
|
5963
6201
|
path: "/v1/automations/:id/pause",
|
|
5964
6202
|
params: IdParams,
|
|
5965
|
-
body:
|
|
6203
|
+
body: import_zod17.z.object({}).strict(),
|
|
5966
6204
|
response: Automation,
|
|
5967
6205
|
status: 200,
|
|
5968
6206
|
access: "write",
|
|
@@ -5972,7 +6210,7 @@ var automationRoutes = {
|
|
|
5972
6210
|
method: "POST",
|
|
5973
6211
|
path: "/v1/automations/:id/resume",
|
|
5974
6212
|
params: IdParams,
|
|
5975
|
-
body:
|
|
6213
|
+
body: import_zod17.z.object({}).strict(),
|
|
5976
6214
|
response: Automation,
|
|
5977
6215
|
status: 200,
|
|
5978
6216
|
access: "write",
|
|
@@ -5982,7 +6220,7 @@ var automationRoutes = {
|
|
|
5982
6220
|
method: "POST",
|
|
5983
6221
|
path: "/v1/automations/:id/archive",
|
|
5984
6222
|
params: IdParams,
|
|
5985
|
-
body:
|
|
6223
|
+
body: import_zod17.z.object({}).strict(),
|
|
5986
6224
|
response: Automation,
|
|
5987
6225
|
status: 200,
|
|
5988
6226
|
access: "write",
|
|
@@ -6116,13 +6354,13 @@ function matchRoute(method, pathname) {
|
|
|
6116
6354
|
for (const [id, route] of Object.entries(routes)) {
|
|
6117
6355
|
if (route.method !== method) continue;
|
|
6118
6356
|
const names = [];
|
|
6119
|
-
const
|
|
6357
|
+
const pattern3 = new RegExp(
|
|
6120
6358
|
"^" + route.path.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/:([a-z_]+)/g, (_, name) => {
|
|
6121
6359
|
names.push(name);
|
|
6122
6360
|
return "([^/]+)";
|
|
6123
6361
|
}) + "$"
|
|
6124
6362
|
);
|
|
6125
|
-
const match =
|
|
6363
|
+
const match = pattern3.exec(pathname);
|
|
6126
6364
|
if (!match) continue;
|
|
6127
6365
|
const params = {};
|
|
6128
6366
|
names.forEach((name, i) => {
|
|
@@ -6323,6 +6561,7 @@ function matchRoute(method, pathname) {
|
|
|
6323
6561
|
InviteListQuery,
|
|
6324
6562
|
InviteStatus,
|
|
6325
6563
|
JsonValue,
|
|
6564
|
+
LETTER_ONLY_MERGE_FIELDS,
|
|
6326
6565
|
LETTER_RECIPIENT_REFUSAL,
|
|
6327
6566
|
LIST_UNSUBSCRIBE_POST_VALUE,
|
|
6328
6567
|
LOCALE_TAG_PATTERN,
|
|
@@ -6391,7 +6630,10 @@ function matchRoute(method, pathname) {
|
|
|
6391
6630
|
MailingLanguageReport,
|
|
6392
6631
|
MailingLanguageStatus,
|
|
6393
6632
|
MailingListQuery,
|
|
6633
|
+
MailingMerge,
|
|
6394
6634
|
MailingMetadata,
|
|
6635
|
+
MailingResolveRequest,
|
|
6636
|
+
MailingResolveResult,
|
|
6395
6637
|
MailingRetryFailedRequest,
|
|
6396
6638
|
MailingScheduleFailedData,
|
|
6397
6639
|
MailingScheduleRequest,
|
|
@@ -6416,6 +6658,8 @@ function matchRoute(method, pathname) {
|
|
|
6416
6658
|
MessageOutcome,
|
|
6417
6659
|
MessageSentData,
|
|
6418
6660
|
MessageSummary,
|
|
6661
|
+
MessageValues,
|
|
6662
|
+
NAME_ON_BROADCAST_REFUSAL,
|
|
6419
6663
|
NotifyRecipients,
|
|
6420
6664
|
NotifyStep,
|
|
6421
6665
|
ON_BEHALF_OF_HEADER,
|
|
@@ -6451,6 +6695,8 @@ function matchRoute(method, pathname) {
|
|
|
6451
6695
|
REQUEST_ID_HEADER,
|
|
6452
6696
|
RESEND_EVENT_TYPES,
|
|
6453
6697
|
RESERVED_MERGE_FIELDS,
|
|
6698
|
+
RESOLVE_PROBLEMS,
|
|
6699
|
+
RESOLVE_REJECTIONS,
|
|
6454
6700
|
RETRYABLE_ERRORS,
|
|
6455
6701
|
RETRY_AFTER_HEADER,
|
|
6456
6702
|
RE_ENTRY_MODES,
|
|
@@ -6463,6 +6709,9 @@ function matchRoute(method, pathname) {
|
|
|
6463
6709
|
RecipientStatus,
|
|
6464
6710
|
RemoteImage,
|
|
6465
6711
|
ResendSigningSecret,
|
|
6712
|
+
ResolveProblem,
|
|
6713
|
+
ResolvedRecipient,
|
|
6714
|
+
ResolvedValue,
|
|
6466
6715
|
SERVICE_FILLED_MERGE_FIELDS,
|
|
6467
6716
|
SIGNUP_FORM_FIELDS,
|
|
6468
6717
|
SKIP_REASONS,
|
|
@@ -6549,10 +6798,13 @@ function matchRoute(method, pathname) {
|
|
|
6549
6798
|
USAGE_METRICS,
|
|
6550
6799
|
USAGE_WARNING_HEADER,
|
|
6551
6800
|
USAGE_WARNING_RATIO,
|
|
6801
|
+
UnfilledLink,
|
|
6552
6802
|
Usage,
|
|
6553
6803
|
UsageMetric,
|
|
6554
6804
|
UsageWarning,
|
|
6805
|
+
VALUE_LAYERS,
|
|
6555
6806
|
ValidationIssue,
|
|
6807
|
+
ValueLayer,
|
|
6556
6808
|
VariantAnalytics,
|
|
6557
6809
|
WEBHOOK_DELIVERY_STATUSES,
|
|
6558
6810
|
WEBHOOK_EVENT_ID_HEADER,
|
|
@@ -6616,6 +6868,7 @@ function matchRoute(method, pathname) {
|
|
|
6616
6868
|
editMainInsertions,
|
|
6617
6869
|
effectivePreviewPicks,
|
|
6618
6870
|
emptyFlow,
|
|
6871
|
+
emptyLinkValues,
|
|
6619
6872
|
errorBody,
|
|
6620
6873
|
escapeMergeHtml,
|
|
6621
6874
|
exportFilename,
|
|
@@ -6646,6 +6899,8 @@ function matchRoute(method, pathname) {
|
|
|
6646
6899
|
languageInsertions,
|
|
6647
6900
|
languageName,
|
|
6648
6901
|
languageTabs,
|
|
6902
|
+
letterOnlyValues,
|
|
6903
|
+
linkTokens,
|
|
6649
6904
|
mainInsertionText,
|
|
6650
6905
|
matchLocale,
|
|
6651
6906
|
matchRoute,
|
|
@@ -6666,6 +6921,8 @@ function matchRoute(method, pathname) {
|
|
|
6666
6921
|
previewInsertions,
|
|
6667
6922
|
previewPersonalization,
|
|
6668
6923
|
primaryLanguage,
|
|
6924
|
+
printedFields,
|
|
6925
|
+
rawMergeValue,
|
|
6669
6926
|
reachable,
|
|
6670
6927
|
readyWithoutInsertions,
|
|
6671
6928
|
readyWithoutSubject,
|
|
@@ -6682,6 +6939,7 @@ function matchRoute(method, pathname) {
|
|
|
6682
6939
|
renameTokenInDocument,
|
|
6683
6940
|
renameTokenInText,
|
|
6684
6941
|
resolveInsertions,
|
|
6942
|
+
resolveValue,
|
|
6685
6943
|
restorePatch,
|
|
6686
6944
|
routes,
|
|
6687
6945
|
sameJson,
|
|
@@ -6708,5 +6966,7 @@ function matchRoute(method, pathname) {
|
|
|
6708
6966
|
unknownRefusedInsertions,
|
|
6709
6967
|
unplacedInsertions,
|
|
6710
6968
|
validateAutomation,
|
|
6969
|
+
valueNames,
|
|
6970
|
+
valuesRead,
|
|
6711
6971
|
verifyWebhook
|
|
6712
6972
|
});
|