perspectapi-ts-sdk 7.2.8 → 7.4.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/README.md +54 -0
- package/dist/{chunk-WD62IBI5.mjs → chunk-PWZSSX4V.mjs} +170 -4
- package/dist/{index-BbTVcEl5.d.mts → index-CmcHYKO8.d.mts} +259 -7
- package/dist/{index-BbTVcEl5.d.ts → index-CmcHYKO8.d.ts} +259 -7
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +169 -4
- package/dist/index.mjs +1 -1
- package/dist/v2/index.d.mts +1 -1
- package/dist/v2/index.d.ts +1 -1
- package/dist/v2/index.js +171 -4
- package/dist/v2/index.mjs +3 -1
- package/package.json +1 -1
- package/src/utils/http-client.ts +17 -5
- package/src/v2/client/email-client.ts +11 -4
- package/src/v2/client/email-templates-client.ts +113 -0
- package/src/v2/client/newsletter-client.ts +156 -0
- package/src/v2/index.ts +4 -0
- package/src/v2/types.ts +233 -2
package/dist/index.mjs
CHANGED
package/dist/v2/index.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { cI as ApiKeysV2Client, cx as BaseV2Client, cA as CategoriesV2Client, cB as CollectionsV2Client, cF as ContactsV2Client, cy as ContentV2Client, cL as CreditsV2Client, cN as EmailTemplatesV2Client, cM as EmailV2Client, cE as NewsletterV2Client, cC as OrdersV2Client, cG as OrganizationsV2Client, ay as PerspectApiV2Client, cw as PerspectApiV2Config, aA as PerspectV2Error, cz as ProductsV2Client, cD as SiteUsersV2Client, cH as SitesV2Client, cK as SubscriptionsV2Client, bS as V2ApiKey, c1 as V2CancelSubscriptionResult, b4 as V2Category, b5 as V2CategoryCreateParams, b6 as V2CategoryUpdateParams, b7 as V2Collection, b9 as V2CollectionCreateParams, b8 as V2CollectionItem, ba as V2CollectionUpdateParams, bP as V2ContactSubmission, aY as V2Content, aZ as V2ContentCreateParams, a$ as V2ContentListParams, a_ as V2ContentUpdateParams, c3 as V2CreditBalance, c2 as V2CreditTransaction, aT as V2Deleted, c8 as V2EmailSendParams, ce as V2EmailSendResult, c9 as V2EmailTemplate, cd as V2EmailTemplateCloneParams, cc as V2EmailTemplateCreateParams, cb as V2EmailTemplateListParams, c7 as V2EmailTemplateStatus, c6 as V2EmailTemplateType, ca as V2EmailTemplateType_Listing, aU as V2Error, aV as V2ErrorType, c4 as V2GrantCreditParams, c5 as V2GrantCreditResult, aS as V2List, aX as V2Media, bN as V2NewsletterBulkParams, bO as V2NewsletterBulkResult, bw as V2NewsletterCampaign, bH as V2NewsletterCampaignCreateParams, bv as V2NewsletterCampaignStatus, bI as V2NewsletterCampaignUpdateParams, bF as V2NewsletterImportRequest, bG as V2NewsletterImportResult, bu as V2NewsletterList, bA as V2NewsletterListCreateParams, bB as V2NewsletterListUpdateParams, bx as V2NewsletterSeries, bJ as V2NewsletterSeriesCreateParams, bK as V2NewsletterSeriesUpdateParams, by as V2NewsletterStatistics, bL as V2NewsletterStatisticsParams, bt as V2NewsletterSubscription, bE as V2NewsletterSubscriptionListMembershipUpdate, bM as V2NewsletterSubscriptionStatusUpdate, bC as V2NewsletterSyncInput, bD as V2NewsletterSyncResult, bz as V2NewsletterTrackingResponse, aR as V2Object, bb as V2Order, bf as V2OrderAddress, bh as V2OrderCreateParams, bm as V2OrderCreateResult, bj as V2OrderFulfillmentNotificationLineItem, bk as V2OrderFulfillmentNotificationParams, bl as V2OrderFulfillmentNotificationResult, bi as V2OrderFulfillmentUpdate, be as V2OrderLineItem, bd as V2OrderLineItemPriceData, bc as V2OrderListParams, bg as V2OrderTaxRequest, bQ as V2Organization, aW as V2PaginationParams, b0 as V2Product, b1 as V2ProductCreateParams, b3 as V2ProductListParams, b2 as V2ProductUpdateParams, bR as V2Site, bn as V2SiteUser, bq as V2SiteUserListParams, bp as V2SiteUserMeUpdateParams, bs as V2SiteUserProfile, bX as V2SiteUserSubscription, bo as V2SiteUserUpdateParams, br as V2SiteUserWithProfile, bZ as V2SubscriptionCancelParams, b_ as V2SubscriptionChangePlanParams, b$ as V2SubscriptionChargeParams, c0 as V2SubscriptionChargeResult, bY as V2SubscriptionPauseParams, bU as V2Webhook, bV as V2WebhookCreateParams, bT as V2WebhookEventType, bW as V2WebhookUpdateParams, cJ as WebhooksV2Client, az as createPerspectApiV2Client } from '../index-CmcHYKO8.mjs';
|
package/dist/v2/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { cI as ApiKeysV2Client, cx as BaseV2Client, cA as CategoriesV2Client, cB as CollectionsV2Client, cF as ContactsV2Client, cy as ContentV2Client, cL as CreditsV2Client, cN as EmailTemplatesV2Client, cM as EmailV2Client, cE as NewsletterV2Client, cC as OrdersV2Client, cG as OrganizationsV2Client, ay as PerspectApiV2Client, cw as PerspectApiV2Config, aA as PerspectV2Error, cz as ProductsV2Client, cD as SiteUsersV2Client, cH as SitesV2Client, cK as SubscriptionsV2Client, bS as V2ApiKey, c1 as V2CancelSubscriptionResult, b4 as V2Category, b5 as V2CategoryCreateParams, b6 as V2CategoryUpdateParams, b7 as V2Collection, b9 as V2CollectionCreateParams, b8 as V2CollectionItem, ba as V2CollectionUpdateParams, bP as V2ContactSubmission, aY as V2Content, aZ as V2ContentCreateParams, a$ as V2ContentListParams, a_ as V2ContentUpdateParams, c3 as V2CreditBalance, c2 as V2CreditTransaction, aT as V2Deleted, c8 as V2EmailSendParams, ce as V2EmailSendResult, c9 as V2EmailTemplate, cd as V2EmailTemplateCloneParams, cc as V2EmailTemplateCreateParams, cb as V2EmailTemplateListParams, c7 as V2EmailTemplateStatus, c6 as V2EmailTemplateType, ca as V2EmailTemplateType_Listing, aU as V2Error, aV as V2ErrorType, c4 as V2GrantCreditParams, c5 as V2GrantCreditResult, aS as V2List, aX as V2Media, bN as V2NewsletterBulkParams, bO as V2NewsletterBulkResult, bw as V2NewsletterCampaign, bH as V2NewsletterCampaignCreateParams, bv as V2NewsletterCampaignStatus, bI as V2NewsletterCampaignUpdateParams, bF as V2NewsletterImportRequest, bG as V2NewsletterImportResult, bu as V2NewsletterList, bA as V2NewsletterListCreateParams, bB as V2NewsletterListUpdateParams, bx as V2NewsletterSeries, bJ as V2NewsletterSeriesCreateParams, bK as V2NewsletterSeriesUpdateParams, by as V2NewsletterStatistics, bL as V2NewsletterStatisticsParams, bt as V2NewsletterSubscription, bE as V2NewsletterSubscriptionListMembershipUpdate, bM as V2NewsletterSubscriptionStatusUpdate, bC as V2NewsletterSyncInput, bD as V2NewsletterSyncResult, bz as V2NewsletterTrackingResponse, aR as V2Object, bb as V2Order, bf as V2OrderAddress, bh as V2OrderCreateParams, bm as V2OrderCreateResult, bj as V2OrderFulfillmentNotificationLineItem, bk as V2OrderFulfillmentNotificationParams, bl as V2OrderFulfillmentNotificationResult, bi as V2OrderFulfillmentUpdate, be as V2OrderLineItem, bd as V2OrderLineItemPriceData, bc as V2OrderListParams, bg as V2OrderTaxRequest, bQ as V2Organization, aW as V2PaginationParams, b0 as V2Product, b1 as V2ProductCreateParams, b3 as V2ProductListParams, b2 as V2ProductUpdateParams, bR as V2Site, bn as V2SiteUser, bq as V2SiteUserListParams, bp as V2SiteUserMeUpdateParams, bs as V2SiteUserProfile, bX as V2SiteUserSubscription, bo as V2SiteUserUpdateParams, br as V2SiteUserWithProfile, bZ as V2SubscriptionCancelParams, b_ as V2SubscriptionChangePlanParams, b$ as V2SubscriptionChargeParams, c0 as V2SubscriptionChargeResult, bY as V2SubscriptionPauseParams, bU as V2Webhook, bV as V2WebhookCreateParams, bT as V2WebhookEventType, bW as V2WebhookUpdateParams, cJ as WebhooksV2Client, az as createPerspectApiV2Client } from '../index-CmcHYKO8.js';
|
package/dist/v2/index.js
CHANGED
|
@@ -27,6 +27,7 @@ __export(v2_exports, {
|
|
|
27
27
|
ContactsV2Client: () => ContactsV2Client,
|
|
28
28
|
ContentV2Client: () => ContentV2Client,
|
|
29
29
|
CreditsV2Client: () => CreditsV2Client,
|
|
30
|
+
EmailTemplatesV2Client: () => EmailTemplatesV2Client,
|
|
30
31
|
EmailV2Client: () => EmailV2Client,
|
|
31
32
|
NewsletterV2Client: () => NewsletterV2Client,
|
|
32
33
|
OrdersV2Client: () => OrdersV2Client,
|
|
@@ -140,6 +141,8 @@ var HttpClient = class {
|
|
|
140
141
|
}
|
|
141
142
|
this.dbg(`[HTTP Client] Headers:`, JSON.stringify(safeHeaders, null, 2));
|
|
142
143
|
let lastError;
|
|
144
|
+
const method = (options.method || "GET").toUpperCase();
|
|
145
|
+
const isIdempotent = method === "GET" || method === "HEAD";
|
|
143
146
|
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
144
147
|
try {
|
|
145
148
|
const response = await this.fetchWithTimeout(url, requestOptions);
|
|
@@ -149,6 +152,9 @@ var HttpClient = class {
|
|
|
149
152
|
if (error && typeof error === "object" && "status" in error && typeof error.status === "number" && error.status < 500) {
|
|
150
153
|
throw error;
|
|
151
154
|
}
|
|
155
|
+
if (!isIdempotent) {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
152
158
|
if (attempt === this.retries) {
|
|
153
159
|
break;
|
|
154
160
|
}
|
|
@@ -1293,6 +1299,97 @@ var NewsletterV2Client = class extends BaseV2Client {
|
|
|
1293
1299
|
data
|
|
1294
1300
|
);
|
|
1295
1301
|
}
|
|
1302
|
+
// --- Lists (get by id) ---
|
|
1303
|
+
async getListById(siteName, id, cachePolicy) {
|
|
1304
|
+
return this.getOne(
|
|
1305
|
+
this.sitePath(siteName, "newsletter", `lists/${encodeURIComponent(id)}`),
|
|
1306
|
+
void 0,
|
|
1307
|
+
cachePolicy
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
// --- Subscriptions (admin: lookup / status / delete / bulk) ---
|
|
1311
|
+
async getSubscriptionByEmail(siteName, email, cachePolicy) {
|
|
1312
|
+
return this.getOne(
|
|
1313
|
+
this.sitePath(siteName, "newsletter", "subscriptions/by-email"),
|
|
1314
|
+
{ email },
|
|
1315
|
+
cachePolicy
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
async updateSubscriptionStatus(siteName, id, data) {
|
|
1319
|
+
return this.post(
|
|
1320
|
+
this.sitePath(siteName, "newsletter", `subscriptions/${encodeURIComponent(id)}/status`),
|
|
1321
|
+
data
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
async deleteSubscription(siteName, id) {
|
|
1325
|
+
return this.deleteOne(
|
|
1326
|
+
this.sitePath(siteName, "newsletter", `subscriptions/${encodeURIComponent(id)}`)
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
async bulkUpdateSubscriptions(siteName, data) {
|
|
1330
|
+
return this.post(
|
|
1331
|
+
this.sitePath(siteName, "newsletter", "subscriptions/bulk"),
|
|
1332
|
+
data
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
// --- Statistics ---
|
|
1336
|
+
async getStatistics(siteName, params, cachePolicy) {
|
|
1337
|
+
return this.getOne(
|
|
1338
|
+
this.sitePath(siteName, "newsletter", "statistics"),
|
|
1339
|
+
params,
|
|
1340
|
+
cachePolicy
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
// --- Campaigns (create / update / delete) ---
|
|
1344
|
+
async createCampaign(siteName, data) {
|
|
1345
|
+
return this.post(
|
|
1346
|
+
this.sitePath(siteName, "newsletter", "campaigns"),
|
|
1347
|
+
data
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1350
|
+
async updateCampaign(siteName, id, data) {
|
|
1351
|
+
return this.patchOne(
|
|
1352
|
+
this.sitePath(siteName, "newsletter", `campaigns/${encodeURIComponent(id)}`),
|
|
1353
|
+
data
|
|
1354
|
+
);
|
|
1355
|
+
}
|
|
1356
|
+
async deleteCampaign(siteName, id) {
|
|
1357
|
+
return this.deleteOne(
|
|
1358
|
+
this.sitePath(siteName, "newsletter", `campaigns/${encodeURIComponent(id)}`)
|
|
1359
|
+
);
|
|
1360
|
+
}
|
|
1361
|
+
// --- Series ---
|
|
1362
|
+
async listSeries(siteName, params, cachePolicy) {
|
|
1363
|
+
return this.getList(
|
|
1364
|
+
this.sitePath(siteName, "newsletter", "series"),
|
|
1365
|
+
params,
|
|
1366
|
+
cachePolicy
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
async getSeries(siteName, id, cachePolicy) {
|
|
1370
|
+
return this.getOne(
|
|
1371
|
+
this.sitePath(siteName, "newsletter", `series/${encodeURIComponent(id)}`),
|
|
1372
|
+
void 0,
|
|
1373
|
+
cachePolicy
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
async createSeries(siteName, data) {
|
|
1377
|
+
return this.post(
|
|
1378
|
+
this.sitePath(siteName, "newsletter", "series"),
|
|
1379
|
+
data
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
async updateSeries(siteName, id, data) {
|
|
1383
|
+
return this.patchOne(
|
|
1384
|
+
this.sitePath(siteName, "newsletter", `series/${encodeURIComponent(id)}`),
|
|
1385
|
+
data
|
|
1386
|
+
);
|
|
1387
|
+
}
|
|
1388
|
+
async deleteSeries(siteName, id) {
|
|
1389
|
+
return this.deleteOne(
|
|
1390
|
+
this.sitePath(siteName, "newsletter", `series/${encodeURIComponent(id)}`)
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1296
1393
|
};
|
|
1297
1394
|
|
|
1298
1395
|
// src/v2/client/contacts-client.ts
|
|
@@ -1481,11 +1578,18 @@ var CreditsV2Client = class extends BaseV2Client {
|
|
|
1481
1578
|
// src/v2/client/email-client.ts
|
|
1482
1579
|
var EmailV2Client = class extends BaseV2Client {
|
|
1483
1580
|
/**
|
|
1484
|
-
* Send a transactional email
|
|
1581
|
+
* Send a transactional email through the site's email provider.
|
|
1582
|
+
*
|
|
1583
|
+
* Requires a server-side API key — never call this from a browser. Sites
|
|
1584
|
+
* without a configured provider fall back to the platform default with
|
|
1585
|
+
* policy restrictions (owner-only recipients, daily quota).
|
|
1485
1586
|
*
|
|
1486
|
-
*
|
|
1487
|
-
*
|
|
1488
|
-
*
|
|
1587
|
+
* Provide content one of two ways (mutually exclusive):
|
|
1588
|
+
* - Raw: `subject` plus at least one of `html` / `text`.
|
|
1589
|
+
* - Template: `template_type` (published template for that type) or
|
|
1590
|
+
* `template_id` (published template by ID) plus optional `variables`; the
|
|
1591
|
+
* template is rendered server-side. `subject` is optional here and
|
|
1592
|
+
* overrides the rendered one.
|
|
1489
1593
|
*/
|
|
1490
1594
|
async send(siteName, params) {
|
|
1491
1595
|
return this.post(
|
|
@@ -1495,6 +1599,66 @@ var EmailV2Client = class extends BaseV2Client {
|
|
|
1495
1599
|
}
|
|
1496
1600
|
};
|
|
1497
1601
|
|
|
1602
|
+
// src/v2/client/email-templates-client.ts
|
|
1603
|
+
var EmailTemplatesV2Client = class extends BaseV2Client {
|
|
1604
|
+
path(siteName, suffix = "") {
|
|
1605
|
+
return this.sitePath(siteName, "email", suffix ? `templates/${suffix}` : "templates");
|
|
1606
|
+
}
|
|
1607
|
+
/** List every supported template type with its allowed variables. */
|
|
1608
|
+
async listTypes(siteName, cachePolicy) {
|
|
1609
|
+
return this.getList(
|
|
1610
|
+
this.path(siteName, "types"),
|
|
1611
|
+
void 0,
|
|
1612
|
+
cachePolicy
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
/** Get the allowed variables for a single template type. */
|
|
1616
|
+
async getTypeVariables(siteName, templateType, cachePolicy) {
|
|
1617
|
+
return this.getOne(
|
|
1618
|
+
this.path(siteName, `types/${templateType}`),
|
|
1619
|
+
void 0,
|
|
1620
|
+
cachePolicy
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
/** List template versions, optionally filtered by type and/or status. */
|
|
1624
|
+
async list(siteName, params, cachePolicy) {
|
|
1625
|
+
return this.getList(this.path(siteName), params, cachePolicy);
|
|
1626
|
+
}
|
|
1627
|
+
/** Get a specific template version by ID (`etpl_…`). */
|
|
1628
|
+
async get(siteName, templateId, cachePolicy) {
|
|
1629
|
+
return this.getOne(
|
|
1630
|
+
this.path(siteName, encodeURIComponent(templateId)),
|
|
1631
|
+
void 0,
|
|
1632
|
+
cachePolicy
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
/** Get the currently published version for a template type. */
|
|
1636
|
+
async getPublished(siteName, templateType, cachePolicy) {
|
|
1637
|
+
return this.getOne(
|
|
1638
|
+
this.path(siteName, `published/${templateType}`),
|
|
1639
|
+
void 0,
|
|
1640
|
+
cachePolicy
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1643
|
+
/** Create a new template version. */
|
|
1644
|
+
async create(siteName, params) {
|
|
1645
|
+
return this.post(this.path(siteName), params);
|
|
1646
|
+
}
|
|
1647
|
+
/** Clone a template version, optionally overriding fields. */
|
|
1648
|
+
async clone(siteName, templateId, params) {
|
|
1649
|
+
return this.post(
|
|
1650
|
+
this.path(siteName, `${encodeURIComponent(templateId)}/clone`),
|
|
1651
|
+
params ?? {}
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
/** Publish a template version (archives the previously published one). */
|
|
1655
|
+
async publish(siteName, templateId) {
|
|
1656
|
+
return this.post(
|
|
1657
|
+
this.path(siteName, `${encodeURIComponent(templateId)}/publish`)
|
|
1658
|
+
);
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1498
1662
|
// src/v2/index.ts
|
|
1499
1663
|
var PerspectApiV2Client = class {
|
|
1500
1664
|
http;
|
|
@@ -1514,6 +1678,7 @@ var PerspectApiV2Client = class {
|
|
|
1514
1678
|
subscriptions;
|
|
1515
1679
|
credits;
|
|
1516
1680
|
email;
|
|
1681
|
+
emailTemplates;
|
|
1517
1682
|
constructor(config) {
|
|
1518
1683
|
const baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
1519
1684
|
const v2BaseUrl = baseUrl.endsWith("/api/v2") ? baseUrl : `${baseUrl}/api/v2`;
|
|
@@ -1536,6 +1701,7 @@ var PerspectApiV2Client = class {
|
|
|
1536
1701
|
this.subscriptions = new SubscriptionsV2Client(this.http, basePath, cache);
|
|
1537
1702
|
this.credits = new CreditsV2Client(this.http, basePath, cache);
|
|
1538
1703
|
this.email = new EmailV2Client(this.http, basePath, cache);
|
|
1704
|
+
this.emailTemplates = new EmailTemplatesV2Client(this.http, basePath, cache);
|
|
1539
1705
|
}
|
|
1540
1706
|
/** Update the JWT token for authenticated requests. */
|
|
1541
1707
|
setAuth(jwt) {
|
|
@@ -1562,6 +1728,7 @@ function createPerspectApiV2Client(config) {
|
|
|
1562
1728
|
ContactsV2Client,
|
|
1563
1729
|
ContentV2Client,
|
|
1564
1730
|
CreditsV2Client,
|
|
1731
|
+
EmailTemplatesV2Client,
|
|
1565
1732
|
EmailV2Client,
|
|
1566
1733
|
NewsletterV2Client,
|
|
1567
1734
|
OrdersV2Client,
|
package/dist/v2/index.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ContactsV2Client,
|
|
7
7
|
ContentV2Client,
|
|
8
8
|
CreditsV2Client,
|
|
9
|
+
EmailTemplatesV2Client,
|
|
9
10
|
EmailV2Client,
|
|
10
11
|
NewsletterV2Client,
|
|
11
12
|
OrdersV2Client,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
SubscriptionsV2Client,
|
|
19
20
|
WebhooksV2Client,
|
|
20
21
|
createPerspectApiV2Client
|
|
21
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-PWZSSX4V.mjs";
|
|
22
23
|
export {
|
|
23
24
|
ApiKeysV2Client,
|
|
24
25
|
BaseV2Client,
|
|
@@ -27,6 +28,7 @@ export {
|
|
|
27
28
|
ContactsV2Client,
|
|
28
29
|
ContentV2Client,
|
|
29
30
|
CreditsV2Client,
|
|
31
|
+
EmailTemplatesV2Client,
|
|
30
32
|
EmailV2Client,
|
|
31
33
|
NewsletterV2Client,
|
|
32
34
|
OrdersV2Client,
|
package/package.json
CHANGED
package/src/utils/http-client.ts
CHANGED
|
@@ -115,25 +115,37 @@ export class HttpClient {
|
|
|
115
115
|
this.dbg(`[HTTP Client] Headers:`, JSON.stringify(safeHeaders, null, 2));
|
|
116
116
|
|
|
117
117
|
let lastError: Error;
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
// Only retry idempotent methods. Retrying POST/PATCH/PUT/DELETE on a
|
|
120
|
+
// timeout or 5xx can duplicate a side effect the server already applied
|
|
121
|
+
// (e.g. send the same transactional email twice, create two campaigns).
|
|
122
|
+
const method = (options.method || 'GET').toUpperCase();
|
|
123
|
+
const isIdempotent = method === 'GET' || method === 'HEAD';
|
|
124
|
+
|
|
119
125
|
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
120
126
|
try {
|
|
121
127
|
const response = await this.fetchWithTimeout(url, requestOptions);
|
|
122
128
|
return await this.handleResponse<T>(response);
|
|
123
129
|
} catch (error) {
|
|
124
130
|
lastError = error as Error;
|
|
125
|
-
|
|
131
|
+
|
|
126
132
|
// Don't retry on client errors (4xx)
|
|
127
|
-
if (error && typeof error === 'object' && 'status' in error &&
|
|
133
|
+
if (error && typeof error === 'object' && 'status' in error &&
|
|
128
134
|
typeof (error as any).status === 'number' && (error as any).status < 500) {
|
|
129
135
|
throw error;
|
|
130
136
|
}
|
|
131
|
-
|
|
137
|
+
|
|
138
|
+
// Don't retry non-idempotent methods — the request may have been
|
|
139
|
+
// applied server-side even though we saw a timeout/5xx.
|
|
140
|
+
if (!isIdempotent) {
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
|
|
132
144
|
// Don't retry on last attempt
|
|
133
145
|
if (attempt === this.retries) {
|
|
134
146
|
break;
|
|
135
147
|
}
|
|
136
|
-
|
|
148
|
+
|
|
137
149
|
// Exponential backoff
|
|
138
150
|
await this.delay(Math.pow(2, attempt) * 1000);
|
|
139
151
|
}
|
|
@@ -8,11 +8,18 @@ import type { V2EmailSendParams, V2EmailSendResult } from '../types';
|
|
|
8
8
|
export class EmailV2Client extends BaseV2Client {
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Send a transactional email
|
|
11
|
+
* Send a transactional email through the site's email provider.
|
|
12
12
|
*
|
|
13
|
-
* Requires a server-side API key — never call this from a browser.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Requires a server-side API key — never call this from a browser. Sites
|
|
14
|
+
* without a configured provider fall back to the platform default with
|
|
15
|
+
* policy restrictions (owner-only recipients, daily quota).
|
|
16
|
+
*
|
|
17
|
+
* Provide content one of two ways (mutually exclusive):
|
|
18
|
+
* - Raw: `subject` plus at least one of `html` / `text`.
|
|
19
|
+
* - Template: `template_type` (published template for that type) or
|
|
20
|
+
* `template_id` (published template by ID) plus optional `variables`; the
|
|
21
|
+
* template is rendered server-side. `subject` is optional here and
|
|
22
|
+
* overrides the rendered one.
|
|
16
23
|
*/
|
|
17
24
|
async send(siteName: string, params: V2EmailSendParams): Promise<V2EmailSendResult> {
|
|
18
25
|
return this.post<V2EmailSendResult>(
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2 Email Templates Client — versioned CRUD for site email templates.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the email_template_* MCP tools. Templates live under
|
|
5
|
+
* /sites/:siteName/email/templates. Use `listTypes` / `getTypeVariables` to
|
|
6
|
+
* discover the allowed substitution variables for each template type before
|
|
7
|
+
* authoring, then create/clone/publish versions.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { BaseV2Client } from './base-v2-client';
|
|
11
|
+
import type { CachePolicy } from '../../cache/types';
|
|
12
|
+
import type {
|
|
13
|
+
V2EmailTemplate,
|
|
14
|
+
V2EmailTemplateType,
|
|
15
|
+
V2EmailTemplateType_Listing,
|
|
16
|
+
V2EmailTemplateListParams,
|
|
17
|
+
V2EmailTemplateCreateParams,
|
|
18
|
+
V2EmailTemplateCloneParams,
|
|
19
|
+
V2List,
|
|
20
|
+
} from '../types';
|
|
21
|
+
|
|
22
|
+
export class EmailTemplatesV2Client extends BaseV2Client {
|
|
23
|
+
private path(siteName: string, suffix = ''): string {
|
|
24
|
+
return this.sitePath(siteName, 'email', suffix ? `templates/${suffix}` : 'templates');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** List every supported template type with its allowed variables. */
|
|
28
|
+
async listTypes(
|
|
29
|
+
siteName: string,
|
|
30
|
+
cachePolicy?: CachePolicy,
|
|
31
|
+
): Promise<V2List<V2EmailTemplateType_Listing>> {
|
|
32
|
+
return this.getList<V2EmailTemplateType_Listing>(
|
|
33
|
+
this.path(siteName, 'types'),
|
|
34
|
+
undefined,
|
|
35
|
+
cachePolicy,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Get the allowed variables for a single template type. */
|
|
40
|
+
async getTypeVariables(
|
|
41
|
+
siteName: string,
|
|
42
|
+
templateType: V2EmailTemplateType,
|
|
43
|
+
cachePolicy?: CachePolicy,
|
|
44
|
+
): Promise<V2EmailTemplateType_Listing> {
|
|
45
|
+
return this.getOne<V2EmailTemplateType_Listing>(
|
|
46
|
+
this.path(siteName, `types/${templateType}`),
|
|
47
|
+
undefined,
|
|
48
|
+
cachePolicy,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** List template versions, optionally filtered by type and/or status. */
|
|
53
|
+
async list(
|
|
54
|
+
siteName: string,
|
|
55
|
+
params?: V2EmailTemplateListParams,
|
|
56
|
+
cachePolicy?: CachePolicy,
|
|
57
|
+
): Promise<V2List<V2EmailTemplate>> {
|
|
58
|
+
return this.getList<V2EmailTemplate>(this.path(siteName), params, cachePolicy);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Get a specific template version by ID (`etpl_…`). */
|
|
62
|
+
async get(
|
|
63
|
+
siteName: string,
|
|
64
|
+
templateId: string,
|
|
65
|
+
cachePolicy?: CachePolicy,
|
|
66
|
+
): Promise<V2EmailTemplate> {
|
|
67
|
+
return this.getOne<V2EmailTemplate>(
|
|
68
|
+
this.path(siteName, encodeURIComponent(templateId)),
|
|
69
|
+
undefined,
|
|
70
|
+
cachePolicy,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Get the currently published version for a template type. */
|
|
75
|
+
async getPublished(
|
|
76
|
+
siteName: string,
|
|
77
|
+
templateType: V2EmailTemplateType,
|
|
78
|
+
cachePolicy?: CachePolicy,
|
|
79
|
+
): Promise<V2EmailTemplate> {
|
|
80
|
+
return this.getOne<V2EmailTemplate>(
|
|
81
|
+
this.path(siteName, `published/${templateType}`),
|
|
82
|
+
undefined,
|
|
83
|
+
cachePolicy,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Create a new template version. */
|
|
88
|
+
async create(
|
|
89
|
+
siteName: string,
|
|
90
|
+
params: V2EmailTemplateCreateParams,
|
|
91
|
+
): Promise<V2EmailTemplate> {
|
|
92
|
+
return this.post<V2EmailTemplate>(this.path(siteName), params);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Clone a template version, optionally overriding fields. */
|
|
96
|
+
async clone(
|
|
97
|
+
siteName: string,
|
|
98
|
+
templateId: string,
|
|
99
|
+
params?: V2EmailTemplateCloneParams,
|
|
100
|
+
): Promise<V2EmailTemplate> {
|
|
101
|
+
return this.post<V2EmailTemplate>(
|
|
102
|
+
this.path(siteName, `${encodeURIComponent(templateId)}/clone`),
|
|
103
|
+
params ?? {},
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Publish a template version (archives the previously published one). */
|
|
108
|
+
async publish(siteName: string, templateId: string): Promise<V2EmailTemplate> {
|
|
109
|
+
return this.post<V2EmailTemplate>(
|
|
110
|
+
this.path(siteName, `${encodeURIComponent(templateId)}/publish`),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -6,11 +6,16 @@ import { BaseV2Client } from './base-v2-client';
|
|
|
6
6
|
import type { CachePolicy } from '../../cache/types';
|
|
7
7
|
import type {
|
|
8
8
|
V2NewsletterSubscription, V2NewsletterList, V2NewsletterCampaign,
|
|
9
|
+
V2NewsletterSeries, V2NewsletterStatistics,
|
|
9
10
|
V2PaginationParams, V2List, V2Deleted, V2NewsletterTrackingResponse,
|
|
10
11
|
V2NewsletterListCreateParams, V2NewsletterListUpdateParams,
|
|
11
12
|
V2NewsletterSyncInput, V2NewsletterSyncResult,
|
|
12
13
|
V2NewsletterSubscriptionListMembershipUpdate,
|
|
13
14
|
V2NewsletterImportRequest, V2NewsletterImportResult,
|
|
15
|
+
V2NewsletterCampaignCreateParams, V2NewsletterCampaignUpdateParams,
|
|
16
|
+
V2NewsletterSeriesCreateParams, V2NewsletterSeriesUpdateParams,
|
|
17
|
+
V2NewsletterStatisticsParams, V2NewsletterSubscriptionStatusUpdate,
|
|
18
|
+
V2NewsletterBulkParams, V2NewsletterBulkResult,
|
|
14
19
|
} from '../types';
|
|
15
20
|
|
|
16
21
|
export class NewsletterV2Client extends BaseV2Client {
|
|
@@ -206,4 +211,155 @@ export class NewsletterV2Client extends BaseV2Client {
|
|
|
206
211
|
data,
|
|
207
212
|
);
|
|
208
213
|
}
|
|
214
|
+
|
|
215
|
+
// --- Lists (get by id) ---
|
|
216
|
+
|
|
217
|
+
async getListById(
|
|
218
|
+
siteName: string,
|
|
219
|
+
id: string,
|
|
220
|
+
cachePolicy?: CachePolicy,
|
|
221
|
+
): Promise<V2NewsletterList> {
|
|
222
|
+
return this.getOne<V2NewsletterList>(
|
|
223
|
+
this.sitePath(siteName, 'newsletter', `lists/${encodeURIComponent(id)}`),
|
|
224
|
+
undefined,
|
|
225
|
+
cachePolicy,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// --- Subscriptions (admin: lookup / status / delete / bulk) ---
|
|
230
|
+
|
|
231
|
+
async getSubscriptionByEmail(
|
|
232
|
+
siteName: string,
|
|
233
|
+
email: string,
|
|
234
|
+
cachePolicy?: CachePolicy,
|
|
235
|
+
): Promise<V2NewsletterSubscription> {
|
|
236
|
+
return this.getOne<V2NewsletterSubscription>(
|
|
237
|
+
this.sitePath(siteName, 'newsletter', 'subscriptions/by-email'),
|
|
238
|
+
{ email },
|
|
239
|
+
cachePolicy,
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async updateSubscriptionStatus(
|
|
244
|
+
siteName: string,
|
|
245
|
+
id: string,
|
|
246
|
+
data: V2NewsletterSubscriptionStatusUpdate,
|
|
247
|
+
): Promise<V2NewsletterSubscription> {
|
|
248
|
+
return this.post<V2NewsletterSubscription>(
|
|
249
|
+
this.sitePath(siteName, 'newsletter', `subscriptions/${encodeURIComponent(id)}/status`),
|
|
250
|
+
data,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async deleteSubscription(siteName: string, id: string): Promise<V2Deleted> {
|
|
255
|
+
return this.deleteOne(
|
|
256
|
+
this.sitePath(siteName, 'newsletter', `subscriptions/${encodeURIComponent(id)}`),
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async bulkUpdateSubscriptions(
|
|
261
|
+
siteName: string,
|
|
262
|
+
data: V2NewsletterBulkParams,
|
|
263
|
+
): Promise<V2NewsletterBulkResult> {
|
|
264
|
+
return this.post<V2NewsletterBulkResult>(
|
|
265
|
+
this.sitePath(siteName, 'newsletter', 'subscriptions/bulk'),
|
|
266
|
+
data,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// --- Statistics ---
|
|
271
|
+
|
|
272
|
+
async getStatistics(
|
|
273
|
+
siteName: string,
|
|
274
|
+
params?: V2NewsletterStatisticsParams,
|
|
275
|
+
cachePolicy?: CachePolicy,
|
|
276
|
+
): Promise<V2NewsletterStatistics> {
|
|
277
|
+
return this.getOne<V2NewsletterStatistics>(
|
|
278
|
+
this.sitePath(siteName, 'newsletter', 'statistics'),
|
|
279
|
+
params,
|
|
280
|
+
cachePolicy,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// --- Campaigns (create / update / delete) ---
|
|
285
|
+
|
|
286
|
+
async createCampaign(
|
|
287
|
+
siteName: string,
|
|
288
|
+
data: V2NewsletterCampaignCreateParams,
|
|
289
|
+
): Promise<V2NewsletterCampaign> {
|
|
290
|
+
return this.post<V2NewsletterCampaign>(
|
|
291
|
+
this.sitePath(siteName, 'newsletter', 'campaigns'),
|
|
292
|
+
data,
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async updateCampaign(
|
|
297
|
+
siteName: string,
|
|
298
|
+
id: string,
|
|
299
|
+
data: V2NewsletterCampaignUpdateParams,
|
|
300
|
+
): Promise<V2NewsletterCampaign> {
|
|
301
|
+
return this.patchOne<V2NewsletterCampaign>(
|
|
302
|
+
this.sitePath(siteName, 'newsletter', `campaigns/${encodeURIComponent(id)}`),
|
|
303
|
+
data,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async deleteCampaign(siteName: string, id: string): Promise<V2Deleted> {
|
|
308
|
+
return this.deleteOne(
|
|
309
|
+
this.sitePath(siteName, 'newsletter', `campaigns/${encodeURIComponent(id)}`),
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// --- Series ---
|
|
314
|
+
|
|
315
|
+
async listSeries(
|
|
316
|
+
siteName: string,
|
|
317
|
+
params?: { status?: 'active' | 'paused' | 'archived' },
|
|
318
|
+
cachePolicy?: CachePolicy,
|
|
319
|
+
): Promise<V2List<V2NewsletterSeries>> {
|
|
320
|
+
return this.getList<V2NewsletterSeries>(
|
|
321
|
+
this.sitePath(siteName, 'newsletter', 'series'),
|
|
322
|
+
params,
|
|
323
|
+
cachePolicy,
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async getSeries(
|
|
328
|
+
siteName: string,
|
|
329
|
+
id: string,
|
|
330
|
+
cachePolicy?: CachePolicy,
|
|
331
|
+
): Promise<V2NewsletterSeries> {
|
|
332
|
+
return this.getOne<V2NewsletterSeries>(
|
|
333
|
+
this.sitePath(siteName, 'newsletter', `series/${encodeURIComponent(id)}`),
|
|
334
|
+
undefined,
|
|
335
|
+
cachePolicy,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async createSeries(
|
|
340
|
+
siteName: string,
|
|
341
|
+
data: V2NewsletterSeriesCreateParams,
|
|
342
|
+
): Promise<V2NewsletterSeries> {
|
|
343
|
+
return this.post<V2NewsletterSeries>(
|
|
344
|
+
this.sitePath(siteName, 'newsletter', 'series'),
|
|
345
|
+
data,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
async updateSeries(
|
|
350
|
+
siteName: string,
|
|
351
|
+
id: string,
|
|
352
|
+
data: V2NewsletterSeriesUpdateParams,
|
|
353
|
+
): Promise<V2NewsletterSeries> {
|
|
354
|
+
return this.patchOne<V2NewsletterSeries>(
|
|
355
|
+
this.sitePath(siteName, 'newsletter', `series/${encodeURIComponent(id)}`),
|
|
356
|
+
data,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async deleteSeries(siteName: string, id: string): Promise<V2Deleted> {
|
|
361
|
+
return this.deleteOne(
|
|
362
|
+
this.sitePath(siteName, 'newsletter', `series/${encodeURIComponent(id)}`),
|
|
363
|
+
);
|
|
364
|
+
}
|
|
209
365
|
}
|