perspectapi-ts-sdk 3.7.0 → 5.0.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 +60 -59
- package/dist/index.d.mts +1036 -155
- package/dist/index.d.ts +1036 -155
- package/dist/index.js +626 -111
- package/dist/index.mjs +622 -111
- package/package.json +1 -1
- package/src/client/newsletter-client.ts +0 -242
- package/src/client/newsletter-management-client.ts +426 -0
- package/src/client/site-users-client.ts +15 -9
- package/src/index.ts +30 -1
- package/src/perspect-api-client.ts +3 -0
- package/src/types/index.ts +287 -1
- package/src/v2/client/api-keys-client.ts +21 -0
- package/src/v2/client/base-v2-client.ts +146 -0
- package/src/v2/client/categories-client.ts +32 -0
- package/src/v2/client/collections-client.ts +64 -0
- package/src/v2/client/contacts-client.ts +37 -0
- package/src/v2/client/content-client.ts +44 -0
- package/src/v2/client/newsletter-client.ts +95 -0
- package/src/v2/client/orders-client.ts +21 -0
- package/src/v2/client/organizations-client.ts +17 -0
- package/src/v2/client/products-client.ts +36 -0
- package/src/v2/client/site-users-client.ts +53 -0
- package/src/v2/client/sites-client.ts +17 -0
- package/src/v2/client/webhooks-client.ts +32 -0
- package/src/v2/index.ts +105 -0
- package/src/v2/types.ts +395 -0
|
@@ -18,6 +18,8 @@ import type {
|
|
|
18
18
|
VerifyOtpResponse,
|
|
19
19
|
UpdateSiteUserRequest,
|
|
20
20
|
SetProfileValueRequest,
|
|
21
|
+
CancelSubscriptionRequest,
|
|
22
|
+
CancelSubscriptionResponse,
|
|
21
23
|
ApiResponse,
|
|
22
24
|
} from '../types';
|
|
23
25
|
|
|
@@ -276,19 +278,21 @@ export class SiteUsersClient extends BaseClient {
|
|
|
276
278
|
}
|
|
277
279
|
|
|
278
280
|
/**
|
|
279
|
-
* Cancel a subscription
|
|
281
|
+
* Cancel a subscription.
|
|
280
282
|
* @param siteName - The site name
|
|
281
283
|
* @param id - Subscription ID
|
|
282
284
|
* @param csrfToken - CSRF token (required)
|
|
285
|
+
* @param options - Cancellation mode/details
|
|
283
286
|
*/
|
|
284
287
|
async cancelSubscription(
|
|
285
288
|
siteName: string,
|
|
286
289
|
id: string,
|
|
287
|
-
csrfToken?: string
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
csrfToken?: string,
|
|
291
|
+
options?: CancelSubscriptionRequest
|
|
292
|
+
): Promise<ApiResponse<CancelSubscriptionResponse>> {
|
|
293
|
+
return this.create<CancelSubscriptionRequest, CancelSubscriptionResponse>(
|
|
290
294
|
this.siteUserEndpoint(siteName, `/users/me/subscriptions/${encodeURIComponent(id)}/cancel`),
|
|
291
|
-
{},
|
|
295
|
+
options ?? {},
|
|
292
296
|
csrfToken
|
|
293
297
|
);
|
|
294
298
|
}
|
|
@@ -596,15 +600,17 @@ export class SiteUsersClient extends BaseClient {
|
|
|
596
600
|
* @param siteName - The site name
|
|
597
601
|
* @param userId - User ID
|
|
598
602
|
* @param subscriptionId - Subscription ID
|
|
603
|
+
* @param options - Cancellation mode/details
|
|
599
604
|
*/
|
|
600
605
|
async cancelUserSubscription(
|
|
601
606
|
siteName: string,
|
|
602
607
|
userId: string,
|
|
603
|
-
subscriptionId: string
|
|
604
|
-
|
|
605
|
-
|
|
608
|
+
subscriptionId: string,
|
|
609
|
+
options?: CancelSubscriptionRequest
|
|
610
|
+
): Promise<ApiResponse<CancelSubscriptionResponse>> {
|
|
611
|
+
return this.create<CancelSubscriptionRequest, CancelSubscriptionResponse>(
|
|
606
612
|
this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/cancel`),
|
|
607
|
-
{}
|
|
613
|
+
options ?? {}
|
|
608
614
|
);
|
|
609
615
|
}
|
|
610
616
|
|
package/src/index.ts
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
* Cloudflare Workers compatible SDK for PerspectAPI
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
// Main client
|
|
6
|
+
// Main client (v1)
|
|
7
7
|
export { PerspectApiClient, createPerspectApiClient } from './perspect-api-client';
|
|
8
8
|
export { default } from './perspect-api-client';
|
|
9
9
|
|
|
10
|
+
// v2 client
|
|
11
|
+
export { PerspectApiV2Client, createPerspectApiV2Client } from './v2';
|
|
12
|
+
export { PerspectV2Error } from './v2/client/base-v2-client';
|
|
13
|
+
|
|
10
14
|
// Individual clients (for advanced usage)
|
|
11
15
|
export { AuthClient } from './client/auth-client';
|
|
12
16
|
export { ContentClient } from './client/content-client';
|
|
@@ -19,6 +23,7 @@ export { WebhooksClient } from './client/webhooks-client';
|
|
|
19
23
|
export { CheckoutClient } from './client/checkout-client';
|
|
20
24
|
export { ContactClient } from './client/contact-client';
|
|
21
25
|
export { NewsletterClient } from './client/newsletter-client';
|
|
26
|
+
export { NewsletterManagementClient } from './client/newsletter-management-client';
|
|
22
27
|
export { SiteUsersClient } from './client/site-users-client';
|
|
23
28
|
export { BundlesClient } from './client/bundles-client';
|
|
24
29
|
|
|
@@ -109,6 +114,30 @@ export type {
|
|
|
109
114
|
NewsletterConfirmResponse,
|
|
110
115
|
NewsletterUnsubscribeRequest,
|
|
111
116
|
NewsletterUnsubscribeResponse,
|
|
117
|
+
NewsletterManagementListMembership,
|
|
118
|
+
NewsletterManagementSubscription,
|
|
119
|
+
NewsletterSubscriptionSyncRequest,
|
|
120
|
+
NewsletterSubscriptionSyncResponse,
|
|
121
|
+
NewsletterSubscriptionsBulkAction,
|
|
122
|
+
NewsletterSubscriptionsBulkUpdateRequest,
|
|
123
|
+
NewsletterSubscriptionsBulkOutcome,
|
|
124
|
+
NewsletterSubscriptionsBulkUpdateResponse,
|
|
125
|
+
NewsletterSubscriptionMembershipUpdateRequest,
|
|
126
|
+
NewsletterSubscriptionImportRowRequest,
|
|
127
|
+
NewsletterSubscriptionsImportRequest,
|
|
128
|
+
NewsletterSubscriptionsImportRowResult,
|
|
129
|
+
NewsletterSubscriptionsImportResponse,
|
|
130
|
+
NewsletterManagementPagination,
|
|
131
|
+
NewsletterManagementSubscriptionsListResponse,
|
|
132
|
+
NewsletterManagementList,
|
|
133
|
+
NewsletterManagementSeries,
|
|
134
|
+
NewsletterManagementCampaign,
|
|
135
|
+
NewsletterManagementCampaignListResponse,
|
|
136
|
+
NewsletterCampaignTestSendRequest,
|
|
137
|
+
NewsletterCampaignTestSendResponse,
|
|
138
|
+
NewsletterManagementStatsResponse,
|
|
139
|
+
NewsletterExportCreateRequest,
|
|
140
|
+
NewsletterExportCreateResponse,
|
|
112
141
|
ContactSubmitResponse,
|
|
113
142
|
ContactStatusResponse,
|
|
114
143
|
SiteUser,
|
|
@@ -16,6 +16,7 @@ import { WebhooksClient } from './client/webhooks-client';
|
|
|
16
16
|
import { CheckoutClient } from './client/checkout-client';
|
|
17
17
|
import { ContactClient } from './client/contact-client';
|
|
18
18
|
import { NewsletterClient } from './client/newsletter-client';
|
|
19
|
+
import { NewsletterManagementClient } from './client/newsletter-management-client';
|
|
19
20
|
import { SiteUsersClient } from './client/site-users-client';
|
|
20
21
|
import { BundlesClient } from './client/bundles-client';
|
|
21
22
|
|
|
@@ -37,6 +38,7 @@ export class PerspectApiClient {
|
|
|
37
38
|
public readonly checkout: CheckoutClient;
|
|
38
39
|
public readonly contact: ContactClient;
|
|
39
40
|
public readonly newsletter: NewsletterClient;
|
|
41
|
+
public readonly newsletterManagement: NewsletterManagementClient;
|
|
40
42
|
public readonly siteUsers: SiteUsersClient;
|
|
41
43
|
public readonly bundles: BundlesClient;
|
|
42
44
|
|
|
@@ -62,6 +64,7 @@ export class PerspectApiClient {
|
|
|
62
64
|
this.checkout = new CheckoutClient(this.http, this.cache);
|
|
63
65
|
this.contact = new ContactClient(this.http, this.cache);
|
|
64
66
|
this.newsletter = new NewsletterClient(this.http, this.cache);
|
|
67
|
+
this.newsletterManagement = new NewsletterManagementClient(this.http, this.cache);
|
|
65
68
|
this.siteUsers = new SiteUsersClient(this.http, this.cache);
|
|
66
69
|
this.bundles = new BundlesClient(this.http, this.cache);
|
|
67
70
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -225,6 +225,269 @@ export interface NewsletterUnsubscribeResponse {
|
|
|
225
225
|
status?: string;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
// Newsletter Management
|
|
229
|
+
export interface NewsletterManagementListMembership {
|
|
230
|
+
id: string;
|
|
231
|
+
list_name: string;
|
|
232
|
+
slug: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface NewsletterManagementSubscription {
|
|
236
|
+
id: string;
|
|
237
|
+
site_id: string;
|
|
238
|
+
site_name: string;
|
|
239
|
+
email: string;
|
|
240
|
+
name?: string | null;
|
|
241
|
+
status: 'pending' | 'confirmed' | 'unsubscribed' | 'bounced' | 'complained';
|
|
242
|
+
confirmation_token?: string | null;
|
|
243
|
+
unsubscribe_token: string;
|
|
244
|
+
double_opt_in: boolean;
|
|
245
|
+
confirmed_at?: string | null;
|
|
246
|
+
source?: string | null;
|
|
247
|
+
source_url?: string | null;
|
|
248
|
+
frequency: 'instant' | 'daily' | 'weekly' | 'monthly';
|
|
249
|
+
topics?: string[] | string | null;
|
|
250
|
+
language: string;
|
|
251
|
+
tags?: string[] | string | null;
|
|
252
|
+
custom_fields?: Record<string, any> | string | null;
|
|
253
|
+
notes?: string | null;
|
|
254
|
+
unsubscribed_at?: string | null;
|
|
255
|
+
unsubscribe_reason?: string | null;
|
|
256
|
+
created_at: string;
|
|
257
|
+
updated_at: string;
|
|
258
|
+
lists: NewsletterManagementListMembership[];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface NewsletterSubscriptionSyncRequest {
|
|
262
|
+
email: string;
|
|
263
|
+
name?: string | null;
|
|
264
|
+
status?: 'pending' | 'confirmed' | 'unsubscribed' | 'bounced' | 'complained';
|
|
265
|
+
list_ids?: string[];
|
|
266
|
+
frequency?: 'instant' | 'daily' | 'weekly' | 'monthly';
|
|
267
|
+
topics?: string[];
|
|
268
|
+
language?: string | null;
|
|
269
|
+
source?: string | null;
|
|
270
|
+
source_url?: string | null;
|
|
271
|
+
notes?: string | null;
|
|
272
|
+
tags?: string[];
|
|
273
|
+
metadata?: Record<string, any>;
|
|
274
|
+
resubscribe_override?: boolean;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export interface NewsletterSubscriptionSyncResponse {
|
|
278
|
+
applied: boolean;
|
|
279
|
+
code: 'CREATED' | 'UPDATED' | 'RESUBSCRIBED' | 'ALREADY_UNSUBSCRIBED';
|
|
280
|
+
skipped_unsubscribed: boolean;
|
|
281
|
+
resubscribed: boolean;
|
|
282
|
+
created: boolean;
|
|
283
|
+
updated: boolean;
|
|
284
|
+
subscription_id: string;
|
|
285
|
+
subscription: NewsletterManagementSubscription;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export type NewsletterSubscriptionsBulkAction =
|
|
289
|
+
| 'confirm'
|
|
290
|
+
| 'unsubscribe'
|
|
291
|
+
| 'delete'
|
|
292
|
+
| 'add_to_list'
|
|
293
|
+
| 'remove_from_list';
|
|
294
|
+
|
|
295
|
+
export interface NewsletterSubscriptionsBulkUpdateRequest {
|
|
296
|
+
ids: string[];
|
|
297
|
+
action: NewsletterSubscriptionsBulkAction;
|
|
298
|
+
list_id?: string;
|
|
299
|
+
resubscribe_override?: boolean;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export interface NewsletterSubscriptionsBulkOutcome {
|
|
303
|
+
id: string;
|
|
304
|
+
applied: boolean;
|
|
305
|
+
code: string;
|
|
306
|
+
error?: string;
|
|
307
|
+
skipped_unsubscribed?: boolean;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface NewsletterSubscriptionsBulkUpdateResponse {
|
|
311
|
+
succeeded: number;
|
|
312
|
+
failed: number;
|
|
313
|
+
skipped_unsubscribed: number;
|
|
314
|
+
outcomes: NewsletterSubscriptionsBulkOutcome[];
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export interface NewsletterSubscriptionMembershipUpdateRequest {
|
|
318
|
+
mode: 'add' | 'remove' | 'replace';
|
|
319
|
+
list_ids: string[];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export interface NewsletterSubscriptionImportRowRequest {
|
|
323
|
+
email: string;
|
|
324
|
+
name?: string | null;
|
|
325
|
+
status?: 'pending' | 'confirmed' | 'unsubscribed' | 'bounced' | 'complained';
|
|
326
|
+
list_ids?: string[];
|
|
327
|
+
frequency?: 'instant' | 'daily' | 'weekly' | 'monthly';
|
|
328
|
+
topics?: string[];
|
|
329
|
+
language?: string | null;
|
|
330
|
+
source?: string | null;
|
|
331
|
+
source_url?: string | null;
|
|
332
|
+
notes?: string | null;
|
|
333
|
+
tags?: string[];
|
|
334
|
+
metadata?: Record<string, any>;
|
|
335
|
+
resubscribe_override?: boolean;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export interface NewsletterSubscriptionsImportRequest {
|
|
339
|
+
rows: NewsletterSubscriptionImportRowRequest[];
|
|
340
|
+
resubscribe_override?: boolean;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export interface NewsletterSubscriptionsImportRowResult {
|
|
344
|
+
index: number;
|
|
345
|
+
email: string;
|
|
346
|
+
applied: boolean;
|
|
347
|
+
code: string;
|
|
348
|
+
skipped_unsubscribed: boolean;
|
|
349
|
+
resubscribed: boolean;
|
|
350
|
+
subscription_id: string;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export interface NewsletterSubscriptionsImportResponse {
|
|
354
|
+
total: number;
|
|
355
|
+
processed: number;
|
|
356
|
+
applied: number;
|
|
357
|
+
created: number;
|
|
358
|
+
updated: number;
|
|
359
|
+
resubscribed: number;
|
|
360
|
+
skipped_unsubscribed: number;
|
|
361
|
+
rows: NewsletterSubscriptionsImportRowResult[];
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export interface NewsletterManagementPagination {
|
|
365
|
+
page: number;
|
|
366
|
+
limit: number;
|
|
367
|
+
total: number;
|
|
368
|
+
pages: number;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export interface NewsletterManagementSubscriptionsListResponse {
|
|
372
|
+
items: NewsletterManagementSubscription[];
|
|
373
|
+
pagination: NewsletterManagementPagination;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export interface NewsletterManagementList extends NewsletterList {
|
|
377
|
+
site_id: string;
|
|
378
|
+
site_name: string;
|
|
379
|
+
description?: string;
|
|
380
|
+
is_public: boolean;
|
|
381
|
+
is_default: boolean;
|
|
382
|
+
double_opt_in: boolean;
|
|
383
|
+
welcome_email_enabled: boolean;
|
|
384
|
+
subscriber_count: number;
|
|
385
|
+
status: 'active' | 'archived';
|
|
386
|
+
created_at: string;
|
|
387
|
+
updated_at: string;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export interface NewsletterManagementSeries {
|
|
391
|
+
id: string;
|
|
392
|
+
site_id: string;
|
|
393
|
+
site_name: string;
|
|
394
|
+
series_name: string;
|
|
395
|
+
description?: string | null;
|
|
396
|
+
list_ids?: string | null;
|
|
397
|
+
from_name?: string | null;
|
|
398
|
+
from_email?: string | null;
|
|
399
|
+
reply_to_email?: string | null;
|
|
400
|
+
subject_prefix?: string | null;
|
|
401
|
+
cadence: 'manual' | 'daily' | 'weekly' | 'monthly';
|
|
402
|
+
timezone?: string | null;
|
|
403
|
+
send_time?: string | null;
|
|
404
|
+
day_of_week?: number | null;
|
|
405
|
+
day_of_month?: number | null;
|
|
406
|
+
status: 'active' | 'paused' | 'archived';
|
|
407
|
+
last_sent_at?: string | null;
|
|
408
|
+
next_send_at?: string | null;
|
|
409
|
+
tags?: string | null;
|
|
410
|
+
notes?: string | null;
|
|
411
|
+
created_at: string;
|
|
412
|
+
updated_at: string;
|
|
413
|
+
created_by?: string | null;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export interface NewsletterManagementCampaign {
|
|
417
|
+
id: string;
|
|
418
|
+
site_id: string;
|
|
419
|
+
site_name: string;
|
|
420
|
+
series_id?: string | null;
|
|
421
|
+
series_name?: string | null;
|
|
422
|
+
campaign_name: string;
|
|
423
|
+
slug?: string | null;
|
|
424
|
+
slug_prefix?: string | null;
|
|
425
|
+
subject: string;
|
|
426
|
+
markdown_content?: string | null;
|
|
427
|
+
template_id?: string | null;
|
|
428
|
+
list_ids?: string | null;
|
|
429
|
+
tags?: string | null;
|
|
430
|
+
notes?: string | null;
|
|
431
|
+
preview_text?: string | null;
|
|
432
|
+
from_name?: string | null;
|
|
433
|
+
from_email?: string | null;
|
|
434
|
+
reply_to_email?: string | null;
|
|
435
|
+
status: 'draft' | 'scheduled' | 'sending' | 'sent' | 'cancelled';
|
|
436
|
+
scheduled_at?: string | null;
|
|
437
|
+
sent_at?: string | null;
|
|
438
|
+
completed_at?: string | null;
|
|
439
|
+
total_recipients?: number | null;
|
|
440
|
+
sent_count?: number | null;
|
|
441
|
+
delivered_count?: number | null;
|
|
442
|
+
opened_count?: number | null;
|
|
443
|
+
clicked_count?: number | null;
|
|
444
|
+
unsubscribed_count?: number | null;
|
|
445
|
+
bounced_count?: number | null;
|
|
446
|
+
complained_count?: number | null;
|
|
447
|
+
created_at: string;
|
|
448
|
+
updated_at: string;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export interface NewsletterManagementCampaignListResponse {
|
|
452
|
+
items: NewsletterManagementCampaign[];
|
|
453
|
+
pagination: NewsletterManagementPagination;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export interface NewsletterCampaignTestSendRequest {
|
|
457
|
+
to: string | string[];
|
|
458
|
+
subject?: string | null;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export interface NewsletterCampaignTestSendResponse {
|
|
462
|
+
sent: number;
|
|
463
|
+
recipients: string[];
|
|
464
|
+
campaign_id: string;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export interface NewsletterManagementStatsResponse {
|
|
468
|
+
total: number;
|
|
469
|
+
byStatus: Record<string, number>;
|
|
470
|
+
recentActivity: Array<{
|
|
471
|
+
date: string;
|
|
472
|
+
count: number;
|
|
473
|
+
}>;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export interface NewsletterExportCreateRequest {
|
|
477
|
+
format?: 'csv' | 'json' | 'xlsx';
|
|
478
|
+
status?: 'pending' | 'confirmed' | 'unsubscribed' | 'bounced' | 'complained';
|
|
479
|
+
list_id?: string;
|
|
480
|
+
search?: string | null;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export interface NewsletterExportCreateResponse {
|
|
484
|
+
exportId: string;
|
|
485
|
+
downloadUrl: string;
|
|
486
|
+
expiresAt: string;
|
|
487
|
+
format: 'csv' | 'json';
|
|
488
|
+
rowCount: number;
|
|
489
|
+
}
|
|
490
|
+
|
|
228
491
|
// Content Management
|
|
229
492
|
export type ContentStatus = 'draft' | 'publish' | 'private' | 'trash';
|
|
230
493
|
export type ContentType = 'post' | 'page' | 'block';
|
|
@@ -695,7 +958,7 @@ export interface SiteUserSubscription {
|
|
|
695
958
|
provider_subscription_id?: string;
|
|
696
959
|
plan_name?: string;
|
|
697
960
|
plan_id?: string;
|
|
698
|
-
status: 'active' | 'past_due' | 'canceled' | 'paused' | 'trialing' | 'expired';
|
|
961
|
+
status: 'active' | 'past_due' | 'canceled' | 'paused' | 'trialing' | 'expired' | 'incomplete';
|
|
699
962
|
amount?: number;
|
|
700
963
|
currency?: string;
|
|
701
964
|
billing_interval?: string;
|
|
@@ -718,11 +981,34 @@ export interface SiteUserOrder {
|
|
|
718
981
|
currency: string;
|
|
719
982
|
status: string;
|
|
720
983
|
payment_status?: string;
|
|
984
|
+
fulfillment_status?: string;
|
|
721
985
|
line_items: any[];
|
|
722
986
|
created_at: string;
|
|
723
987
|
completed_at?: string;
|
|
724
988
|
}
|
|
725
989
|
|
|
990
|
+
export type SubscriptionCancellationMode = 'immediate' | 'period_end' | 'scheduled';
|
|
991
|
+
|
|
992
|
+
export interface CancelSubscriptionRequest {
|
|
993
|
+
mode?: SubscriptionCancellationMode;
|
|
994
|
+
cancel_at?: string; // ISO timestamp
|
|
995
|
+
delay_days?: number;
|
|
996
|
+
delay_hours?: number;
|
|
997
|
+
delay_minutes?: number;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
export interface CancelSubscriptionResponse {
|
|
1001
|
+
success: boolean;
|
|
1002
|
+
message: string;
|
|
1003
|
+
cancellation?: {
|
|
1004
|
+
mode: SubscriptionCancellationMode;
|
|
1005
|
+
status: string;
|
|
1006
|
+
cancel_at_period_end: boolean;
|
|
1007
|
+
effective_at: string | null;
|
|
1008
|
+
scheduled_cancel_at: string | null;
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
|
|
726
1012
|
// Credits
|
|
727
1013
|
export interface CreditTransaction {
|
|
728
1014
|
id: number;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2 API Keys Client
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BaseV2Client } from './base-v2-client';
|
|
6
|
+
import type { V2ApiKey, V2PaginationParams, V2List, V2Deleted } from '../types';
|
|
7
|
+
|
|
8
|
+
export class ApiKeysV2Client extends BaseV2Client {
|
|
9
|
+
|
|
10
|
+
async list(params?: V2PaginationParams): Promise<V2List<V2ApiKey>> {
|
|
11
|
+
return this.getList<V2ApiKey>('/api-keys', params);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async get(id: string): Promise<V2ApiKey> {
|
|
15
|
+
return this.getOne<V2ApiKey>(`/api-keys/${id}`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async del(id: string): Promise<V2Deleted> {
|
|
19
|
+
return this.deleteOne(`/api-keys/${id}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2 Base Client — cursor pagination, expand support, typed errors.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { HttpClient } from '../../utils/http-client';
|
|
6
|
+
import type { V2List, V2Error, V2Deleted } from '../types';
|
|
7
|
+
|
|
8
|
+
export class PerspectV2Error extends Error {
|
|
9
|
+
readonly type: string;
|
|
10
|
+
readonly code: string;
|
|
11
|
+
readonly param?: string;
|
|
12
|
+
readonly status: number;
|
|
13
|
+
|
|
14
|
+
constructor(error: V2Error['error'], status: number) {
|
|
15
|
+
super(error.message);
|
|
16
|
+
this.name = 'PerspectV2Error';
|
|
17
|
+
this.type = error.type;
|
|
18
|
+
this.code = error.code;
|
|
19
|
+
this.param = error.param;
|
|
20
|
+
this.status = status;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export abstract class BaseV2Client {
|
|
25
|
+
protected http: HttpClient;
|
|
26
|
+
protected basePath: string;
|
|
27
|
+
|
|
28
|
+
constructor(http: HttpClient, basePath: string) {
|
|
29
|
+
this.http = http;
|
|
30
|
+
this.basePath = basePath;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected buildPath(endpoint: string): string {
|
|
34
|
+
const clean = endpoint.replace(/^\//, '');
|
|
35
|
+
return clean ? `${this.basePath}/${clean}` : this.basePath;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected sitePath(siteName: string, resource: string, suffix = ''): string {
|
|
39
|
+
const encoded = encodeURIComponent(siteName.trim());
|
|
40
|
+
const cleanSuffix = suffix.replace(/^\//, '');
|
|
41
|
+
const end = cleanSuffix ? `/${cleanSuffix}` : '';
|
|
42
|
+
return `/sites/${encoded}/${resource}${end}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
private toParams(params?: any): Record<string, string> | undefined {
|
|
47
|
+
if (!params) return undefined;
|
|
48
|
+
const out: Record<string, string> = {};
|
|
49
|
+
for (const [k, v] of Object.entries(params)) {
|
|
50
|
+
if (v !== undefined && v !== null) out[k] = String(v);
|
|
51
|
+
}
|
|
52
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** GET a single resource. */
|
|
56
|
+
protected async getOne<T>(path: string, params?: object): Promise<T> {
|
|
57
|
+
const response = await this.http.get<T>(path, this.toParams(params));
|
|
58
|
+
if (!response.success) {
|
|
59
|
+
throw this.toError(response);
|
|
60
|
+
}
|
|
61
|
+
return response.data!;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** GET a list of resources with cursor pagination. */
|
|
65
|
+
protected async getList<T>(
|
|
66
|
+
path: string,
|
|
67
|
+
params?: object,
|
|
68
|
+
): Promise<V2List<T>> {
|
|
69
|
+
const response = await this.http.get<V2List<T>>(path, this.toParams(params));
|
|
70
|
+
if (!response.success) {
|
|
71
|
+
throw this.toError(response);
|
|
72
|
+
}
|
|
73
|
+
return response.data!;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** POST to create a resource. */
|
|
77
|
+
protected async post<T>(path: string, body?: unknown): Promise<T> {
|
|
78
|
+
const response = await this.http.post<T>(path, body);
|
|
79
|
+
if (!response.success) {
|
|
80
|
+
throw this.toError(response);
|
|
81
|
+
}
|
|
82
|
+
return response.data!;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** PATCH to update a resource. */
|
|
86
|
+
protected async patchOne<T>(path: string, body?: unknown): Promise<T> {
|
|
87
|
+
const response = await this.http.patch<T>(path, body);
|
|
88
|
+
if (!response.success) {
|
|
89
|
+
throw this.toError(response);
|
|
90
|
+
}
|
|
91
|
+
return response.data!;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** DELETE a resource. */
|
|
95
|
+
protected async deleteOne(path: string): Promise<V2Deleted> {
|
|
96
|
+
const response = await this.http.delete<V2Deleted>(path);
|
|
97
|
+
if (!response.success) {
|
|
98
|
+
throw this.toError(response);
|
|
99
|
+
}
|
|
100
|
+
return response.data!;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Auto-paginating async generator.
|
|
105
|
+
* Yields every item across all pages.
|
|
106
|
+
*
|
|
107
|
+
* Usage:
|
|
108
|
+
* for await (const item of client.listAutoPaginate(path, params)) { ... }
|
|
109
|
+
*/
|
|
110
|
+
protected async *listAutoPaginate<T extends { id: string }>(
|
|
111
|
+
path: string,
|
|
112
|
+
params?: object,
|
|
113
|
+
): AsyncGenerator<T, void, unknown> {
|
|
114
|
+
let startingAfter: string | undefined;
|
|
115
|
+
let hasMore = true;
|
|
116
|
+
|
|
117
|
+
while (hasMore) {
|
|
118
|
+
const queryParams: Record<string, unknown> = { ...(params as Record<string, unknown>) };
|
|
119
|
+
if (startingAfter) queryParams.starting_after = startingAfter;
|
|
120
|
+
|
|
121
|
+
const page = await this.getList<T>(path, queryParams);
|
|
122
|
+
for (const item of page.data) {
|
|
123
|
+
yield item;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
hasMore = page.has_more;
|
|
127
|
+
if (page.data.length > 0) {
|
|
128
|
+
startingAfter = page.data[page.data.length - 1].id;
|
|
129
|
+
} else {
|
|
130
|
+
hasMore = false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private toError(response: { data?: unknown; error?: unknown; message?: string }): PerspectV2Error {
|
|
136
|
+
const data = response.data as Record<string, unknown> | undefined;
|
|
137
|
+
const errorObj = (data?.error ?? response.error) as V2Error['error'] | undefined;
|
|
138
|
+
if (errorObj && typeof errorObj === 'object' && 'type' in errorObj) {
|
|
139
|
+
return new PerspectV2Error(errorObj, 400);
|
|
140
|
+
}
|
|
141
|
+
return new PerspectV2Error(
|
|
142
|
+
{ type: 'api_error', code: 'unknown', message: response.message ?? 'Unknown error' },
|
|
143
|
+
500,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2 Categories Client
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BaseV2Client } from './base-v2-client';
|
|
6
|
+
import type {
|
|
7
|
+
V2Category, V2CategoryCreateParams, V2CategoryUpdateParams,
|
|
8
|
+
V2PaginationParams, V2List, V2Deleted,
|
|
9
|
+
} from '../types';
|
|
10
|
+
|
|
11
|
+
export class CategoriesV2Client extends BaseV2Client {
|
|
12
|
+
|
|
13
|
+
async list(siteName: string, params?: V2PaginationParams & { type?: string }): Promise<V2List<V2Category>> {
|
|
14
|
+
return this.getList<V2Category>(this.sitePath(siteName, 'categories'), params);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async get(siteName: string, id: string): Promise<V2Category> {
|
|
18
|
+
return this.getOne<V2Category>(this.sitePath(siteName, 'categories', id));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async create(siteName: string, data: V2CategoryCreateParams): Promise<V2Category> {
|
|
22
|
+
return this.post<V2Category>(this.sitePath(siteName, 'categories'), data);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async update(siteName: string, id: string, data: V2CategoryUpdateParams): Promise<V2Category> {
|
|
26
|
+
return this.patchOne<V2Category>(this.sitePath(siteName, 'categories', id), data);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async del(siteName: string, id: string): Promise<V2Deleted> {
|
|
30
|
+
return this.deleteOne(this.sitePath(siteName, 'categories', id));
|
|
31
|
+
}
|
|
32
|
+
}
|