perspectapi-ts-sdk 1.1.1
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/LICENSE +21 -0
- package/README.md +515 -0
- package/dist/index.d.mts +1770 -0
- package/dist/index.d.ts +1770 -0
- package/dist/index.js +1777 -0
- package/dist/index.mjs +1727 -0
- package/package.json +69 -0
- package/src/client/api-keys-client.ts +103 -0
- package/src/client/auth-client.ts +87 -0
- package/src/client/base-client.ts +100 -0
- package/src/client/categories-client.ts +151 -0
- package/src/client/checkout-client.ts +249 -0
- package/src/client/contact-client.ts +203 -0
- package/src/client/content-client.ts +112 -0
- package/src/client/organizations-client.ts +106 -0
- package/src/client/products-client.ts +247 -0
- package/src/client/sites-client.ts +148 -0
- package/src/client/webhooks-client.ts +199 -0
- package/src/index.ts +74 -0
- package/src/loaders.ts +644 -0
- package/src/perspect-api-client.ts +179 -0
- package/src/types/index.ts +399 -0
- package/src/utils/http-client.ts +268 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checkout/Stripe client for PerspectAPI SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BaseClient } from './base-client';
|
|
6
|
+
import type {
|
|
7
|
+
CreateCheckoutSessionRequest,
|
|
8
|
+
CheckoutSession,
|
|
9
|
+
ApiResponse,
|
|
10
|
+
} from '../types';
|
|
11
|
+
|
|
12
|
+
export class CheckoutClient extends BaseClient {
|
|
13
|
+
constructor(http: any) {
|
|
14
|
+
super(http, '/api/v1');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get CSRF token for a specific site
|
|
19
|
+
* @param siteName - The site name to get CSRF token for
|
|
20
|
+
*/
|
|
21
|
+
async getCsrfToken(siteName: string): Promise<ApiResponse<{
|
|
22
|
+
csrf_token: string;
|
|
23
|
+
site_id: string;
|
|
24
|
+
site_name: string;
|
|
25
|
+
}>> {
|
|
26
|
+
return this.http.get(`/api/v1/csrf/token/${siteName}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create Stripe checkout session with CSRF protection
|
|
31
|
+
* @param siteName - The site name for the checkout session
|
|
32
|
+
* @param data - Checkout session data (can include priceId for single item or line_items for multiple)
|
|
33
|
+
* @param csrfToken - Optional CSRF token (if not provided, will fetch automatically)
|
|
34
|
+
*/
|
|
35
|
+
async createCheckoutSession(
|
|
36
|
+
siteName: string,
|
|
37
|
+
data: CreateCheckoutSessionRequest,
|
|
38
|
+
csrfToken?: string
|
|
39
|
+
): Promise<ApiResponse<CheckoutSession>> {
|
|
40
|
+
// If no CSRF token provided, fetch it first
|
|
41
|
+
let token = csrfToken;
|
|
42
|
+
if (!token) {
|
|
43
|
+
const csrfResponse = await this.getCsrfToken(siteName);
|
|
44
|
+
const csrfToken = csrfResponse.data?.csrf_token;
|
|
45
|
+
|
|
46
|
+
if (!csrfToken) {
|
|
47
|
+
throw new Error('Failed to obtain CSRF token');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
token = csrfToken;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Make the checkout request with CSRF token in headers
|
|
54
|
+
return this.http.request(this.buildPath(
|
|
55
|
+
this.siteScopedEndpoint(siteName, '/checkout/create-session')
|
|
56
|
+
), {
|
|
57
|
+
method: 'POST',
|
|
58
|
+
body: data,
|
|
59
|
+
headers: {
|
|
60
|
+
'X-CSRF-Token': token
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get checkout session by ID
|
|
67
|
+
*/
|
|
68
|
+
async getCheckoutSession(sessionId: string): Promise<ApiResponse<{
|
|
69
|
+
id: string;
|
|
70
|
+
status: string;
|
|
71
|
+
paymentStatus: string;
|
|
72
|
+
customerEmail?: string;
|
|
73
|
+
amountTotal: number;
|
|
74
|
+
currency: string;
|
|
75
|
+
metadata?: Record<string, string>;
|
|
76
|
+
createdAt: string;
|
|
77
|
+
expiresAt: string;
|
|
78
|
+
}>> {
|
|
79
|
+
return this.getSingle(`/checkout/sessions/${sessionId}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get checkout sessions for organization
|
|
84
|
+
*/
|
|
85
|
+
async getCheckoutSessions(params?: {
|
|
86
|
+
page?: number;
|
|
87
|
+
limit?: number;
|
|
88
|
+
status?: string;
|
|
89
|
+
customerEmail?: string;
|
|
90
|
+
startDate?: string;
|
|
91
|
+
endDate?: string;
|
|
92
|
+
}): Promise<ApiResponse<Array<{
|
|
93
|
+
id: string;
|
|
94
|
+
status: string;
|
|
95
|
+
paymentStatus: string;
|
|
96
|
+
customerEmail?: string;
|
|
97
|
+
amountTotal: number;
|
|
98
|
+
currency: string;
|
|
99
|
+
createdAt: string;
|
|
100
|
+
}>>> {
|
|
101
|
+
return this.getPaginated('/checkout/sessions', params);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Cancel checkout session
|
|
106
|
+
*/
|
|
107
|
+
async cancelCheckoutSession(sessionId: string): Promise<ApiResponse<{
|
|
108
|
+
success: boolean;
|
|
109
|
+
message: string;
|
|
110
|
+
}>> {
|
|
111
|
+
return this.create(`/checkout/sessions/${sessionId}/cancel`, {});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Expire checkout session
|
|
116
|
+
*/
|
|
117
|
+
async expireCheckoutSession(sessionId: string): Promise<ApiResponse<{
|
|
118
|
+
success: boolean;
|
|
119
|
+
message: string;
|
|
120
|
+
}>> {
|
|
121
|
+
return this.create(`/checkout/sessions/${sessionId}/expire`, {});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get Stripe publishable key
|
|
126
|
+
*/
|
|
127
|
+
async getStripePublishableKey(): Promise<ApiResponse<{
|
|
128
|
+
publishableKey: string;
|
|
129
|
+
mode: 'test' | 'live';
|
|
130
|
+
}>> {
|
|
131
|
+
return this.getSingle('/checkout/stripe/config');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Create payment intent (for custom checkout flows)
|
|
136
|
+
*/
|
|
137
|
+
async createPaymentIntent(data: {
|
|
138
|
+
amount: number;
|
|
139
|
+
currency: string;
|
|
140
|
+
customerEmail?: string;
|
|
141
|
+
metadata?: Record<string, string>;
|
|
142
|
+
paymentMethodTypes?: string[];
|
|
143
|
+
}): Promise<ApiResponse<{
|
|
144
|
+
clientSecret: string;
|
|
145
|
+
id: string;
|
|
146
|
+
status: string;
|
|
147
|
+
}>> {
|
|
148
|
+
return this.create('/checkout/payment-intent', data);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Confirm payment intent
|
|
153
|
+
*/
|
|
154
|
+
async confirmPaymentIntent(paymentIntentId: string, data: {
|
|
155
|
+
paymentMethodId: string;
|
|
156
|
+
returnUrl?: string;
|
|
157
|
+
}): Promise<ApiResponse<{
|
|
158
|
+
success: boolean;
|
|
159
|
+
status: string;
|
|
160
|
+
nextAction?: any;
|
|
161
|
+
}>> {
|
|
162
|
+
return this.create(`/checkout/payment-intent/${paymentIntentId}/confirm`, data);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get payment methods for customer
|
|
167
|
+
*/
|
|
168
|
+
async getPaymentMethods(customerId: string): Promise<ApiResponse<Array<{
|
|
169
|
+
id: string;
|
|
170
|
+
type: string;
|
|
171
|
+
card?: {
|
|
172
|
+
brand: string;
|
|
173
|
+
last4: string;
|
|
174
|
+
expMonth: number;
|
|
175
|
+
expYear: number;
|
|
176
|
+
};
|
|
177
|
+
createdAt: string;
|
|
178
|
+
}>>> {
|
|
179
|
+
return this.getSingle(`/checkout/customers/${customerId}/payment-methods`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Create customer
|
|
184
|
+
*/
|
|
185
|
+
async createCustomer(data: {
|
|
186
|
+
email: string;
|
|
187
|
+
name?: string;
|
|
188
|
+
phone?: string;
|
|
189
|
+
metadata?: Record<string, string>;
|
|
190
|
+
}): Promise<ApiResponse<{
|
|
191
|
+
id: string;
|
|
192
|
+
email: string;
|
|
193
|
+
name?: string;
|
|
194
|
+
createdAt: string;
|
|
195
|
+
}>> {
|
|
196
|
+
return this.create('/checkout/customers', data);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get customer by ID
|
|
201
|
+
*/
|
|
202
|
+
async getCustomer(customerId: string): Promise<ApiResponse<{
|
|
203
|
+
id: string;
|
|
204
|
+
email: string;
|
|
205
|
+
name?: string;
|
|
206
|
+
phone?: string;
|
|
207
|
+
metadata?: Record<string, string>;
|
|
208
|
+
createdAt: string;
|
|
209
|
+
}>> {
|
|
210
|
+
return this.getSingle(`/checkout/customers/${customerId}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Update customer
|
|
215
|
+
*/
|
|
216
|
+
async updateCustomer(customerId: string, data: {
|
|
217
|
+
email?: string;
|
|
218
|
+
name?: string;
|
|
219
|
+
phone?: string;
|
|
220
|
+
metadata?: Record<string, string>;
|
|
221
|
+
}): Promise<ApiResponse<{
|
|
222
|
+
id: string;
|
|
223
|
+
email: string;
|
|
224
|
+
name?: string;
|
|
225
|
+
updatedAt: string;
|
|
226
|
+
}>> {
|
|
227
|
+
return this.update(`/checkout/customers/${customerId}`, data);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Get invoices for customer
|
|
232
|
+
*/
|
|
233
|
+
async getCustomerInvoices(customerId: string, params?: {
|
|
234
|
+
page?: number;
|
|
235
|
+
limit?: number;
|
|
236
|
+
status?: string;
|
|
237
|
+
}): Promise<ApiResponse<Array<{
|
|
238
|
+
id: string;
|
|
239
|
+
number: string;
|
|
240
|
+
status: string;
|
|
241
|
+
amountPaid: number;
|
|
242
|
+
amountDue: number;
|
|
243
|
+
currency: string;
|
|
244
|
+
dueDate?: string;
|
|
245
|
+
createdAt: string;
|
|
246
|
+
}>>> {
|
|
247
|
+
return this.getPaginated(`/checkout/customers/${customerId}/invoices`, params);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contact Forms client for PerspectAPI SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BaseClient } from './base-client';
|
|
6
|
+
import type {
|
|
7
|
+
ContactSubmission,
|
|
8
|
+
CreateContactRequest,
|
|
9
|
+
PaginatedResponse,
|
|
10
|
+
ApiResponse,
|
|
11
|
+
} from '../types';
|
|
12
|
+
|
|
13
|
+
export class ContactClient extends BaseClient {
|
|
14
|
+
constructor(http: any) {
|
|
15
|
+
super(http, '/api/v1');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Build a contact endpoint scoped to a site (without /sites prefix)
|
|
20
|
+
*/
|
|
21
|
+
private contactEndpoint(siteName: string, endpoint: string): string {
|
|
22
|
+
return this.siteScopedEndpoint(siteName, endpoint, { includeSitesSegment: false });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Submit contact form
|
|
27
|
+
*/
|
|
28
|
+
async submitContact(siteName: string, data: CreateContactRequest): Promise<ApiResponse<{
|
|
29
|
+
id: string;
|
|
30
|
+
message: string;
|
|
31
|
+
status: string;
|
|
32
|
+
}>> {
|
|
33
|
+
return this.create<CreateContactRequest, {
|
|
34
|
+
id: string;
|
|
35
|
+
message: string;
|
|
36
|
+
status: string;
|
|
37
|
+
}>(this.contactEndpoint(siteName, '/contact/submit'), data);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get contact submission status
|
|
42
|
+
*/
|
|
43
|
+
async getContactStatus(siteName: string, id: string): Promise<ApiResponse<{
|
|
44
|
+
id: string;
|
|
45
|
+
status: string;
|
|
46
|
+
submittedAt: string;
|
|
47
|
+
processedAt?: string;
|
|
48
|
+
}>> {
|
|
49
|
+
return this.getSingle(this.contactEndpoint(siteName, `/contact/status/${encodeURIComponent(id)}`));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get all contact submissions (admin only)
|
|
54
|
+
*/
|
|
55
|
+
async getContactSubmissions(siteName: string, params?: {
|
|
56
|
+
page?: number;
|
|
57
|
+
limit?: number;
|
|
58
|
+
status?: string;
|
|
59
|
+
startDate?: string;
|
|
60
|
+
endDate?: string;
|
|
61
|
+
search?: string;
|
|
62
|
+
}): Promise<PaginatedResponse<ContactSubmission>> {
|
|
63
|
+
return this.getPaginated<ContactSubmission>(this.contactEndpoint(siteName, '/contact/list'), params);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get contact submission by ID (admin only)
|
|
68
|
+
*/
|
|
69
|
+
async getContactSubmissionById(siteName: string, id: string): Promise<ApiResponse<ContactSubmission & {
|
|
70
|
+
ipAddress?: string;
|
|
71
|
+
userAgent?: string;
|
|
72
|
+
metadata?: Record<string, any>;
|
|
73
|
+
}>> {
|
|
74
|
+
return this.getSingle(this.contactEndpoint(siteName, `/contact/${encodeURIComponent(id)}`));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Update contact submission status (admin only)
|
|
79
|
+
*/
|
|
80
|
+
async updateContactStatus(siteName: string, id: string, status: string, notes?: string): Promise<ApiResponse<{
|
|
81
|
+
message: string;
|
|
82
|
+
status: string;
|
|
83
|
+
}>> {
|
|
84
|
+
return this.patch(this.contactEndpoint(siteName, `/contact/${encodeURIComponent(id)}`), { status, notes });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Mark contact as read (admin only)
|
|
89
|
+
*/
|
|
90
|
+
async markContactAsRead(siteName: string, id: string): Promise<ApiResponse<{ message: string }>> {
|
|
91
|
+
return this.patch(this.contactEndpoint(siteName, `/contact/${encodeURIComponent(id)}`), { status: 'read' });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Mark contact as unread (admin only)
|
|
96
|
+
*/
|
|
97
|
+
async markContactAsUnread(siteName: string, id: string): Promise<ApiResponse<{ message: string }>> {
|
|
98
|
+
return this.patch(this.contactEndpoint(siteName, `/contact/${encodeURIComponent(id)}`), { status: 'unread' });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Archive contact submission (admin only)
|
|
103
|
+
*/
|
|
104
|
+
async archiveContact(siteName: string, id: string): Promise<ApiResponse<{ message: string }>> {
|
|
105
|
+
return this.patch(this.contactEndpoint(siteName, `/contact/${encodeURIComponent(id)}`), { status: 'archived' });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Delete contact submission (admin only)
|
|
110
|
+
*/
|
|
111
|
+
async deleteContact(siteName: string, id: string): Promise<ApiResponse<{ message: string }>> {
|
|
112
|
+
return this.delete<{ message: string }>(this.contactEndpoint(siteName, `/contact/${encodeURIComponent(id)}`));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Bulk update contact submissions (admin only)
|
|
117
|
+
*/
|
|
118
|
+
async bulkUpdateContacts(siteName: string, data: {
|
|
119
|
+
ids: string[];
|
|
120
|
+
status?: string;
|
|
121
|
+
action: 'mark_read' | 'mark_unread' | 'archive' | 'delete';
|
|
122
|
+
}): Promise<ApiResponse<{
|
|
123
|
+
success: boolean;
|
|
124
|
+
updatedCount: number;
|
|
125
|
+
failedCount: number;
|
|
126
|
+
}>> {
|
|
127
|
+
return this.create(this.contactEndpoint(siteName, '/contact/bulk-update'), data);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get contact form statistics (admin only)
|
|
132
|
+
*/
|
|
133
|
+
async getContactStats(siteName: string, params?: {
|
|
134
|
+
startDate?: string;
|
|
135
|
+
endDate?: string;
|
|
136
|
+
}): Promise<ApiResponse<{
|
|
137
|
+
totalSubmissions: number;
|
|
138
|
+
unreadSubmissions: number;
|
|
139
|
+
readSubmissions: number;
|
|
140
|
+
archivedSubmissions: number;
|
|
141
|
+
submissionsByDay: Array<{
|
|
142
|
+
date: string;
|
|
143
|
+
count: number;
|
|
144
|
+
}>;
|
|
145
|
+
submissionsByStatus: Record<string, number>;
|
|
146
|
+
averageResponseTime?: number;
|
|
147
|
+
}>> {
|
|
148
|
+
return this.http.get(this.buildPath(this.contactEndpoint(siteName, '/contact/stats')), params);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Export contact submissions (admin only)
|
|
153
|
+
*/
|
|
154
|
+
async exportContacts(siteName: string, params?: {
|
|
155
|
+
format?: 'csv' | 'json' | 'xlsx';
|
|
156
|
+
startDate?: string;
|
|
157
|
+
endDate?: string;
|
|
158
|
+
status?: string;
|
|
159
|
+
}): Promise<ApiResponse<{
|
|
160
|
+
downloadUrl: string;
|
|
161
|
+
expiresAt: string;
|
|
162
|
+
}>> {
|
|
163
|
+
return this.create(this.contactEndpoint(siteName, '/contact/export'), params || {});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get contact form configuration
|
|
168
|
+
*/
|
|
169
|
+
async getContactConfig(siteName: string): Promise<ApiResponse<{
|
|
170
|
+
turnstileEnabled: boolean;
|
|
171
|
+
rateLimitEnabled: boolean;
|
|
172
|
+
rateLimitWindow: number;
|
|
173
|
+
rateLimitMax: number;
|
|
174
|
+
requiredFields: string[];
|
|
175
|
+
customFields?: Array<{
|
|
176
|
+
name: string;
|
|
177
|
+
type: string;
|
|
178
|
+
required: boolean;
|
|
179
|
+
label: string;
|
|
180
|
+
}>;
|
|
181
|
+
}>> {
|
|
182
|
+
return this.getSingle(this.contactEndpoint(siteName, '/contact/config'));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Update contact form configuration (admin only)
|
|
187
|
+
*/
|
|
188
|
+
async updateContactConfig(siteName: string, data: {
|
|
189
|
+
turnstileEnabled?: boolean;
|
|
190
|
+
rateLimitEnabled?: boolean;
|
|
191
|
+
rateLimitWindow?: number;
|
|
192
|
+
rateLimitMax?: number;
|
|
193
|
+
requiredFields?: string[];
|
|
194
|
+
customFields?: Array<{
|
|
195
|
+
name: string;
|
|
196
|
+
type: string;
|
|
197
|
+
required: boolean;
|
|
198
|
+
label: string;
|
|
199
|
+
}>;
|
|
200
|
+
}): Promise<ApiResponse<{ message: string }>> {
|
|
201
|
+
return this.update(this.contactEndpoint(siteName, '/contact/config'), data);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content Management client for PerspectAPI SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BaseClient } from './base-client';
|
|
6
|
+
import type {
|
|
7
|
+
Content,
|
|
8
|
+
CreateContentRequest,
|
|
9
|
+
UpdateContentRequest,
|
|
10
|
+
ContentQueryParams,
|
|
11
|
+
PaginatedResponse,
|
|
12
|
+
ApiResponse,
|
|
13
|
+
} from '../types';
|
|
14
|
+
|
|
15
|
+
export class ContentClient extends BaseClient {
|
|
16
|
+
constructor(http: any) {
|
|
17
|
+
super(http, '/api/v1');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get all content with pagination and filtering for a site
|
|
22
|
+
*/
|
|
23
|
+
async getContent(siteName: string, params?: ContentQueryParams): Promise<PaginatedResponse<Content>> {
|
|
24
|
+
return this.http.get(this.buildPath(this.siteScopedEndpoint(siteName)), params);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get content by ID
|
|
29
|
+
*/
|
|
30
|
+
async getContentById(id: number): Promise<ApiResponse<Content>> {
|
|
31
|
+
return this.getSingle<Content>(`/content/${id}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get content by slug for a site
|
|
36
|
+
*/
|
|
37
|
+
async getContentBySlug(siteName: string, slug: string): Promise<ApiResponse<Content>> {
|
|
38
|
+
return this.http.get(this.buildPath(
|
|
39
|
+
this.siteScopedEndpoint(siteName, `/slug/${encodeURIComponent(slug)}`)
|
|
40
|
+
));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create new content
|
|
45
|
+
*/
|
|
46
|
+
async createContent(data: CreateContentRequest): Promise<ApiResponse<Content>> {
|
|
47
|
+
return this.create<CreateContentRequest, Content>('/content', data);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Update content
|
|
52
|
+
*/
|
|
53
|
+
async updateContent(id: number, data: UpdateContentRequest): Promise<ApiResponse<Content>> {
|
|
54
|
+
return this.update<UpdateContentRequest, Content>(`/content/${id}`, data);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Partially update content
|
|
59
|
+
*/
|
|
60
|
+
async patchContent(id: number, data: Partial<UpdateContentRequest>): Promise<ApiResponse<Content>> {
|
|
61
|
+
return this.patch<Partial<UpdateContentRequest>, Content>(`/content/${id}`, data);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Delete content
|
|
66
|
+
*/
|
|
67
|
+
async deleteContent(id: number): Promise<ApiResponse<{ message: string }>> {
|
|
68
|
+
return this.delete<{ message: string }>(`/content/${id}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Publish content
|
|
73
|
+
*/
|
|
74
|
+
async publishContent(id: number): Promise<ApiResponse<Content>> {
|
|
75
|
+
return this.create<{ action: string }, Content>(`/content/${id}/publish`, { action: 'publish' });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Unpublish content
|
|
80
|
+
*/
|
|
81
|
+
async unpublishContent(id: number): Promise<ApiResponse<Content>> {
|
|
82
|
+
return this.create<{ action: string }, Content>(`/content/${id}/publish`, { action: 'unpublish' });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Move content to trash
|
|
87
|
+
*/
|
|
88
|
+
async trashContent(id: number): Promise<ApiResponse<Content>> {
|
|
89
|
+
return this.create<{ action: string }, Content>(`/content/${id}/publish`, { action: 'trash' });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Restore content from trash
|
|
94
|
+
*/
|
|
95
|
+
async restoreContent(id: number): Promise<ApiResponse<Content>> {
|
|
96
|
+
return this.create<{ action: string }, Content>(`/content/${id}/publish`, { action: 'restore' });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get content revisions
|
|
101
|
+
*/
|
|
102
|
+
async getContentRevisions(id: number): Promise<ApiResponse<Content[]>> {
|
|
103
|
+
return this.getSingle<Content[]>(`/content/${id}/revisions`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Duplicate content
|
|
108
|
+
*/
|
|
109
|
+
async duplicateContent(id: number): Promise<ApiResponse<Content>> {
|
|
110
|
+
return this.create<Record<string, never>, Content>(`/content/${id}/duplicate`, {});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organizations Management client for PerspectAPI SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BaseClient } from './base-client';
|
|
6
|
+
import type {
|
|
7
|
+
Organization,
|
|
8
|
+
CreateOrganizationRequest,
|
|
9
|
+
PaginatedResponse,
|
|
10
|
+
ApiResponse,
|
|
11
|
+
} from '../types';
|
|
12
|
+
|
|
13
|
+
export class OrganizationsClient extends BaseClient {
|
|
14
|
+
constructor(http: any) {
|
|
15
|
+
super(http, '/api/v1');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get all organizations
|
|
20
|
+
*/
|
|
21
|
+
async getOrganizations(params?: { page?: number; limit?: number }): Promise<PaginatedResponse<Organization>> {
|
|
22
|
+
return this.getPaginated<Organization>('/organizations', params);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get organization by ID
|
|
27
|
+
*/
|
|
28
|
+
async getOrganizationById(id: number): Promise<ApiResponse<Organization>> {
|
|
29
|
+
return this.getSingle<Organization>(`/organizations/${id}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create new organization
|
|
34
|
+
*/
|
|
35
|
+
async createOrganization(data: CreateOrganizationRequest): Promise<ApiResponse<Organization>> {
|
|
36
|
+
return this.create<CreateOrganizationRequest, Organization>('/organizations', data);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Update organization
|
|
41
|
+
*/
|
|
42
|
+
async updateOrganization(id: number, data: Partial<CreateOrganizationRequest>): Promise<ApiResponse<Organization>> {
|
|
43
|
+
return this.update<Partial<CreateOrganizationRequest>, Organization>(`/organizations/${id}`, data);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Delete organization
|
|
48
|
+
*/
|
|
49
|
+
async deleteOrganization(id: number): Promise<ApiResponse<{ message: string }>> {
|
|
50
|
+
return this.delete<{ message: string }>(`/organizations/${id}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get organization members
|
|
55
|
+
*/
|
|
56
|
+
async getOrganizationMembers(id: number): Promise<ApiResponse<Array<{
|
|
57
|
+
id: string;
|
|
58
|
+
email: string;
|
|
59
|
+
firstName?: string;
|
|
60
|
+
lastName?: string;
|
|
61
|
+
role: string;
|
|
62
|
+
joinedAt: string;
|
|
63
|
+
}>>> {
|
|
64
|
+
return this.getSingle(`/organizations/${id}/members`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Add member to organization
|
|
69
|
+
*/
|
|
70
|
+
async addOrganizationMember(id: number, data: {
|
|
71
|
+
email: string;
|
|
72
|
+
role: string;
|
|
73
|
+
}): Promise<ApiResponse<{ message: string }>> {
|
|
74
|
+
return this.create(`/organizations/${id}/members`, data);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Update organization member role
|
|
79
|
+
*/
|
|
80
|
+
async updateOrganizationMember(id: number, userId: string, data: {
|
|
81
|
+
role: string;
|
|
82
|
+
}): Promise<ApiResponse<{ message: string }>> {
|
|
83
|
+
return this.update(`/organizations/${id}/members/${userId}`, data);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Remove member from organization
|
|
88
|
+
*/
|
|
89
|
+
async removeOrganizationMember(id: number, userId: string): Promise<ApiResponse<{ message: string }>> {
|
|
90
|
+
return this.delete<{ message: string }>(`/organizations/${id}/members/${userId}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get organization settings
|
|
95
|
+
*/
|
|
96
|
+
async getOrganizationSettings(id: number): Promise<ApiResponse<Record<string, any>>> {
|
|
97
|
+
return this.getSingle<Record<string, any>>(`/organizations/${id}/settings`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Update organization settings
|
|
102
|
+
*/
|
|
103
|
+
async updateOrganizationSettings(id: number, settings: Record<string, any>): Promise<ApiResponse<Record<string, any>>> {
|
|
104
|
+
return this.update<Record<string, any>>(`/organizations/${id}/settings`, settings);
|
|
105
|
+
}
|
|
106
|
+
}
|