@marlinjai/mail-contract 0.12.0 → 0.14.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 +873 -153
- package/dist/index.d.ts +873 -153
- package/dist/index.js +142 -11
- package/dist/index.mjs +129 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -107,10 +107,13 @@ __export(index_exports, {
|
|
|
107
107
|
BILLING_NOT_CONFIGURED_REASON: () => BILLING_NOT_CONFIGURED_REASON,
|
|
108
108
|
BoundedAutomationFilter: () => BoundedAutomationFilter,
|
|
109
109
|
BoundedSegmentFilter: () => BoundedSegmentFilter,
|
|
110
|
+
COMPANY_GRANT_ROLES: () => COMPANY_GRANT_ROLES,
|
|
111
|
+
COMPANY_ROLE_MAX_AGE_HOURS: () => COMPANY_ROLE_MAX_AGE_HOURS,
|
|
110
112
|
CONTACT_PROPERTY_TYPES: () => CONTACT_PROPERTY_TYPES,
|
|
111
113
|
CatalogPlan: () => CatalogPlan,
|
|
112
114
|
CheckoutRequest: () => CheckoutRequest,
|
|
113
115
|
CheckoutSession: () => CheckoutSession,
|
|
116
|
+
CompanyGrantRole: () => CompanyGrantRole,
|
|
114
117
|
CompanyId: () => CompanyId,
|
|
115
118
|
CompileMessage: () => CompileMessage,
|
|
116
119
|
CompileRequest: () => CompileRequest,
|
|
@@ -249,6 +252,7 @@ __export(index_exports, {
|
|
|
249
252
|
MAX_STEPS: () => MAX_STEPS,
|
|
250
253
|
MAX_STEP_VISITS: () => MAX_STEP_VISITS,
|
|
251
254
|
MAX_SUBJECT_LENGTH: () => MAX_SUBJECT_LENGTH,
|
|
255
|
+
MAX_SYNC_COMPANIES: () => MAX_SYNC_COMPANIES,
|
|
252
256
|
MAX_TEMPLATE_INPUTS: () => MAX_TEMPLATE_INPUTS,
|
|
253
257
|
MAX_TEMPLATE_INPUTS_APP_LENGTH: () => MAX_TEMPLATE_INPUTS_APP_LENGTH,
|
|
254
258
|
MAX_TEMPLATE_INPUTS_SEEN: () => MAX_TEMPLATE_INPUTS_SEEN,
|
|
@@ -259,6 +263,7 @@ __export(index_exports, {
|
|
|
259
263
|
MAX_TEMPLATE_TRANSLATIONS: () => MAX_TEMPLATE_TRANSLATIONS,
|
|
260
264
|
MAX_TRIGGERS: () => MAX_TRIGGERS,
|
|
261
265
|
MEMBER_ROLES: () => MEMBER_ROLES,
|
|
266
|
+
MEMBER_SOURCES: () => MEMBER_SOURCES,
|
|
262
267
|
MERGE_FIELD_PATTERN: () => MERGE_FIELD_PATTERN,
|
|
263
268
|
MESSAGE_OUTCOMES: () => MESSAGE_OUTCOMES,
|
|
264
269
|
MIN_SPLIT_BRANCHES: () => MIN_SPLIT_BRANCHES,
|
|
@@ -294,8 +299,11 @@ __export(index_exports, {
|
|
|
294
299
|
MailingTestResult: () => MailingTestResult,
|
|
295
300
|
MailingUpdate: () => MailingUpdate,
|
|
296
301
|
Member: () => Member,
|
|
302
|
+
MemberCompanySync: () => MemberCompanySync,
|
|
303
|
+
MemberCompanySyncResult: () => MemberCompanySyncResult,
|
|
297
304
|
MemberCreate: () => MemberCreate,
|
|
298
305
|
MemberRole: () => MemberRole,
|
|
306
|
+
MemberSource: () => MemberSource,
|
|
299
307
|
MemberUpdate: () => MemberUpdate,
|
|
300
308
|
MergeDefaultValue: () => MergeDefaultValue,
|
|
301
309
|
MergeDefaults: () => MergeDefaults,
|
|
@@ -396,6 +404,11 @@ __export(index_exports, {
|
|
|
396
404
|
TEMPLATE_SORTS: () => TEMPLATE_SORTS,
|
|
397
405
|
TEMPLATE_SORT_DEFAULT_ORDER: () => TEMPLATE_SORT_DEFAULT_ORDER,
|
|
398
406
|
TERMINAL_MAILING_STATUSES: () => TERMINAL_MAILING_STATUSES,
|
|
407
|
+
TRANSACTIONAL_BLOCKING_REASONS: () => TRANSACTIONAL_BLOCKING_REASONS,
|
|
408
|
+
TRANSACTIONAL_NEEDS_LETTER_REFUSAL: () => TRANSACTIONAL_NEEDS_LETTER_REFUSAL,
|
|
409
|
+
TRANSACTIONAL_NEEDS_TEMPLATE_LOCALE_REFUSAL: () => TRANSACTIONAL_NEEDS_TEMPLATE_LOCALE_REFUSAL,
|
|
410
|
+
TRANSACTIONAL_NOT_ALLOWED_REFUSAL: () => TRANSACTIONAL_NOT_ALLOWED_REFUSAL,
|
|
411
|
+
TRANSACTIONAL_UNSUBSCRIBE_URL_REFUSAL: () => TRANSACTIONAL_UNSUBSCRIBE_URL_REFUSAL,
|
|
399
412
|
TRUSTED_APPS: () => TRUSTED_APPS,
|
|
400
413
|
TRUSTED_APP_OPERATIONS: () => TRUSTED_APP_OPERATIONS,
|
|
401
414
|
Tag: () => Tag,
|
|
@@ -1794,6 +1807,17 @@ var Mailing = import_zod8.z.object({
|
|
|
1794
1807
|
* the workspace's defaults, below the recipient's own. Empty by default.
|
|
1795
1808
|
*/
|
|
1796
1809
|
merge: MailingMerge.default({}),
|
|
1810
|
+
/**
|
|
1811
|
+
* Where a reader's reply goes for this mailing, or null for the sending
|
|
1812
|
+
* provider's own reply address (see `MailingContent.reply_to`).
|
|
1813
|
+
*/
|
|
1814
|
+
reply_to: Email.nullable().default(null),
|
|
1815
|
+
/**
|
|
1816
|
+
* Whether this is a transactional letter (see `MailingCreate.transactional`
|
|
1817
|
+
* and "Transactional letters" in the contract's documentation). False for
|
|
1818
|
+
* every mailing made without the flag.
|
|
1819
|
+
*/
|
|
1820
|
+
transactional: import_zod8.z.boolean().default(false),
|
|
1797
1821
|
scheduled_at: Timestamp.nullable(),
|
|
1798
1822
|
/** The A/B test on subject or content (S4), null when there is none. */
|
|
1799
1823
|
ab_test: AbTestState.nullable(),
|
|
@@ -1818,22 +1842,46 @@ var MailingContent = {
|
|
|
1818
1842
|
send_locale: LocaleTag.nullable().optional(),
|
|
1819
1843
|
/**
|
|
1820
1844
|
* Omitted or null makes the mailing a letter: one recipient at most, sent to
|
|
1821
|
-
* anybody not blocked on every topic, with an unsubscribe link
|
|
1822
|
-
*
|
|
1845
|
+
* anybody not blocked on every topic, with an unsubscribe link and
|
|
1846
|
+
* List-Unsubscribe headers that offer every topic. See "Letters" in the
|
|
1823
1847
|
* contract's documentation.
|
|
1824
1848
|
*/
|
|
1825
1849
|
topic: Slug.nullable().optional(),
|
|
1826
1850
|
provider_id: Id,
|
|
1827
1851
|
metadata: MailingMetadata.optional(),
|
|
1828
1852
|
/** See `Mailing.merge`. `first_name` and `last_name` only on a letter (no topic). */
|
|
1829
|
-
merge: MailingMerge.optional()
|
|
1853
|
+
merge: MailingMerge.optional(),
|
|
1854
|
+
/**
|
|
1855
|
+
* The Reply-To of this mailing's messages: one address, in place of the
|
|
1856
|
+
* sending provider's `reply_to`. Omitted or null keeps the provider's. The
|
|
1857
|
+
* sender (From) is always the provider's, and so is the mailto alternative
|
|
1858
|
+
* of the List-Unsubscribe header, since a request to leave belongs to the
|
|
1859
|
+
* workspace and not to whoever a reply reaches.
|
|
1860
|
+
*/
|
|
1861
|
+
reply_to: Email.nullable().optional()
|
|
1830
1862
|
};
|
|
1831
1863
|
var MailingCreate = import_zod8.z.object({
|
|
1832
1864
|
...MailingContent,
|
|
1833
1865
|
subject: MailingContent.subject.optional(),
|
|
1834
1866
|
document: TemplateDocument.optional(),
|
|
1835
1867
|
template_id: Id.optional(),
|
|
1836
|
-
template_locale: LocaleTag.optional()
|
|
1868
|
+
template_locale: LocaleTag.optional(),
|
|
1869
|
+
/**
|
|
1870
|
+
* True makes the mailing a transactional letter: mail that answers
|
|
1871
|
+
* something its one reader did and that they need whatever they chose
|
|
1872
|
+
* about marketing (a booking's confirmation, its reminder, its
|
|
1873
|
+
* cancellation). It needs no `{{unsubscribe_url}}`, carries no
|
|
1874
|
+
* List-Unsubscribe headers and is not stopped by an unsubscribe; a hard
|
|
1875
|
+
* bounce, a spam complaint and a block set by hand still stop it.
|
|
1876
|
+
*
|
|
1877
|
+
* Only a key that a trusted application created may set it (`forbidden`,
|
|
1878
|
+
* `details.reason: "transactional_not_allowed"`), only on a letter
|
|
1879
|
+
* (`validation_failed`, `"transactional_needs_letter"`), from a template
|
|
1880
|
+
* only with `template_locale` (`"transactional_needs_template_locale"`),
|
|
1881
|
+
* and it is fixed when the mailing is created. See "Transactional letters" in the
|
|
1882
|
+
* contract's documentation.
|
|
1883
|
+
*/
|
|
1884
|
+
transactional: import_zod8.z.boolean().optional()
|
|
1837
1885
|
}).refine((v) => v.document === void 0 !== (v.template_id === void 0), {
|
|
1838
1886
|
message: "exactly one of document or template_id",
|
|
1839
1887
|
path: ["document"]
|
|
@@ -1860,6 +1908,8 @@ var MailingUpdate = import_zod8.z.object({
|
|
|
1860
1908
|
* them.
|
|
1861
1909
|
*/
|
|
1862
1910
|
merge: MailingMerge.optional(),
|
|
1911
|
+
/** See `MailingContent.reply_to`. Null goes back to the provider's reply address. */
|
|
1912
|
+
reply_to: Email.nullable().optional(),
|
|
1863
1913
|
document: TemplateDocument.optional()
|
|
1864
1914
|
}).refine((v) => Object.keys(v).length > 0, "at least one field");
|
|
1865
1915
|
var MailingListQuery = PageQuery.extend({
|
|
@@ -1908,6 +1958,11 @@ var Recipient = import_zod8.z.object({
|
|
|
1908
1958
|
var MAX_RECIPIENTS_PER_BATCH = 1e3;
|
|
1909
1959
|
var MAX_LETTER_RECIPIENTS = 1;
|
|
1910
1960
|
var LETTER_RECIPIENT_REFUSAL = "letter_has_one_recipient";
|
|
1961
|
+
var TRANSACTIONAL_NOT_ALLOWED_REFUSAL = "transactional_not_allowed";
|
|
1962
|
+
var TRANSACTIONAL_NEEDS_LETTER_REFUSAL = "transactional_needs_letter";
|
|
1963
|
+
var TRANSACTIONAL_NEEDS_TEMPLATE_LOCALE_REFUSAL = "transactional_needs_template_locale";
|
|
1964
|
+
var TRANSACTIONAL_UNSUBSCRIBE_URL_REFUSAL = "transactional_has_unsubscribe_url";
|
|
1965
|
+
var TRANSACTIONAL_BLOCKING_REASONS = ["bounced", "complained", "manual"];
|
|
1911
1966
|
var RecipientInput = import_zod8.z.object({
|
|
1912
1967
|
contact_id: Id.optional(),
|
|
1913
1968
|
external_id: import_zod8.z.string().min(1).max(255).optional(),
|
|
@@ -3427,12 +3482,13 @@ var WorkspaceCreate = import_zod11.z.object({
|
|
|
3427
3482
|
name: import_zod11.z.string().max(200).nullable().optional()
|
|
3428
3483
|
}),
|
|
3429
3484
|
/**
|
|
3430
|
-
* The
|
|
3431
|
-
*
|
|
3432
|
-
* erasure
|
|
3433
|
-
*
|
|
3485
|
+
* The auth-brain company the workspace is created in. Required since 0.14.0:
|
|
3486
|
+
* every new workspace belongs to a company, which is what links it to that
|
|
3487
|
+
* company's erasure and lets the company's owners and admins in without an
|
|
3488
|
+
* invitation (`members.syncCompanyRole`). A workspace created before, without
|
|
3489
|
+
* one, keeps working and simply has no such inheritance.
|
|
3434
3490
|
*/
|
|
3435
|
-
company_id: CompanyId
|
|
3491
|
+
company_id: CompanyId
|
|
3436
3492
|
});
|
|
3437
3493
|
var WorkspaceUpdate = import_zod11.z.object({
|
|
3438
3494
|
name: import_zod11.z.string().min(1).max(120),
|
|
@@ -3442,14 +3498,58 @@ var WorkspaceMove = import_zod11.z.object({ company_id: CompanyId });
|
|
|
3442
3498
|
var MEMBER_ROLES = ["owner", "admin", "editor", "viewer"];
|
|
3443
3499
|
var MemberRole = import_zod11.z.enum(MEMBER_ROLES);
|
|
3444
3500
|
var WorkspaceMembership = Workspace.extend({ role: MemberRole });
|
|
3501
|
+
var MEMBER_SOURCES = ["invited", "company"];
|
|
3502
|
+
var MemberSource = import_zod11.z.enum(MEMBER_SOURCES);
|
|
3503
|
+
var COMPANY_GRANT_ROLES = ["owner", "admin"];
|
|
3504
|
+
var CompanyGrantRole = import_zod11.z.enum(COMPANY_GRANT_ROLES);
|
|
3505
|
+
var COMPANY_ROLE_MAX_AGE_HOURS = 24;
|
|
3445
3506
|
var Member = import_zod11.z.object({
|
|
3446
3507
|
id: Id,
|
|
3447
3508
|
/** The person's auth-brain subject. */
|
|
3448
3509
|
subject: import_zod11.z.string().min(1).max(255),
|
|
3449
3510
|
email: Email,
|
|
3450
3511
|
name: import_zod11.z.string().max(200).nullable(),
|
|
3512
|
+
/**
|
|
3513
|
+
* The role in force: the higher of the person's own role in the workspace
|
|
3514
|
+
* and the one a confirmed company role carries. For a `company` row that is
|
|
3515
|
+
* no longer confirmed, the role it would carry once confirmed again.
|
|
3516
|
+
*/
|
|
3451
3517
|
role: MemberRole,
|
|
3452
|
-
created_at: Timestamp
|
|
3518
|
+
created_at: Timestamp,
|
|
3519
|
+
/*
|
|
3520
|
+
* The five fields below exist since 0.14.0 and are optional only so that a
|
|
3521
|
+
* client built against this contract can still read a service that predates
|
|
3522
|
+
* them: absent means an ordinary, invited member.
|
|
3523
|
+
*/
|
|
3524
|
+
source: MemberSource.optional(),
|
|
3525
|
+
/** The company role last reported for the person (`members.syncCompanyRole`), or null. */
|
|
3526
|
+
company_role: CompanyGrantRole.nullable().optional(),
|
|
3527
|
+
/** When the dashboard last confirmed `company_role`; null without one. */
|
|
3528
|
+
company_checked_at: Timestamp.nullable().optional(),
|
|
3529
|
+
/** The person's own role in the workspace; null for a `company` row. */
|
|
3530
|
+
direct_role: MemberRole.nullable().optional(),
|
|
3531
|
+
/**
|
|
3532
|
+
* True while `role` is held only through a confirmed company role. Such a
|
|
3533
|
+
* member cannot be changed or removed here (`inherited_from_company`): the
|
|
3534
|
+
* role is managed in the shared login. A `company` row with `inherited`
|
|
3535
|
+
* false is one whose company role has not been confirmed within
|
|
3536
|
+
* `COMPANY_ROLE_MAX_AGE_HOURS`; it grants nothing and an admin may remove it.
|
|
3537
|
+
*/
|
|
3538
|
+
inherited: import_zod11.z.boolean().optional()
|
|
3539
|
+
});
|
|
3540
|
+
var MAX_SYNC_COMPANIES = 100;
|
|
3541
|
+
var MemberCompanySync = import_zod11.z.object({
|
|
3542
|
+
email: Email,
|
|
3543
|
+
name: import_zod11.z.string().max(200).nullable().optional(),
|
|
3544
|
+
companies: import_zod11.z.array(import_zod11.z.object({ company_id: CompanyId, role: CompanyGrantRole })).max(MAX_SYNC_COMPANIES).refine((list2) => new Set(list2.map((c) => c.company_id)).size === list2.length, "each company at most once")
|
|
3545
|
+
});
|
|
3546
|
+
var MemberCompanySyncResult = import_zod11.z.object({
|
|
3547
|
+
/** Workspaces in which the person now holds a company role they did not hold, or held differently, before this call. */
|
|
3548
|
+
granted: import_zod11.z.array(Id),
|
|
3549
|
+
/** Workspaces in which a company role was taken away by this call. */
|
|
3550
|
+
revoked: import_zod11.z.array(Id),
|
|
3551
|
+
/** Workspaces in which the person's company role was already as stated. */
|
|
3552
|
+
unchanged: import_zod11.z.array(Id)
|
|
3453
3553
|
});
|
|
3454
3554
|
var MemberCreate = import_zod11.z.object({
|
|
3455
3555
|
subject: import_zod11.z.string().min(1).max(255),
|
|
@@ -5057,6 +5157,24 @@ var foundationRoutes = {
|
|
|
5057
5157
|
access: "admin",
|
|
5058
5158
|
phase: "S0"
|
|
5059
5159
|
},
|
|
5160
|
+
/**
|
|
5161
|
+
* The dashboard states the signed-in person's owner and admin roles in
|
|
5162
|
+
* companies, and the service brings the member lists in line (see
|
|
5163
|
+
* `MemberCompanySync`). `dashboard` access: the dashboard's service token
|
|
5164
|
+
* and the person's subject, no workspace. An API key is refused, and so is
|
|
5165
|
+
* every trusted application: it is not in any `TRUSTED_APP_OPERATIONS` list
|
|
5166
|
+
* and the handler refuses an application once more by itself.
|
|
5167
|
+
*/
|
|
5168
|
+
"members.syncCompanyRole": {
|
|
5169
|
+
method: "POST",
|
|
5170
|
+
path: "/v1/members/company-sync",
|
|
5171
|
+
body: MemberCompanySync,
|
|
5172
|
+
response: MemberCompanySyncResult,
|
|
5173
|
+
status: 200,
|
|
5174
|
+
access: "dashboard",
|
|
5175
|
+
phase: "S0",
|
|
5176
|
+
statement: true
|
|
5177
|
+
},
|
|
5060
5178
|
"apiKeys.list": {
|
|
5061
5179
|
method: "GET",
|
|
5062
5180
|
path: "/v1/api-keys",
|
|
@@ -6360,7 +6478,7 @@ function trustedAppMayCall(app, id) {
|
|
|
6360
6478
|
return TRUSTED_APP_OPERATIONS[app].includes(id);
|
|
6361
6479
|
}
|
|
6362
6480
|
function acceptsIdempotencyKey(route) {
|
|
6363
|
-
return route.method !== "GET";
|
|
6481
|
+
return route.method !== "GET" && route.statement !== true;
|
|
6364
6482
|
}
|
|
6365
6483
|
function buildPath(path, params = {}) {
|
|
6366
6484
|
return path.replace(/:([a-z_]+)/g, (_, name) => {
|
|
@@ -6481,10 +6599,13 @@ function matchRoute(method, pathname) {
|
|
|
6481
6599
|
BILLING_NOT_CONFIGURED_REASON,
|
|
6482
6600
|
BoundedAutomationFilter,
|
|
6483
6601
|
BoundedSegmentFilter,
|
|
6602
|
+
COMPANY_GRANT_ROLES,
|
|
6603
|
+
COMPANY_ROLE_MAX_AGE_HOURS,
|
|
6484
6604
|
CONTACT_PROPERTY_TYPES,
|
|
6485
6605
|
CatalogPlan,
|
|
6486
6606
|
CheckoutRequest,
|
|
6487
6607
|
CheckoutSession,
|
|
6608
|
+
CompanyGrantRole,
|
|
6488
6609
|
CompanyId,
|
|
6489
6610
|
CompileMessage,
|
|
6490
6611
|
CompileRequest,
|
|
@@ -6623,6 +6744,7 @@ function matchRoute(method, pathname) {
|
|
|
6623
6744
|
MAX_STEPS,
|
|
6624
6745
|
MAX_STEP_VISITS,
|
|
6625
6746
|
MAX_SUBJECT_LENGTH,
|
|
6747
|
+
MAX_SYNC_COMPANIES,
|
|
6626
6748
|
MAX_TEMPLATE_INPUTS,
|
|
6627
6749
|
MAX_TEMPLATE_INPUTS_APP_LENGTH,
|
|
6628
6750
|
MAX_TEMPLATE_INPUTS_SEEN,
|
|
@@ -6633,6 +6755,7 @@ function matchRoute(method, pathname) {
|
|
|
6633
6755
|
MAX_TEMPLATE_TRANSLATIONS,
|
|
6634
6756
|
MAX_TRIGGERS,
|
|
6635
6757
|
MEMBER_ROLES,
|
|
6758
|
+
MEMBER_SOURCES,
|
|
6636
6759
|
MERGE_FIELD_PATTERN,
|
|
6637
6760
|
MESSAGE_OUTCOMES,
|
|
6638
6761
|
MIN_SPLIT_BRANCHES,
|
|
@@ -6668,8 +6791,11 @@ function matchRoute(method, pathname) {
|
|
|
6668
6791
|
MailingTestResult,
|
|
6669
6792
|
MailingUpdate,
|
|
6670
6793
|
Member,
|
|
6794
|
+
MemberCompanySync,
|
|
6795
|
+
MemberCompanySyncResult,
|
|
6671
6796
|
MemberCreate,
|
|
6672
6797
|
MemberRole,
|
|
6798
|
+
MemberSource,
|
|
6673
6799
|
MemberUpdate,
|
|
6674
6800
|
MergeDefaultValue,
|
|
6675
6801
|
MergeDefaults,
|
|
@@ -6770,6 +6896,11 @@ function matchRoute(method, pathname) {
|
|
|
6770
6896
|
TEMPLATE_SORTS,
|
|
6771
6897
|
TEMPLATE_SORT_DEFAULT_ORDER,
|
|
6772
6898
|
TERMINAL_MAILING_STATUSES,
|
|
6899
|
+
TRANSACTIONAL_BLOCKING_REASONS,
|
|
6900
|
+
TRANSACTIONAL_NEEDS_LETTER_REFUSAL,
|
|
6901
|
+
TRANSACTIONAL_NEEDS_TEMPLATE_LOCALE_REFUSAL,
|
|
6902
|
+
TRANSACTIONAL_NOT_ALLOWED_REFUSAL,
|
|
6903
|
+
TRANSACTIONAL_UNSUBSCRIBE_URL_REFUSAL,
|
|
6773
6904
|
TRUSTED_APPS,
|
|
6774
6905
|
TRUSTED_APP_OPERATIONS,
|
|
6775
6906
|
Tag,
|
package/dist/index.mjs
CHANGED
|
@@ -1168,6 +1168,17 @@ var Mailing = z8.object({
|
|
|
1168
1168
|
* the workspace's defaults, below the recipient's own. Empty by default.
|
|
1169
1169
|
*/
|
|
1170
1170
|
merge: MailingMerge.default({}),
|
|
1171
|
+
/**
|
|
1172
|
+
* Where a reader's reply goes for this mailing, or null for the sending
|
|
1173
|
+
* provider's own reply address (see `MailingContent.reply_to`).
|
|
1174
|
+
*/
|
|
1175
|
+
reply_to: Email.nullable().default(null),
|
|
1176
|
+
/**
|
|
1177
|
+
* Whether this is a transactional letter (see `MailingCreate.transactional`
|
|
1178
|
+
* and "Transactional letters" in the contract's documentation). False for
|
|
1179
|
+
* every mailing made without the flag.
|
|
1180
|
+
*/
|
|
1181
|
+
transactional: z8.boolean().default(false),
|
|
1171
1182
|
scheduled_at: Timestamp.nullable(),
|
|
1172
1183
|
/** The A/B test on subject or content (S4), null when there is none. */
|
|
1173
1184
|
ab_test: AbTestState.nullable(),
|
|
@@ -1192,22 +1203,46 @@ var MailingContent = {
|
|
|
1192
1203
|
send_locale: LocaleTag.nullable().optional(),
|
|
1193
1204
|
/**
|
|
1194
1205
|
* Omitted or null makes the mailing a letter: one recipient at most, sent to
|
|
1195
|
-
* anybody not blocked on every topic, with an unsubscribe link
|
|
1196
|
-
*
|
|
1206
|
+
* anybody not blocked on every topic, with an unsubscribe link and
|
|
1207
|
+
* List-Unsubscribe headers that offer every topic. See "Letters" in the
|
|
1197
1208
|
* contract's documentation.
|
|
1198
1209
|
*/
|
|
1199
1210
|
topic: Slug.nullable().optional(),
|
|
1200
1211
|
provider_id: Id,
|
|
1201
1212
|
metadata: MailingMetadata.optional(),
|
|
1202
1213
|
/** See `Mailing.merge`. `first_name` and `last_name` only on a letter (no topic). */
|
|
1203
|
-
merge: MailingMerge.optional()
|
|
1214
|
+
merge: MailingMerge.optional(),
|
|
1215
|
+
/**
|
|
1216
|
+
* The Reply-To of this mailing's messages: one address, in place of the
|
|
1217
|
+
* sending provider's `reply_to`. Omitted or null keeps the provider's. The
|
|
1218
|
+
* sender (From) is always the provider's, and so is the mailto alternative
|
|
1219
|
+
* of the List-Unsubscribe header, since a request to leave belongs to the
|
|
1220
|
+
* workspace and not to whoever a reply reaches.
|
|
1221
|
+
*/
|
|
1222
|
+
reply_to: Email.nullable().optional()
|
|
1204
1223
|
};
|
|
1205
1224
|
var MailingCreate = z8.object({
|
|
1206
1225
|
...MailingContent,
|
|
1207
1226
|
subject: MailingContent.subject.optional(),
|
|
1208
1227
|
document: TemplateDocument.optional(),
|
|
1209
1228
|
template_id: Id.optional(),
|
|
1210
|
-
template_locale: LocaleTag.optional()
|
|
1229
|
+
template_locale: LocaleTag.optional(),
|
|
1230
|
+
/**
|
|
1231
|
+
* True makes the mailing a transactional letter: mail that answers
|
|
1232
|
+
* something its one reader did and that they need whatever they chose
|
|
1233
|
+
* about marketing (a booking's confirmation, its reminder, its
|
|
1234
|
+
* cancellation). It needs no `{{unsubscribe_url}}`, carries no
|
|
1235
|
+
* List-Unsubscribe headers and is not stopped by an unsubscribe; a hard
|
|
1236
|
+
* bounce, a spam complaint and a block set by hand still stop it.
|
|
1237
|
+
*
|
|
1238
|
+
* Only a key that a trusted application created may set it (`forbidden`,
|
|
1239
|
+
* `details.reason: "transactional_not_allowed"`), only on a letter
|
|
1240
|
+
* (`validation_failed`, `"transactional_needs_letter"`), from a template
|
|
1241
|
+
* only with `template_locale` (`"transactional_needs_template_locale"`),
|
|
1242
|
+
* and it is fixed when the mailing is created. See "Transactional letters" in the
|
|
1243
|
+
* contract's documentation.
|
|
1244
|
+
*/
|
|
1245
|
+
transactional: z8.boolean().optional()
|
|
1211
1246
|
}).refine((v) => v.document === void 0 !== (v.template_id === void 0), {
|
|
1212
1247
|
message: "exactly one of document or template_id",
|
|
1213
1248
|
path: ["document"]
|
|
@@ -1234,6 +1269,8 @@ var MailingUpdate = z8.object({
|
|
|
1234
1269
|
* them.
|
|
1235
1270
|
*/
|
|
1236
1271
|
merge: MailingMerge.optional(),
|
|
1272
|
+
/** See `MailingContent.reply_to`. Null goes back to the provider's reply address. */
|
|
1273
|
+
reply_to: Email.nullable().optional(),
|
|
1237
1274
|
document: TemplateDocument.optional()
|
|
1238
1275
|
}).refine((v) => Object.keys(v).length > 0, "at least one field");
|
|
1239
1276
|
var MailingListQuery = PageQuery.extend({
|
|
@@ -1282,6 +1319,11 @@ var Recipient = z8.object({
|
|
|
1282
1319
|
var MAX_RECIPIENTS_PER_BATCH = 1e3;
|
|
1283
1320
|
var MAX_LETTER_RECIPIENTS = 1;
|
|
1284
1321
|
var LETTER_RECIPIENT_REFUSAL = "letter_has_one_recipient";
|
|
1322
|
+
var TRANSACTIONAL_NOT_ALLOWED_REFUSAL = "transactional_not_allowed";
|
|
1323
|
+
var TRANSACTIONAL_NEEDS_LETTER_REFUSAL = "transactional_needs_letter";
|
|
1324
|
+
var TRANSACTIONAL_NEEDS_TEMPLATE_LOCALE_REFUSAL = "transactional_needs_template_locale";
|
|
1325
|
+
var TRANSACTIONAL_UNSUBSCRIBE_URL_REFUSAL = "transactional_has_unsubscribe_url";
|
|
1326
|
+
var TRANSACTIONAL_BLOCKING_REASONS = ["bounced", "complained", "manual"];
|
|
1285
1327
|
var RecipientInput = z8.object({
|
|
1286
1328
|
contact_id: Id.optional(),
|
|
1287
1329
|
external_id: z8.string().min(1).max(255).optional(),
|
|
@@ -2801,12 +2843,13 @@ var WorkspaceCreate = z11.object({
|
|
|
2801
2843
|
name: z11.string().max(200).nullable().optional()
|
|
2802
2844
|
}),
|
|
2803
2845
|
/**
|
|
2804
|
-
* The
|
|
2805
|
-
*
|
|
2806
|
-
* erasure
|
|
2807
|
-
*
|
|
2846
|
+
* The auth-brain company the workspace is created in. Required since 0.14.0:
|
|
2847
|
+
* every new workspace belongs to a company, which is what links it to that
|
|
2848
|
+
* company's erasure and lets the company's owners and admins in without an
|
|
2849
|
+
* invitation (`members.syncCompanyRole`). A workspace created before, without
|
|
2850
|
+
* one, keeps working and simply has no such inheritance.
|
|
2808
2851
|
*/
|
|
2809
|
-
company_id: CompanyId
|
|
2852
|
+
company_id: CompanyId
|
|
2810
2853
|
});
|
|
2811
2854
|
var WorkspaceUpdate = z11.object({
|
|
2812
2855
|
name: z11.string().min(1).max(120),
|
|
@@ -2816,14 +2859,58 @@ var WorkspaceMove = z11.object({ company_id: CompanyId });
|
|
|
2816
2859
|
var MEMBER_ROLES = ["owner", "admin", "editor", "viewer"];
|
|
2817
2860
|
var MemberRole = z11.enum(MEMBER_ROLES);
|
|
2818
2861
|
var WorkspaceMembership = Workspace.extend({ role: MemberRole });
|
|
2862
|
+
var MEMBER_SOURCES = ["invited", "company"];
|
|
2863
|
+
var MemberSource = z11.enum(MEMBER_SOURCES);
|
|
2864
|
+
var COMPANY_GRANT_ROLES = ["owner", "admin"];
|
|
2865
|
+
var CompanyGrantRole = z11.enum(COMPANY_GRANT_ROLES);
|
|
2866
|
+
var COMPANY_ROLE_MAX_AGE_HOURS = 24;
|
|
2819
2867
|
var Member = z11.object({
|
|
2820
2868
|
id: Id,
|
|
2821
2869
|
/** The person's auth-brain subject. */
|
|
2822
2870
|
subject: z11.string().min(1).max(255),
|
|
2823
2871
|
email: Email,
|
|
2824
2872
|
name: z11.string().max(200).nullable(),
|
|
2873
|
+
/**
|
|
2874
|
+
* The role in force: the higher of the person's own role in the workspace
|
|
2875
|
+
* and the one a confirmed company role carries. For a `company` row that is
|
|
2876
|
+
* no longer confirmed, the role it would carry once confirmed again.
|
|
2877
|
+
*/
|
|
2825
2878
|
role: MemberRole,
|
|
2826
|
-
created_at: Timestamp
|
|
2879
|
+
created_at: Timestamp,
|
|
2880
|
+
/*
|
|
2881
|
+
* The five fields below exist since 0.14.0 and are optional only so that a
|
|
2882
|
+
* client built against this contract can still read a service that predates
|
|
2883
|
+
* them: absent means an ordinary, invited member.
|
|
2884
|
+
*/
|
|
2885
|
+
source: MemberSource.optional(),
|
|
2886
|
+
/** The company role last reported for the person (`members.syncCompanyRole`), or null. */
|
|
2887
|
+
company_role: CompanyGrantRole.nullable().optional(),
|
|
2888
|
+
/** When the dashboard last confirmed `company_role`; null without one. */
|
|
2889
|
+
company_checked_at: Timestamp.nullable().optional(),
|
|
2890
|
+
/** The person's own role in the workspace; null for a `company` row. */
|
|
2891
|
+
direct_role: MemberRole.nullable().optional(),
|
|
2892
|
+
/**
|
|
2893
|
+
* True while `role` is held only through a confirmed company role. Such a
|
|
2894
|
+
* member cannot be changed or removed here (`inherited_from_company`): the
|
|
2895
|
+
* role is managed in the shared login. A `company` row with `inherited`
|
|
2896
|
+
* false is one whose company role has not been confirmed within
|
|
2897
|
+
* `COMPANY_ROLE_MAX_AGE_HOURS`; it grants nothing and an admin may remove it.
|
|
2898
|
+
*/
|
|
2899
|
+
inherited: z11.boolean().optional()
|
|
2900
|
+
});
|
|
2901
|
+
var MAX_SYNC_COMPANIES = 100;
|
|
2902
|
+
var MemberCompanySync = z11.object({
|
|
2903
|
+
email: Email,
|
|
2904
|
+
name: z11.string().max(200).nullable().optional(),
|
|
2905
|
+
companies: z11.array(z11.object({ company_id: CompanyId, role: CompanyGrantRole })).max(MAX_SYNC_COMPANIES).refine((list2) => new Set(list2.map((c) => c.company_id)).size === list2.length, "each company at most once")
|
|
2906
|
+
});
|
|
2907
|
+
var MemberCompanySyncResult = z11.object({
|
|
2908
|
+
/** Workspaces in which the person now holds a company role they did not hold, or held differently, before this call. */
|
|
2909
|
+
granted: z11.array(Id),
|
|
2910
|
+
/** Workspaces in which a company role was taken away by this call. */
|
|
2911
|
+
revoked: z11.array(Id),
|
|
2912
|
+
/** Workspaces in which the person's company role was already as stated. */
|
|
2913
|
+
unchanged: z11.array(Id)
|
|
2827
2914
|
});
|
|
2828
2915
|
var MemberCreate = z11.object({
|
|
2829
2916
|
subject: z11.string().min(1).max(255),
|
|
@@ -4431,6 +4518,24 @@ var foundationRoutes = {
|
|
|
4431
4518
|
access: "admin",
|
|
4432
4519
|
phase: "S0"
|
|
4433
4520
|
},
|
|
4521
|
+
/**
|
|
4522
|
+
* The dashboard states the signed-in person's owner and admin roles in
|
|
4523
|
+
* companies, and the service brings the member lists in line (see
|
|
4524
|
+
* `MemberCompanySync`). `dashboard` access: the dashboard's service token
|
|
4525
|
+
* and the person's subject, no workspace. An API key is refused, and so is
|
|
4526
|
+
* every trusted application: it is not in any `TRUSTED_APP_OPERATIONS` list
|
|
4527
|
+
* and the handler refuses an application once more by itself.
|
|
4528
|
+
*/
|
|
4529
|
+
"members.syncCompanyRole": {
|
|
4530
|
+
method: "POST",
|
|
4531
|
+
path: "/v1/members/company-sync",
|
|
4532
|
+
body: MemberCompanySync,
|
|
4533
|
+
response: MemberCompanySyncResult,
|
|
4534
|
+
status: 200,
|
|
4535
|
+
access: "dashboard",
|
|
4536
|
+
phase: "S0",
|
|
4537
|
+
statement: true
|
|
4538
|
+
},
|
|
4434
4539
|
"apiKeys.list": {
|
|
4435
4540
|
method: "GET",
|
|
4436
4541
|
path: "/v1/api-keys",
|
|
@@ -5734,7 +5839,7 @@ function trustedAppMayCall(app, id) {
|
|
|
5734
5839
|
return TRUSTED_APP_OPERATIONS[app].includes(id);
|
|
5735
5840
|
}
|
|
5736
5841
|
function acceptsIdempotencyKey(route) {
|
|
5737
|
-
return route.method !== "GET";
|
|
5842
|
+
return route.method !== "GET" && route.statement !== true;
|
|
5738
5843
|
}
|
|
5739
5844
|
function buildPath(path, params = {}) {
|
|
5740
5845
|
return path.replace(/:([a-z_]+)/g, (_, name) => {
|
|
@@ -5854,10 +5959,13 @@ export {
|
|
|
5854
5959
|
BILLING_NOT_CONFIGURED_REASON,
|
|
5855
5960
|
BoundedAutomationFilter,
|
|
5856
5961
|
BoundedSegmentFilter,
|
|
5962
|
+
COMPANY_GRANT_ROLES,
|
|
5963
|
+
COMPANY_ROLE_MAX_AGE_HOURS,
|
|
5857
5964
|
CONTACT_PROPERTY_TYPES,
|
|
5858
5965
|
CatalogPlan,
|
|
5859
5966
|
CheckoutRequest,
|
|
5860
5967
|
CheckoutSession,
|
|
5968
|
+
CompanyGrantRole,
|
|
5861
5969
|
CompanyId,
|
|
5862
5970
|
CompileMessage,
|
|
5863
5971
|
CompileRequest,
|
|
@@ -5996,6 +6104,7 @@ export {
|
|
|
5996
6104
|
MAX_STEPS,
|
|
5997
6105
|
MAX_STEP_VISITS,
|
|
5998
6106
|
MAX_SUBJECT_LENGTH,
|
|
6107
|
+
MAX_SYNC_COMPANIES,
|
|
5999
6108
|
MAX_TEMPLATE_INPUTS,
|
|
6000
6109
|
MAX_TEMPLATE_INPUTS_APP_LENGTH,
|
|
6001
6110
|
MAX_TEMPLATE_INPUTS_SEEN,
|
|
@@ -6006,6 +6115,7 @@ export {
|
|
|
6006
6115
|
MAX_TEMPLATE_TRANSLATIONS,
|
|
6007
6116
|
MAX_TRIGGERS,
|
|
6008
6117
|
MEMBER_ROLES,
|
|
6118
|
+
MEMBER_SOURCES,
|
|
6009
6119
|
MERGE_FIELD_PATTERN,
|
|
6010
6120
|
MESSAGE_OUTCOMES,
|
|
6011
6121
|
MIN_SPLIT_BRANCHES,
|
|
@@ -6041,8 +6151,11 @@ export {
|
|
|
6041
6151
|
MailingTestResult,
|
|
6042
6152
|
MailingUpdate,
|
|
6043
6153
|
Member,
|
|
6154
|
+
MemberCompanySync,
|
|
6155
|
+
MemberCompanySyncResult,
|
|
6044
6156
|
MemberCreate,
|
|
6045
6157
|
MemberRole,
|
|
6158
|
+
MemberSource,
|
|
6046
6159
|
MemberUpdate,
|
|
6047
6160
|
MergeDefaultValue,
|
|
6048
6161
|
MergeDefaults,
|
|
@@ -6143,6 +6256,11 @@ export {
|
|
|
6143
6256
|
TEMPLATE_SORTS,
|
|
6144
6257
|
TEMPLATE_SORT_DEFAULT_ORDER,
|
|
6145
6258
|
TERMINAL_MAILING_STATUSES,
|
|
6259
|
+
TRANSACTIONAL_BLOCKING_REASONS,
|
|
6260
|
+
TRANSACTIONAL_NEEDS_LETTER_REFUSAL,
|
|
6261
|
+
TRANSACTIONAL_NEEDS_TEMPLATE_LOCALE_REFUSAL,
|
|
6262
|
+
TRANSACTIONAL_NOT_ALLOWED_REFUSAL,
|
|
6263
|
+
TRANSACTIONAL_UNSUBSCRIBE_URL_REFUSAL,
|
|
6146
6264
|
TRUSTED_APPS,
|
|
6147
6265
|
TRUSTED_APP_OPERATIONS,
|
|
6148
6266
|
Tag,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.14.0",
|
|
7
7
|
"description": "The v1 API contract of the mail service: zod schemas and types for every request, response, error and webhook, the route table, and webhook signing helpers",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": {
|