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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * v2 Collections Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type {
7
+ V2Collection, V2CollectionItem, V2CollectionCreateParams,
8
+ V2CollectionUpdateParams, V2PaginationParams, V2List, V2Deleted,
9
+ } from '../types';
10
+
11
+ export class CollectionsV2Client extends BaseV2Client {
12
+
13
+ async list(siteName: string, params?: V2PaginationParams): Promise<V2List<V2Collection>> {
14
+ return this.getList<V2Collection>(this.sitePath(siteName, 'collections'), params);
15
+ }
16
+
17
+ async getCurrent(siteName: string): Promise<V2Collection | null> {
18
+ const result = await this.getOne<{ object: string; data: V2Collection | null }>(
19
+ this.sitePath(siteName, 'collections', 'current'),
20
+ );
21
+ return (result as unknown as V2Collection) ?? null;
22
+ }
23
+
24
+ async get(siteName: string, id: string): Promise<V2Collection> {
25
+ return this.getOne<V2Collection>(this.sitePath(siteName, 'collections', id));
26
+ }
27
+
28
+ async create(siteName: string, data: V2CollectionCreateParams): Promise<V2Collection> {
29
+ return this.post<V2Collection>(this.sitePath(siteName, 'collections'), data);
30
+ }
31
+
32
+ async update(siteName: string, id: string, data: V2CollectionUpdateParams): Promise<V2Collection> {
33
+ return this.patchOne<V2Collection>(this.sitePath(siteName, 'collections', id), data);
34
+ }
35
+
36
+ async del(siteName: string, id: string): Promise<V2Deleted> {
37
+ return this.deleteOne(this.sitePath(siteName, 'collections', id));
38
+ }
39
+
40
+ // --- Items ---
41
+
42
+ async listItems(siteName: string, collectionId: string): Promise<V2List<V2CollectionItem>> {
43
+ return this.getList<V2CollectionItem>(
44
+ this.sitePath(siteName, 'collections', `${collectionId}/items`),
45
+ );
46
+ }
47
+
48
+ async addItem(
49
+ siteName: string,
50
+ collectionId: string,
51
+ data: { product_id: string; max_quantity?: number | null; position?: number },
52
+ ): Promise<V2CollectionItem> {
53
+ return this.post<V2CollectionItem>(
54
+ this.sitePath(siteName, 'collections', `${collectionId}/items`),
55
+ data,
56
+ );
57
+ }
58
+
59
+ async removeItem(siteName: string, collectionId: string, itemId: string): Promise<V2Deleted> {
60
+ return this.deleteOne(
61
+ this.sitePath(siteName, 'collections', `${collectionId}/items/${itemId}`),
62
+ );
63
+ }
64
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * v2 Contacts Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type { V2ContactSubmission, V2PaginationParams, V2List } from '../types';
7
+
8
+ export class ContactsV2Client extends BaseV2Client {
9
+
10
+ async submit(
11
+ siteName: string,
12
+ data: {
13
+ email: string;
14
+ message: string;
15
+ name?: string;
16
+ first_name?: string;
17
+ last_name?: string;
18
+ subject?: string;
19
+ phone?: string;
20
+ company?: string;
21
+ metadata?: Record<string, unknown>;
22
+ },
23
+ ): Promise<V2ContactSubmission> {
24
+ return this.post<V2ContactSubmission>(this.sitePath(siteName, 'contacts'), data);
25
+ }
26
+
27
+ async list(
28
+ siteName: string,
29
+ params?: V2PaginationParams & { status?: string },
30
+ ): Promise<V2List<V2ContactSubmission>> {
31
+ return this.getList<V2ContactSubmission>(this.sitePath(siteName, 'contacts'), params);
32
+ }
33
+
34
+ async get(siteName: string, id: string): Promise<V2ContactSubmission> {
35
+ return this.getOne<V2ContactSubmission>(this.sitePath(siteName, 'contacts', id));
36
+ }
37
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * v2 Content Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type {
7
+ V2Content, V2ContentCreateParams, V2ContentUpdateParams,
8
+ V2ContentListParams, V2List, V2Deleted,
9
+ } from '../types';
10
+
11
+ export class ContentV2Client extends BaseV2Client {
12
+
13
+ async list(siteName: string, params?: V2ContentListParams): Promise<V2List<V2Content>> {
14
+ return this.getList<V2Content>(this.sitePath(siteName, 'content'), params);
15
+ }
16
+
17
+ async *listAutoPaginated(siteName: string, params?: Omit<V2ContentListParams, 'starting_after' | 'ending_before'>) {
18
+ yield* this.listAutoPaginate<V2Content>(this.sitePath(siteName, 'content'), params);
19
+ }
20
+
21
+ async get(siteName: string, idOrSlug: string): Promise<V2Content> {
22
+ return this.getOne<V2Content>(this.sitePath(siteName, 'content', idOrSlug));
23
+ }
24
+
25
+ async create(siteName: string, data: V2ContentCreateParams): Promise<V2Content> {
26
+ return this.post<V2Content>(this.sitePath(siteName, 'content'), data);
27
+ }
28
+
29
+ async update(siteName: string, id: string, data: V2ContentUpdateParams): Promise<V2Content> {
30
+ return this.patchOne<V2Content>(this.sitePath(siteName, 'content', id), data);
31
+ }
32
+
33
+ async del(siteName: string, id: string): Promise<V2Deleted> {
34
+ return this.deleteOne(this.sitePath(siteName, 'content', id));
35
+ }
36
+
37
+ async publish(siteName: string, id: string): Promise<V2Content> {
38
+ return this.post<V2Content>(this.sitePath(siteName, 'content', `${id}/publish`));
39
+ }
40
+
41
+ async unpublish(siteName: string, id: string): Promise<V2Content> {
42
+ return this.post<V2Content>(this.sitePath(siteName, 'content', `${id}/unpublish`));
43
+ }
44
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * v2 Newsletter Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type {
7
+ V2NewsletterSubscription, V2NewsletterList, V2NewsletterCampaign,
8
+ V2PaginationParams, V2List,
9
+ } from '../types';
10
+
11
+ export class NewsletterV2Client extends BaseV2Client {
12
+
13
+ // --- Subscribe / Unsubscribe ---
14
+
15
+ async subscribe(
16
+ siteName: string,
17
+ data: {
18
+ email: string;
19
+ name?: string;
20
+ list_ids?: string[];
21
+ double_opt_in?: boolean;
22
+ source?: string;
23
+ source_url?: string;
24
+ frequency?: 'instant' | 'daily' | 'weekly' | 'monthly';
25
+ topics?: string[];
26
+ language?: string;
27
+ metadata?: Record<string, unknown>;
28
+ },
29
+ ): Promise<V2NewsletterSubscription> {
30
+ return this.post<V2NewsletterSubscription>(
31
+ this.sitePath(siteName, 'newsletter', 'subscribe'),
32
+ data,
33
+ );
34
+ }
35
+
36
+ async confirm(siteName: string, token: string): Promise<V2NewsletterSubscription> {
37
+ return this.getOne<V2NewsletterSubscription>(
38
+ this.sitePath(siteName, 'newsletter', `confirm/${token}`),
39
+ );
40
+ }
41
+
42
+ async unsubscribe(
43
+ siteName: string,
44
+ data: { token?: string; email?: string; reason?: string },
45
+ ): Promise<V2NewsletterSubscription> {
46
+ return this.post<V2NewsletterSubscription>(
47
+ this.sitePath(siteName, 'newsletter', 'unsubscribe'),
48
+ data,
49
+ );
50
+ }
51
+
52
+ // --- Subscriptions (admin) ---
53
+
54
+ async listSubscriptions(
55
+ siteName: string,
56
+ params?: V2PaginationParams & { status?: string },
57
+ ): Promise<V2List<V2NewsletterSubscription>> {
58
+ return this.getList<V2NewsletterSubscription>(
59
+ this.sitePath(siteName, 'newsletter', 'subscriptions'),
60
+ params,
61
+ );
62
+ }
63
+
64
+ async getSubscription(siteName: string, id: string): Promise<V2NewsletterSubscription> {
65
+ return this.getOne<V2NewsletterSubscription>(
66
+ this.sitePath(siteName, 'newsletter', `subscriptions/${id}`),
67
+ );
68
+ }
69
+
70
+ // --- Lists ---
71
+
72
+ async listLists(siteName: string): Promise<V2List<V2NewsletterList>> {
73
+ return this.getList<V2NewsletterList>(
74
+ this.sitePath(siteName, 'newsletter', 'lists'),
75
+ );
76
+ }
77
+
78
+ // --- Campaigns ---
79
+
80
+ async listCampaigns(
81
+ siteName: string,
82
+ params?: V2PaginationParams & { status?: string },
83
+ ): Promise<V2List<V2NewsletterCampaign>> {
84
+ return this.getList<V2NewsletterCampaign>(
85
+ this.sitePath(siteName, 'newsletter', 'campaigns'),
86
+ params,
87
+ );
88
+ }
89
+
90
+ async getCampaign(siteName: string, idOrSlug: string): Promise<V2NewsletterCampaign> {
91
+ return this.getOne<V2NewsletterCampaign>(
92
+ this.sitePath(siteName, 'newsletter', `campaigns/${idOrSlug}`),
93
+ );
94
+ }
95
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * v2 Orders Client (checkout sessions)
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type { V2Order, V2OrderListParams, V2List } from '../types';
7
+
8
+ export class OrdersV2Client extends BaseV2Client {
9
+
10
+ async list(siteName: string, params?: V2OrderListParams): Promise<V2List<V2Order>> {
11
+ return this.getList<V2Order>(this.sitePath(siteName, 'orders'), params);
12
+ }
13
+
14
+ async *listAutoPaginated(siteName: string, params?: Omit<V2OrderListParams, 'starting_after' | 'ending_before'>) {
15
+ yield* this.listAutoPaginate<V2Order>(this.sitePath(siteName, 'orders'), params);
16
+ }
17
+
18
+ async get(siteName: string, id: string): Promise<V2Order> {
19
+ return this.getOne<V2Order>(this.sitePath(siteName, 'orders', id));
20
+ }
21
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * v2 Organizations Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type { V2Organization, V2List } from '../types';
7
+
8
+ export class OrganizationsV2Client extends BaseV2Client {
9
+
10
+ async list(): Promise<V2List<V2Organization>> {
11
+ return this.getList<V2Organization>('/organizations');
12
+ }
13
+
14
+ async get(id: string): Promise<V2Organization> {
15
+ return this.getOne<V2Organization>(`/organizations/${id}`);
16
+ }
17
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * v2 Products Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type {
7
+ V2Product, V2ProductCreateParams, V2ProductUpdateParams,
8
+ V2ProductListParams, V2List, V2Deleted,
9
+ } from '../types';
10
+
11
+ export class ProductsV2Client extends BaseV2Client {
12
+
13
+ async list(siteName: string, params?: V2ProductListParams): Promise<V2List<V2Product>> {
14
+ return this.getList<V2Product>(this.sitePath(siteName, 'products'), params);
15
+ }
16
+
17
+ async *listAutoPaginated(siteName: string, params?: Omit<V2ProductListParams, 'starting_after' | 'ending_before'>) {
18
+ yield* this.listAutoPaginate<V2Product>(this.sitePath(siteName, 'products'), params);
19
+ }
20
+
21
+ async get(siteName: string, idOrSlug: string): Promise<V2Product> {
22
+ return this.getOne<V2Product>(this.sitePath(siteName, 'products', idOrSlug));
23
+ }
24
+
25
+ async create(siteName: string, data: V2ProductCreateParams): Promise<V2Product> {
26
+ return this.post<V2Product>(this.sitePath(siteName, 'products'), data);
27
+ }
28
+
29
+ async update(siteName: string, id: string, data: V2ProductUpdateParams): Promise<V2Product> {
30
+ return this.patchOne<V2Product>(this.sitePath(siteName, 'products', id), data);
31
+ }
32
+
33
+ async del(siteName: string, id: string): Promise<V2Deleted> {
34
+ return this.deleteOne(this.sitePath(siteName, 'products', id));
35
+ }
36
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * v2 Site Users Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type { V2SiteUser, V2SiteUserUpdateParams, V2SiteUserListParams, V2List } from '../types';
7
+
8
+ export interface V2OtpRequestResponse {
9
+ object: 'otp_request';
10
+ email: string;
11
+ expires_in: number;
12
+ }
13
+
14
+ export interface V2OtpVerifyResponse extends V2SiteUser {
15
+ token: string;
16
+ }
17
+
18
+ export class SiteUsersV2Client extends BaseV2Client {
19
+
20
+ // --- OTP Auth ---
21
+
22
+ async requestOtp(
23
+ siteName: string,
24
+ data: { email: string; waitlist?: boolean; metadata?: Record<string, unknown> },
25
+ ): Promise<V2OtpRequestResponse> {
26
+ return this.post<V2OtpRequestResponse>(this.sitePath(siteName, 'users', 'request-otp'), data);
27
+ }
28
+
29
+ async verifyOtp(
30
+ siteName: string,
31
+ data: { email: string; code: string },
32
+ ): Promise<V2OtpVerifyResponse> {
33
+ return this.post<V2OtpVerifyResponse>(this.sitePath(siteName, 'users', 'verify-otp'), data);
34
+ }
35
+
36
+ // --- Admin ---
37
+
38
+ async list(siteName: string, params?: V2SiteUserListParams): Promise<V2List<V2SiteUser>> {
39
+ return this.getList<V2SiteUser>(this.sitePath(siteName, 'users'), params);
40
+ }
41
+
42
+ async *listAutoPaginated(siteName: string, params?: Omit<V2SiteUserListParams, 'starting_after' | 'ending_before'>) {
43
+ yield* this.listAutoPaginate<V2SiteUser>(this.sitePath(siteName, 'users'), params);
44
+ }
45
+
46
+ async get(siteName: string, id: string): Promise<V2SiteUser> {
47
+ return this.getOne<V2SiteUser>(this.sitePath(siteName, 'users', id));
48
+ }
49
+
50
+ async update(siteName: string, id: string, data: V2SiteUserUpdateParams): Promise<V2SiteUser> {
51
+ return this.patchOne<V2SiteUser>(this.sitePath(siteName, 'users', id), data);
52
+ }
53
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * v2 Sites Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type { V2Site, V2PaginationParams, V2List } from '../types';
7
+
8
+ export class SitesV2Client extends BaseV2Client {
9
+
10
+ async list(params?: V2PaginationParams): Promise<V2List<V2Site>> {
11
+ return this.getList<V2Site>('/sites', params);
12
+ }
13
+
14
+ async get(name: string): Promise<V2Site> {
15
+ return this.getOne<V2Site>(`/sites/${encodeURIComponent(name)}`);
16
+ }
17
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * v2 Webhooks Client
3
+ */
4
+
5
+ import { BaseV2Client } from './base-v2-client';
6
+ import type {
7
+ V2Webhook, V2WebhookCreateParams, V2WebhookUpdateParams,
8
+ V2PaginationParams, V2List, V2Deleted,
9
+ } from '../types';
10
+
11
+ export class WebhooksV2Client extends BaseV2Client {
12
+
13
+ async list(siteName: string, params?: V2PaginationParams): Promise<V2List<V2Webhook>> {
14
+ return this.getList<V2Webhook>(this.sitePath(siteName, 'webhooks'), params);
15
+ }
16
+
17
+ async get(siteName: string, id: string): Promise<V2Webhook> {
18
+ return this.getOne<V2Webhook>(this.sitePath(siteName, 'webhooks', id));
19
+ }
20
+
21
+ async create(siteName: string, data: V2WebhookCreateParams): Promise<V2Webhook> {
22
+ return this.post<V2Webhook>(this.sitePath(siteName, 'webhooks'), data);
23
+ }
24
+
25
+ async update(siteName: string, id: string, data: V2WebhookUpdateParams): Promise<V2Webhook> {
26
+ return this.patchOne<V2Webhook>(this.sitePath(siteName, 'webhooks', id), data);
27
+ }
28
+
29
+ async del(siteName: string, id: string): Promise<V2Deleted> {
30
+ return this.deleteOne(this.sitePath(siteName, 'webhooks', id));
31
+ }
32
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * PerspectAPI v2 SDK Client
3
+ *
4
+ * Stripe-style API with consistent envelopes, prefixed IDs,
5
+ * cursor pagination, and snake_case responses.
6
+ *
7
+ * Usage:
8
+ * import { PerspectApiV2Client } from 'perspectapi-ts-sdk/v2';
9
+ * const client = new PerspectApiV2Client({ baseUrl: '...', apiKey: '...' });
10
+ * const posts = await client.content.list('mysite', { type: 'post', limit: 10 });
11
+ */
12
+
13
+ import { HttpClient } from '../utils/http-client';
14
+ import type { PerspectApiConfig } from '../types';
15
+
16
+ import { ContentV2Client } from './client/content-client';
17
+ import { ProductsV2Client } from './client/products-client';
18
+ import { CategoriesV2Client } from './client/categories-client';
19
+ import { CollectionsV2Client } from './client/collections-client';
20
+ import { OrdersV2Client } from './client/orders-client';
21
+ import { SiteUsersV2Client } from './client/site-users-client';
22
+ import { NewsletterV2Client } from './client/newsletter-client';
23
+ import { ContactsV2Client } from './client/contacts-client';
24
+ import { OrganizationsV2Client } from './client/organizations-client';
25
+ import { SitesV2Client } from './client/sites-client';
26
+ import { ApiKeysV2Client } from './client/api-keys-client';
27
+ import { WebhooksV2Client } from './client/webhooks-client';
28
+
29
+ export class PerspectApiV2Client {
30
+ private http: HttpClient;
31
+
32
+ readonly content: ContentV2Client;
33
+ readonly products: ProductsV2Client;
34
+ readonly categories: CategoriesV2Client;
35
+ readonly collections: CollectionsV2Client;
36
+ readonly orders: OrdersV2Client;
37
+ readonly siteUsers: SiteUsersV2Client;
38
+ readonly newsletter: NewsletterV2Client;
39
+ readonly contacts: ContactsV2Client;
40
+ readonly organizations: OrganizationsV2Client;
41
+ readonly sites: SitesV2Client;
42
+ readonly apiKeys: ApiKeysV2Client;
43
+ readonly webhooks: WebhooksV2Client;
44
+
45
+ constructor(config: PerspectApiConfig) {
46
+ // Ensure base URL points to /api/v2
47
+ const baseUrl = config.baseUrl.replace(/\/+$/, '');
48
+ const v2BaseUrl = baseUrl.endsWith('/api/v2')
49
+ ? baseUrl
50
+ : `${baseUrl}/api/v2`;
51
+
52
+ this.http = new HttpClient({ ...config, baseUrl: v2BaseUrl });
53
+
54
+ const basePath = '';
55
+ this.content = new ContentV2Client(this.http, basePath);
56
+ this.products = new ProductsV2Client(this.http, basePath);
57
+ this.categories = new CategoriesV2Client(this.http, basePath);
58
+ this.collections = new CollectionsV2Client(this.http, basePath);
59
+ this.orders = new OrdersV2Client(this.http, basePath);
60
+ this.siteUsers = new SiteUsersV2Client(this.http, basePath);
61
+ this.newsletter = new NewsletterV2Client(this.http, basePath);
62
+ this.contacts = new ContactsV2Client(this.http, basePath);
63
+ this.organizations = new OrganizationsV2Client(this.http, basePath);
64
+ this.sites = new SitesV2Client(this.http, basePath);
65
+ this.apiKeys = new ApiKeysV2Client(this.http, basePath);
66
+ this.webhooks = new WebhooksV2Client(this.http, basePath);
67
+ }
68
+
69
+ /** Update the JWT token for authenticated requests. */
70
+ setAuth(jwt: string): void {
71
+ this.http.setAuth(jwt);
72
+ }
73
+
74
+ /** Update the API key. */
75
+ setApiKey(apiKey: string): void {
76
+ this.http.setApiKey(apiKey);
77
+ }
78
+
79
+ /** Clear authentication. */
80
+ clearAuth(): void {
81
+ this.http.clearAuth();
82
+ }
83
+ }
84
+
85
+ export function createPerspectApiV2Client(config: PerspectApiConfig): PerspectApiV2Client {
86
+ return new PerspectApiV2Client(config);
87
+ }
88
+
89
+ // Re-export all types
90
+ export type * from './types';
91
+
92
+ // Re-export client classes
93
+ export { BaseV2Client, PerspectV2Error } from './client/base-v2-client';
94
+ export { ContentV2Client } from './client/content-client';
95
+ export { ProductsV2Client } from './client/products-client';
96
+ export { CategoriesV2Client } from './client/categories-client';
97
+ export { CollectionsV2Client } from './client/collections-client';
98
+ export { OrdersV2Client } from './client/orders-client';
99
+ export { SiteUsersV2Client } from './client/site-users-client';
100
+ export { NewsletterV2Client } from './client/newsletter-client';
101
+ export { ContactsV2Client } from './client/contacts-client';
102
+ export { OrganizationsV2Client } from './client/organizations-client';
103
+ export { SitesV2Client } from './client/sites-client';
104
+ export { ApiKeysV2Client } from './client/api-keys-client';
105
+ export { WebhooksV2Client } from './client/webhooks-client';