perspectapi-ts-sdk 2.7.0 → 2.8.2
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 +352 -2
- package/dist/index.d.ts +352 -2
- package/dist/index.js +328 -1
- package/dist/index.mjs +327 -1
- package/package.json +1 -1
- package/src/client/products-client.ts +123 -0
- package/src/client/site-users-client.ts +352 -0
- package/src/index.ts +10 -0
- package/src/perspect-api-client.ts +3 -0
- package/src/types/index.ts +90 -1
- package/src/utils/validators.ts +1 -2
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site Users client for PerspectAPI SDK
|
|
3
|
+
* Handles per-site customer accounts (OTP-based auth, profiles, orders, subscriptions)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BaseClient } from './base-client';
|
|
7
|
+
import type { CacheManager } from '../cache/cache-manager';
|
|
8
|
+
import type {
|
|
9
|
+
SiteUser,
|
|
10
|
+
SiteUserProfile,
|
|
11
|
+
SiteUserSubscription,
|
|
12
|
+
SiteUserOrder,
|
|
13
|
+
RequestOtpRequest,
|
|
14
|
+
VerifyOtpRequest,
|
|
15
|
+
VerifyOtpResponse,
|
|
16
|
+
UpdateSiteUserRequest,
|
|
17
|
+
SetProfileValueRequest,
|
|
18
|
+
ApiResponse,
|
|
19
|
+
} from '../types';
|
|
20
|
+
|
|
21
|
+
export class SiteUsersClient extends BaseClient {
|
|
22
|
+
constructor(http: any, cache?: CacheManager) {
|
|
23
|
+
super(http, '/api/v1', cache);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build a site user endpoint scoped to a site (without /sites prefix)
|
|
28
|
+
*/
|
|
29
|
+
private siteUserEndpoint(siteName: string, endpoint: string): string {
|
|
30
|
+
return this.siteScopedEndpoint(siteName, endpoint, { includeSitesSegment: false });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// PUBLIC ENDPOINTS (OTP authentication)
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Request OTP for login/signup
|
|
39
|
+
* @param siteName - The site name
|
|
40
|
+
* @param data - Email address
|
|
41
|
+
* @param csrfToken - CSRF token (required for browser-based submissions)
|
|
42
|
+
*/
|
|
43
|
+
async requestOtp(
|
|
44
|
+
siteName: string,
|
|
45
|
+
data: RequestOtpRequest,
|
|
46
|
+
csrfToken?: string
|
|
47
|
+
): Promise<ApiResponse<{ success: boolean }>> {
|
|
48
|
+
if (typeof window !== 'undefined' && !csrfToken) {
|
|
49
|
+
console.warn('CSRF token recommended for browser-based OTP requests');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return this.create<RequestOtpRequest, { success: boolean }>(
|
|
53
|
+
this.siteUserEndpoint(siteName, '/users/request-otp'),
|
|
54
|
+
data,
|
|
55
|
+
csrfToken
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Verify OTP and get JWT token
|
|
61
|
+
*
|
|
62
|
+
* For cross-domain authentication, you must manually set the token after verification:
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const response = await client.siteUsers.verifyOtp('mysite', { email, code });
|
|
65
|
+
* const { token, user } = response.data;
|
|
66
|
+
*
|
|
67
|
+
* // Store token securely (choose one):
|
|
68
|
+
* // Option 1: Memory (lost on refresh, most secure)
|
|
69
|
+
* client.setAuth(token);
|
|
70
|
+
*
|
|
71
|
+
* // Option 2: httpOnly cookie on YOUR domain (recommended for production)
|
|
72
|
+
* await fetch('/your-api/set-auth-cookie', {
|
|
73
|
+
* method: 'POST',
|
|
74
|
+
* body: JSON.stringify({ token })
|
|
75
|
+
* });
|
|
76
|
+
* client.setAuth(token);
|
|
77
|
+
*
|
|
78
|
+
* // Option 3: localStorage (vulnerable to XSS, not recommended)
|
|
79
|
+
* localStorage.setItem('site_user_token', token);
|
|
80
|
+
* client.setAuth(token);
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* For convenience, use `verifyOtpAndSetAuth()` to automatically set the token in memory.
|
|
84
|
+
*
|
|
85
|
+
* @param siteName - The site name
|
|
86
|
+
* @param data - Email and code
|
|
87
|
+
* @param csrfToken - CSRF token (required for browser-based submissions)
|
|
88
|
+
*/
|
|
89
|
+
async verifyOtp(
|
|
90
|
+
siteName: string,
|
|
91
|
+
data: VerifyOtpRequest,
|
|
92
|
+
csrfToken?: string
|
|
93
|
+
): Promise<ApiResponse<VerifyOtpResponse>> {
|
|
94
|
+
if (typeof window !== 'undefined' && !csrfToken) {
|
|
95
|
+
console.warn('CSRF token recommended for browser-based OTP verification');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return this.create<VerifyOtpRequest, VerifyOtpResponse>(
|
|
99
|
+
this.siteUserEndpoint(siteName, '/users/verify-otp'),
|
|
100
|
+
data,
|
|
101
|
+
csrfToken
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Verify OTP and automatically set the token for subsequent requests
|
|
107
|
+
*
|
|
108
|
+
* Convenience method that:
|
|
109
|
+
* 1. Verifies the OTP
|
|
110
|
+
* 2. Automatically calls setAuth() with the returned token
|
|
111
|
+
*
|
|
112
|
+
* Note: Token is stored in memory only and will be lost on page refresh.
|
|
113
|
+
* For persistent auth, use verifyOtp() and store the token yourself.
|
|
114
|
+
*
|
|
115
|
+
* @param siteName - The site name
|
|
116
|
+
* @param data - Email and code
|
|
117
|
+
* @param csrfToken - CSRF token (required for browser-based submissions)
|
|
118
|
+
*/
|
|
119
|
+
async verifyOtpAndSetAuth(
|
|
120
|
+
siteName: string,
|
|
121
|
+
data: VerifyOtpRequest,
|
|
122
|
+
csrfToken?: string
|
|
123
|
+
): Promise<ApiResponse<VerifyOtpResponse>> {
|
|
124
|
+
const response = await this.verifyOtp(siteName, data, csrfToken);
|
|
125
|
+
|
|
126
|
+
if (response.data?.token) {
|
|
127
|
+
this.http.setAuth(response.data.token);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return response;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Logout (clear session cookie)
|
|
135
|
+
* @param siteName - The site name
|
|
136
|
+
*/
|
|
137
|
+
async logout(siteName: string): Promise<ApiResponse<{ success: boolean }>> {
|
|
138
|
+
return this.create<Record<string, never>, { success: boolean }>(
|
|
139
|
+
this.siteUserEndpoint(siteName, '/users/logout'),
|
|
140
|
+
{}
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// AUTHENTICATED ENDPOINTS (site user JWT required)
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get current user profile
|
|
150
|
+
* @param siteName - The site name
|
|
151
|
+
*/
|
|
152
|
+
async getMe(siteName: string): Promise<ApiResponse<{ user: SiteUser; profile: SiteUserProfile }>> {
|
|
153
|
+
return this.getSingle<{ user: SiteUser; profile: SiteUserProfile }>(
|
|
154
|
+
this.siteUserEndpoint(siteName, '/users/me')
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Update current user profile
|
|
160
|
+
* @param siteName - The site name
|
|
161
|
+
* @param data - Fields to update
|
|
162
|
+
* @param csrfToken - CSRF token (required)
|
|
163
|
+
*/
|
|
164
|
+
async updateMe(
|
|
165
|
+
siteName: string,
|
|
166
|
+
data: UpdateSiteUserRequest,
|
|
167
|
+
csrfToken?: string
|
|
168
|
+
): Promise<ApiResponse<{ success: boolean }>> {
|
|
169
|
+
return this.patch<UpdateSiteUserRequest, { success: boolean }>(
|
|
170
|
+
this.siteUserEndpoint(siteName, '/users/me'),
|
|
171
|
+
data,
|
|
172
|
+
csrfToken
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get all profile key-values
|
|
178
|
+
* @param siteName - The site name
|
|
179
|
+
*/
|
|
180
|
+
async getProfile(siteName: string): Promise<ApiResponse<{ profile: SiteUserProfile }>> {
|
|
181
|
+
return this.getSingle<{ profile: SiteUserProfile }>(
|
|
182
|
+
this.siteUserEndpoint(siteName, '/users/me/profile')
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Set a profile key-value
|
|
188
|
+
* @param siteName - The site name
|
|
189
|
+
* @param key - Profile key (e.g., 'phone', 'whatsapp', 'address_shipping')
|
|
190
|
+
* @param value - Profile value (string or JSON string)
|
|
191
|
+
* @param csrfToken - CSRF token (required)
|
|
192
|
+
*/
|
|
193
|
+
async setProfileValue(
|
|
194
|
+
siteName: string,
|
|
195
|
+
key: string,
|
|
196
|
+
value: string,
|
|
197
|
+
csrfToken?: string
|
|
198
|
+
): Promise<ApiResponse<{ success: boolean }>> {
|
|
199
|
+
return this.update<SetProfileValueRequest, { success: boolean }>(
|
|
200
|
+
this.siteUserEndpoint(siteName, `/users/me/profile/${encodeURIComponent(key)}`),
|
|
201
|
+
{ value },
|
|
202
|
+
csrfToken
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Delete a profile key-value
|
|
208
|
+
* @param siteName - The site name
|
|
209
|
+
* @param key - Profile key to delete
|
|
210
|
+
* @param csrfToken - CSRF token (required)
|
|
211
|
+
*/
|
|
212
|
+
async deleteProfileValue(
|
|
213
|
+
siteName: string,
|
|
214
|
+
key: string,
|
|
215
|
+
csrfToken?: string
|
|
216
|
+
): Promise<ApiResponse<{ success: boolean }>> {
|
|
217
|
+
return this.delete<{ success: boolean }>(
|
|
218
|
+
this.siteUserEndpoint(siteName, `/users/me/profile/${encodeURIComponent(key)}`),
|
|
219
|
+
csrfToken
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get transaction/order history
|
|
225
|
+
* @param siteName - The site name
|
|
226
|
+
* @param params - Pagination params
|
|
227
|
+
*/
|
|
228
|
+
async getOrders(
|
|
229
|
+
siteName: string,
|
|
230
|
+
params?: { limit?: number; offset?: number }
|
|
231
|
+
): Promise<ApiResponse<{ orders: SiteUserOrder[] }>> {
|
|
232
|
+
return this.http.get<{ orders: SiteUserOrder[] }>(
|
|
233
|
+
this.buildPath(this.siteUserEndpoint(siteName, '/users/me/orders')),
|
|
234
|
+
params
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get single order detail
|
|
240
|
+
* @param siteName - The site name
|
|
241
|
+
* @param orderId - Order ID or session ID
|
|
242
|
+
*/
|
|
243
|
+
async getOrder(siteName: string, orderId: string): Promise<ApiResponse<{ order: any }>> {
|
|
244
|
+
return this.getSingle<{ order: any }>(
|
|
245
|
+
this.siteUserEndpoint(siteName, `/users/me/orders/${encodeURIComponent(orderId)}`)
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get payment subscriptions
|
|
251
|
+
* @param siteName - The site name
|
|
252
|
+
* @param params - Pagination params
|
|
253
|
+
*/
|
|
254
|
+
async getSubscriptions(
|
|
255
|
+
siteName: string,
|
|
256
|
+
params?: { limit?: number; offset?: number }
|
|
257
|
+
): Promise<ApiResponse<{ subscriptions: SiteUserSubscription[] }>> {
|
|
258
|
+
return this.http.get<{ subscriptions: SiteUserSubscription[] }>(
|
|
259
|
+
this.buildPath(this.siteUserEndpoint(siteName, '/users/me/subscriptions')),
|
|
260
|
+
params
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get single subscription detail
|
|
266
|
+
* @param siteName - The site name
|
|
267
|
+
* @param id - Subscription ID
|
|
268
|
+
*/
|
|
269
|
+
async getSubscription(siteName: string, id: string): Promise<ApiResponse<{ subscription: SiteUserSubscription }>> {
|
|
270
|
+
return this.getSingle<{ subscription: SiteUserSubscription }>(
|
|
271
|
+
this.siteUserEndpoint(siteName, `/users/me/subscriptions/${encodeURIComponent(id)}`)
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Cancel a subscription (marks for cancellation at period end)
|
|
277
|
+
* @param siteName - The site name
|
|
278
|
+
* @param id - Subscription ID
|
|
279
|
+
* @param csrfToken - CSRF token (required)
|
|
280
|
+
*/
|
|
281
|
+
async cancelSubscription(
|
|
282
|
+
siteName: string,
|
|
283
|
+
id: string,
|
|
284
|
+
csrfToken?: string
|
|
285
|
+
): Promise<ApiResponse<{ success: boolean; message: string }>> {
|
|
286
|
+
return this.create<Record<string, never>, { success: boolean; message: string }>(
|
|
287
|
+
this.siteUserEndpoint(siteName, `/users/me/subscriptions/${encodeURIComponent(id)}/cancel`),
|
|
288
|
+
{},
|
|
289
|
+
csrfToken
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Get linked newsletter subscriptions
|
|
295
|
+
* @param siteName - The site name
|
|
296
|
+
*/
|
|
297
|
+
async getNewsletterSubscriptions(siteName: string): Promise<ApiResponse<{ newsletters: any[] }>> {
|
|
298
|
+
return this.getSingle<{ newsletters: any[] }>(
|
|
299
|
+
this.siteUserEndpoint(siteName, '/users/me/newsletters')
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ============================================================================
|
|
304
|
+
// ADMIN ENDPOINTS (API key auth required)
|
|
305
|
+
// ============================================================================
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* List all site users (admin only)
|
|
309
|
+
* @param siteName - The site name
|
|
310
|
+
* @param params - Query params (limit, offset, status)
|
|
311
|
+
*/
|
|
312
|
+
async listUsers(
|
|
313
|
+
siteName: string,
|
|
314
|
+
params?: { limit?: number; offset?: number; status?: string }
|
|
315
|
+
): Promise<ApiResponse<{ users: SiteUser[] }>> {
|
|
316
|
+
return this.http.get<{ users: SiteUser[] }>(
|
|
317
|
+
this.buildPath(this.siteUserEndpoint(siteName, '/users')),
|
|
318
|
+
params
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Get user detail (admin only)
|
|
324
|
+
* @param siteName - The site name
|
|
325
|
+
* @param userId - User ID
|
|
326
|
+
*/
|
|
327
|
+
async getUser(siteName: string, userId: string): Promise<ApiResponse<{ user: SiteUser; profile: SiteUserProfile }>> {
|
|
328
|
+
return this.getSingle<{ user: SiteUser; profile: SiteUserProfile }>(
|
|
329
|
+
this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}`)
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Update user status (admin only)
|
|
335
|
+
* @param siteName - The site name
|
|
336
|
+
* @param userId - User ID
|
|
337
|
+
* @param status - New status
|
|
338
|
+
* @param csrfToken - CSRF token (required)
|
|
339
|
+
*/
|
|
340
|
+
async updateUserStatus(
|
|
341
|
+
siteName: string,
|
|
342
|
+
userId: string,
|
|
343
|
+
status: 'active' | 'suspended' | 'pending_verification',
|
|
344
|
+
csrfToken?: string
|
|
345
|
+
): Promise<ApiResponse<{ success: boolean }>> {
|
|
346
|
+
return this.patch<{ status: string }, { success: boolean }>(
|
|
347
|
+
this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/status`),
|
|
348
|
+
{ status },
|
|
349
|
+
csrfToken
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ export { WebhooksClient } from './client/webhooks-client';
|
|
|
19
19
|
export { CheckoutClient } from './client/checkout-client';
|
|
20
20
|
export { ContactClient } from './client/contact-client';
|
|
21
21
|
export { NewsletterClient } from './client/newsletter-client';
|
|
22
|
+
export { SiteUsersClient } from './client/site-users-client';
|
|
22
23
|
|
|
23
24
|
// Base classes
|
|
24
25
|
export { BaseClient } from './client/base-client';
|
|
@@ -106,4 +107,13 @@ export type {
|
|
|
106
107
|
NewsletterUnsubscribeResponse,
|
|
107
108
|
ContactSubmitResponse,
|
|
108
109
|
ContactStatusResponse,
|
|
110
|
+
SiteUser,
|
|
111
|
+
SiteUserProfile,
|
|
112
|
+
SiteUserSubscription,
|
|
113
|
+
SiteUserOrder,
|
|
114
|
+
RequestOtpRequest,
|
|
115
|
+
VerifyOtpRequest,
|
|
116
|
+
VerifyOtpResponse,
|
|
117
|
+
UpdateSiteUserRequest,
|
|
118
|
+
SetProfileValueRequest,
|
|
109
119
|
} from './types';
|
|
@@ -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 { SiteUsersClient } from './client/site-users-client';
|
|
19
20
|
|
|
20
21
|
import type { PerspectApiConfig, ApiResponse } from './types';
|
|
21
22
|
|
|
@@ -35,6 +36,7 @@ export class PerspectApiClient {
|
|
|
35
36
|
public readonly checkout: CheckoutClient;
|
|
36
37
|
public readonly contact: ContactClient;
|
|
37
38
|
public readonly newsletter: NewsletterClient;
|
|
39
|
+
public readonly siteUsers: SiteUsersClient;
|
|
38
40
|
|
|
39
41
|
constructor(config: PerspectApiConfig) {
|
|
40
42
|
// Validate required configuration
|
|
@@ -58,6 +60,7 @@ export class PerspectApiClient {
|
|
|
58
60
|
this.checkout = new CheckoutClient(this.http, this.cache);
|
|
59
61
|
this.contact = new ContactClient(this.http, this.cache);
|
|
60
62
|
this.newsletter = new NewsletterClient(this.http, this.cache);
|
|
63
|
+
this.siteUsers = new SiteUsersClient(this.http, this.cache);
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
/**
|
package/src/types/index.ts
CHANGED
|
@@ -214,7 +214,7 @@ export interface NewsletterUnsubscribeResponse {
|
|
|
214
214
|
|
|
215
215
|
// Content Management
|
|
216
216
|
export type ContentStatus = 'draft' | 'publish' | 'private' | 'trash';
|
|
217
|
-
export type ContentType = 'post' | 'page';
|
|
217
|
+
export type ContentType = 'post' | 'page' | 'block';
|
|
218
218
|
|
|
219
219
|
export interface Content {
|
|
220
220
|
id: number;
|
|
@@ -579,6 +579,95 @@ export interface ContactStatusResponse {
|
|
|
579
579
|
metadata?: Record<string, any>;
|
|
580
580
|
}
|
|
581
581
|
|
|
582
|
+
// Site Users (customer accounts)
|
|
583
|
+
export interface SiteUser {
|
|
584
|
+
id: string;
|
|
585
|
+
email: string;
|
|
586
|
+
first_name?: string;
|
|
587
|
+
last_name?: string;
|
|
588
|
+
avatar_url?: string;
|
|
589
|
+
status: 'active' | 'suspended' | 'pending_verification';
|
|
590
|
+
email_verified: boolean;
|
|
591
|
+
waitlist: boolean;
|
|
592
|
+
metadata?: Record<string, any>;
|
|
593
|
+
created_at: string;
|
|
594
|
+
last_login_at?: string;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
export interface SiteUserProfile {
|
|
598
|
+
[key: string]: {
|
|
599
|
+
value: any;
|
|
600
|
+
updated_at: string;
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export interface SiteUserSubscription {
|
|
605
|
+
id: string;
|
|
606
|
+
provider: string;
|
|
607
|
+
provider_subscription_id?: string;
|
|
608
|
+
plan_name?: string;
|
|
609
|
+
plan_id?: string;
|
|
610
|
+
status: 'active' | 'past_due' | 'canceled' | 'paused' | 'trialing' | 'expired';
|
|
611
|
+
amount?: number;
|
|
612
|
+
currency?: string;
|
|
613
|
+
billing_interval?: string;
|
|
614
|
+
billing_interval_count?: number;
|
|
615
|
+
current_period_start?: string;
|
|
616
|
+
current_period_end?: string;
|
|
617
|
+
trial_start?: string;
|
|
618
|
+
trial_end?: string;
|
|
619
|
+
canceled_at?: string;
|
|
620
|
+
cancel_at_period_end: boolean;
|
|
621
|
+
created_at: string;
|
|
622
|
+
updated_at: string;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export interface SiteUserOrder {
|
|
626
|
+
session_id: string;
|
|
627
|
+
order_id?: string;
|
|
628
|
+
customer_email?: string;
|
|
629
|
+
amount_total: number;
|
|
630
|
+
currency: string;
|
|
631
|
+
status: string;
|
|
632
|
+
payment_status?: string;
|
|
633
|
+
line_items: any[];
|
|
634
|
+
created_at: string;
|
|
635
|
+
updated_at: string;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export interface RequestOtpRequest {
|
|
639
|
+
email: string;
|
|
640
|
+
waitlist?: boolean; // Mark user as waitlist signup
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
export interface VerifyOtpRequest {
|
|
644
|
+
email: string;
|
|
645
|
+
code: string;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
export interface VerifyOtpResponse {
|
|
649
|
+
success: boolean;
|
|
650
|
+
token: string; // JWT token for cross-domain authentication
|
|
651
|
+
user: {
|
|
652
|
+
id: string;
|
|
653
|
+
email: string;
|
|
654
|
+
first_name?: string;
|
|
655
|
+
last_name?: string;
|
|
656
|
+
avatar_url?: string;
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export interface UpdateSiteUserRequest {
|
|
661
|
+
first_name?: string;
|
|
662
|
+
last_name?: string;
|
|
663
|
+
avatar_url?: string;
|
|
664
|
+
metadata?: Record<string, any>;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
export interface SetProfileValueRequest {
|
|
668
|
+
value: string;
|
|
669
|
+
}
|
|
670
|
+
|
|
582
671
|
// Error Types
|
|
583
672
|
export interface ApiError {
|
|
584
673
|
message: string;
|
package/src/utils/validators.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ContentType } from '../types';
|
|
2
2
|
|
|
3
3
|
export const MAX_API_QUERY_LIMIT = 100;
|
|
4
|
-
const ALLOWED_CONTENT_TYPES: ReadonlyArray<ContentType> = ['post', 'page'];
|
|
4
|
+
const ALLOWED_CONTENT_TYPES: ReadonlyArray<ContentType> = ['post', 'page', 'block'];
|
|
5
5
|
|
|
6
6
|
export function validateLimit(limit: number, context: string): number {
|
|
7
7
|
if (typeof limit !== 'number' || Number.isNaN(limit) || !Number.isFinite(limit)) {
|
|
@@ -50,4 +50,3 @@ export function validateOptionalContentType(
|
|
|
50
50
|
)}.`,
|
|
51
51
|
);
|
|
52
52
|
}
|
|
53
|
-
|