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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 PerspectAPI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
# PerspectAPI TypeScript SDK
|
|
2
|
+
|
|
3
|
+
A comprehensive TypeScript SDK for PerspectAPI, designed to work seamlessly with Cloudflare Workers and other JavaScript environments.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Cloudflare Workers Compatible** - Uses native fetch API, no Node.js dependencies
|
|
8
|
+
- 🔒 **Type Safe** - Full TypeScript support with comprehensive type definitions
|
|
9
|
+
- 🔄 **Automatic Retries** - Built-in retry logic with exponential backoff
|
|
10
|
+
- 🛡️ **Error Handling** - Structured error responses with detailed information
|
|
11
|
+
- 📦 **Modular Design** - Use individual clients or the complete SDK
|
|
12
|
+
- 🔑 **Multiple Auth Methods** - Support for JWT tokens and API keys
|
|
13
|
+
- 📊 **Comprehensive Coverage** - All PerspectAPI endpoints supported
|
|
14
|
+
- 🧩 **High-Level Loaders** - Drop-in helpers for products, content, and checkout flows with fallbacks
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install perspectapi-ts-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { createPerspectApiClient } from 'perspectapi-ts-sdk';
|
|
26
|
+
|
|
27
|
+
// Initialize with API key
|
|
28
|
+
const client = createPerspectApiClient({
|
|
29
|
+
baseUrl: 'https://your-perspectapi-instance.com',
|
|
30
|
+
apiKey: 'your-api-key'
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Or initialize with JWT token
|
|
34
|
+
const client = createPerspectApiClient({
|
|
35
|
+
baseUrl: 'https://your-perspectapi-instance.com',
|
|
36
|
+
jwt: 'your-jwt-token'
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Use the client
|
|
40
|
+
async function example() {
|
|
41
|
+
const siteName = 'your-site-name';
|
|
42
|
+
|
|
43
|
+
// Get all content
|
|
44
|
+
const content = await client.content.getContent(siteName);
|
|
45
|
+
console.log(content.data);
|
|
46
|
+
|
|
47
|
+
// Create new content
|
|
48
|
+
const newContent = await client.content.createContent({
|
|
49
|
+
page_title: 'Hello World',
|
|
50
|
+
page_content: 'This is my first post!',
|
|
51
|
+
page_status: 'publish',
|
|
52
|
+
page_type: 'post'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log(newContent.data);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
### High-Level Loaders (Quick Example)
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import {
|
|
62
|
+
loadProducts,
|
|
63
|
+
loadPosts,
|
|
64
|
+
createCheckoutSession
|
|
65
|
+
} from 'perspectapi-ts-sdk';
|
|
66
|
+
|
|
67
|
+
const loaders = {
|
|
68
|
+
client: createPerspectApiClient({ baseUrl, apiKey }),
|
|
69
|
+
siteName: 'my-museum-site'
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const products = await loadProducts(loaders);
|
|
73
|
+
const posts = await loadPosts(loaders);
|
|
74
|
+
|
|
75
|
+
const checkout = await createCheckoutSession({
|
|
76
|
+
...loaders,
|
|
77
|
+
items: [{ productId: products[0].id, quantity: 1 }],
|
|
78
|
+
successUrl: 'https://example.com/success',
|
|
79
|
+
cancelUrl: 'https://example.com/cancel'
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> 📚 See [docs/loaders.md](docs/loaders.md) for full walkthroughs, including fallback data, custom logging, and Stripe price resolution.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## High-Level Data Loaders
|
|
87
|
+
|
|
88
|
+
The SDK now ships with convenience loaders that wrap the lower-level REST clients. They help you:
|
|
89
|
+
|
|
90
|
+
- normalise products (including nested media arrays and Stripe IDs)
|
|
91
|
+
- search products server-side with limit/offset support and filter by category names or IDs (no hard-coded IDs)
|
|
92
|
+
- fetch published posts/pages with sensible defaults
|
|
93
|
+
- fall back to sample data when PerspectAPI is not configured (useful for local previews)
|
|
94
|
+
- create Stripe checkout sessions by automatically resolving price IDs
|
|
95
|
+
|
|
96
|
+
All loaders accept a shared `LoaderOptions` object:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import {
|
|
100
|
+
loadProducts,
|
|
101
|
+
loadProductBySlug,
|
|
102
|
+
loadPosts,
|
|
103
|
+
createCheckoutSession,
|
|
104
|
+
type LoaderOptions
|
|
105
|
+
} from 'perspectapi-ts-sdk';
|
|
106
|
+
|
|
107
|
+
const options: LoaderOptions = {
|
|
108
|
+
client: createPerspectApiClient({ baseUrl, apiKey }),
|
|
109
|
+
siteName: 'museum-indian-art',
|
|
110
|
+
logger: console, // optional
|
|
111
|
+
fallbackProducts: [], // optional
|
|
112
|
+
fallbackPosts: [] // optional
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const products = await loadProducts(options);
|
|
116
|
+
const single = await loadProductBySlug({ ...options, slug: 'sunset-painting' });
|
|
117
|
+
const posts = await loadPosts(options);
|
|
118
|
+
|
|
119
|
+
await createCheckoutSession({
|
|
120
|
+
...options,
|
|
121
|
+
items: [{ productId: products[0].id, quantity: 1 }],
|
|
122
|
+
successUrl: 'https://example.com/success',
|
|
123
|
+
cancelUrl: 'https://example.com/cancel'
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Filter products by multiple category names/IDs while combining search
|
|
127
|
+
const decorPillows = await loadProducts({
|
|
128
|
+
...options,
|
|
129
|
+
category: ['Home Decor', 'Seasonal Sale'],
|
|
130
|
+
categoryIds: [12],
|
|
131
|
+
search: 'pillow',
|
|
132
|
+
offset: 24,
|
|
133
|
+
limit: 12
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
> More real-world scenarios—including Cloudflare Workers, Remix/Next.js loaders, custom logger implementations, and checkout price resolution—are documented in [docs/loaders.md](docs/loaders.md).
|
|
138
|
+
|
|
139
|
+
## Authentication
|
|
140
|
+
|
|
141
|
+
### API Key Authentication
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const client = createPerspectApiClient({
|
|
145
|
+
baseUrl: 'https://api.example.com',
|
|
146
|
+
apiKey: 'pk_your_api_key_here'
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### JWT Token Authentication
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const client = createPerspectApiClient({
|
|
154
|
+
baseUrl: 'https://api.example.com',
|
|
155
|
+
jwt: 'your.jwt.token'
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Or authenticate after initialization
|
|
159
|
+
await client.auth.signIn({
|
|
160
|
+
email: 'user@example.com',
|
|
161
|
+
password: 'password'
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Dynamic Authentication
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const client = createPerspectApiClient({
|
|
169
|
+
baseUrl: 'https://api.example.com'
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Set authentication later
|
|
173
|
+
client.setApiKey('pk_your_api_key');
|
|
174
|
+
// or
|
|
175
|
+
client.setAuth('your.jwt.token');
|
|
176
|
+
|
|
177
|
+
// Clear authentication
|
|
178
|
+
client.clearAuth();
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## API Reference
|
|
182
|
+
|
|
183
|
+
### Content Management
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Get all content with pagination
|
|
187
|
+
const content = await client.content.getContent('your-site-name', {
|
|
188
|
+
page: 1,
|
|
189
|
+
limit: 20,
|
|
190
|
+
page_status: 'publish',
|
|
191
|
+
page_type: 'post'
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Get content by ID
|
|
195
|
+
const post = await client.content.getContentById(123);
|
|
196
|
+
|
|
197
|
+
// Get content by slug
|
|
198
|
+
const page = await client.content.getContentBySlug('your-site-name', 'about-us');
|
|
199
|
+
|
|
200
|
+
// Create new content
|
|
201
|
+
const newPost = await client.content.createContent({
|
|
202
|
+
page_title: 'My New Post',
|
|
203
|
+
page_content: '<p>Content goes here</p>',
|
|
204
|
+
content_markdown: '# My New Post\n\nContent goes here',
|
|
205
|
+
page_status: 'draft',
|
|
206
|
+
page_type: 'post',
|
|
207
|
+
slug: 'my-new-post'
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Update content
|
|
211
|
+
const updated = await client.content.updateContent(123, {
|
|
212
|
+
page_title: 'Updated Title',
|
|
213
|
+
page_status: 'publish'
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Delete content
|
|
217
|
+
await client.content.deleteContent(123);
|
|
218
|
+
|
|
219
|
+
// Publish/unpublish content
|
|
220
|
+
await client.content.publishContent(123);
|
|
221
|
+
await client.content.unpublishContent(123);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Products & E-commerce
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// Get all products
|
|
228
|
+
const products = await client.products.getProducts('my-site', {
|
|
229
|
+
page: 1,
|
|
230
|
+
limit: 20,
|
|
231
|
+
isActive: true
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Create new product
|
|
235
|
+
const product = await client.products.createProduct({
|
|
236
|
+
name: 'Amazing Product',
|
|
237
|
+
description: 'Product description',
|
|
238
|
+
price: 29.99,
|
|
239
|
+
currency: 'USD',
|
|
240
|
+
sku: 'PROD-001'
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Update product inventory
|
|
244
|
+
await client.products.updateProductInventory(123, {
|
|
245
|
+
quantity: 10,
|
|
246
|
+
operation: 'add',
|
|
247
|
+
reason: 'Restocked'
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Get product by slug and site name (NEW!)
|
|
251
|
+
const productBySlug = await client.products.getProductBySlug('my-site', 'awesome-laptop');
|
|
252
|
+
console.log('Product:', productBySlug.data?.name);
|
|
253
|
+
console.log('Variants:', productBySlug.data?.variants);
|
|
254
|
+
|
|
255
|
+
// Get products by category slug (NEW!)
|
|
256
|
+
const categoryProducts = await client.products.getProductsByCategorySlug(
|
|
257
|
+
'my-site',
|
|
258
|
+
'electronics',
|
|
259
|
+
{
|
|
260
|
+
page: 1,
|
|
261
|
+
limit: 20,
|
|
262
|
+
published: true,
|
|
263
|
+
search: 'phone'
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
console.log('Products:', categoryProducts.data?.data);
|
|
267
|
+
console.log('Category info:', categoryProducts.data?.category);
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Organizations & Sites
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// Get organizations
|
|
274
|
+
const orgs = await client.organizations.getOrganizations();
|
|
275
|
+
|
|
276
|
+
// Create new organization
|
|
277
|
+
const org = await client.organizations.createOrganization({
|
|
278
|
+
name: 'My Company',
|
|
279
|
+
description: 'Company description'
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Get sites
|
|
283
|
+
const sites = await client.sites.getSites({
|
|
284
|
+
organizationId: 1
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// Create new site
|
|
288
|
+
const site = await client.sites.createSite({
|
|
289
|
+
name: 'My Website',
|
|
290
|
+
domain: 'example.com',
|
|
291
|
+
organizationId: 1
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### API Key Management
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Get all API keys
|
|
299
|
+
const apiKeys = await client.apiKeys.getApiKeys();
|
|
300
|
+
|
|
301
|
+
// Create new API key
|
|
302
|
+
const newKey = await client.apiKeys.createApiKey({
|
|
303
|
+
name: 'Frontend App Key',
|
|
304
|
+
description: 'API key for frontend application',
|
|
305
|
+
permissions: ['content:read', 'products:read'],
|
|
306
|
+
expiresAt: '2024-12-31T23:59:59Z'
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
console.log('New API key:', newKey.data.key);
|
|
310
|
+
|
|
311
|
+
// Test API key validity
|
|
312
|
+
const testResult = await client.apiKeys.testApiKey('pk_test_key');
|
|
313
|
+
console.log('Key valid:', testResult.data.valid);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Webhooks
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// Get all webhooks
|
|
320
|
+
const webhooks = await client.webhooks.getWebhooks();
|
|
321
|
+
|
|
322
|
+
// Create new webhook
|
|
323
|
+
const webhook = await client.webhooks.createWebhook({
|
|
324
|
+
name: 'Order Notifications',
|
|
325
|
+
url: 'https://myapp.com/webhooks/orders',
|
|
326
|
+
provider: 'stripe',
|
|
327
|
+
events: ['payment_intent.succeeded', 'payment_intent.payment_failed'],
|
|
328
|
+
isActive: true
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// Test webhook
|
|
332
|
+
const testResult = await client.webhooks.testWebhook(webhook.data.id);
|
|
333
|
+
console.log('Webhook test:', testResult.data);
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Checkout & Payments
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
// Create Stripe checkout session
|
|
340
|
+
const session = await client.checkout.createCheckoutSession({
|
|
341
|
+
priceId: 'price_1234567890',
|
|
342
|
+
successUrl: 'https://myapp.com/success',
|
|
343
|
+
cancelUrl: 'https://myapp.com/cancel',
|
|
344
|
+
customerEmail: 'customer@example.com'
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Redirect user to checkout
|
|
348
|
+
window.location.href = session.data.url;
|
|
349
|
+
|
|
350
|
+
// Get checkout session status
|
|
351
|
+
const sessionStatus = await client.checkout.getCheckoutSession('cs_test_123');
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Contact Forms
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
const siteName = 'your-site-name';
|
|
358
|
+
|
|
359
|
+
// Submit contact form
|
|
360
|
+
const submission = await client.contact.submitContact(siteName, {
|
|
361
|
+
name: 'John Doe',
|
|
362
|
+
email: 'john@example.com',
|
|
363
|
+
subject: 'Question about pricing',
|
|
364
|
+
message: 'I have a question about your pricing plans.',
|
|
365
|
+
turnstileToken: 'turnstile-response-token'
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// Get contact submissions (admin only)
|
|
369
|
+
const submissions = await client.contact.getContactSubmissions(siteName, {
|
|
370
|
+
status: 'unread',
|
|
371
|
+
page: 1,
|
|
372
|
+
limit: 50
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// Update submission status
|
|
376
|
+
await client.contact.updateContactStatus(siteName, submission.data.id, 'read');
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## Configuration Options
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
interface PerspectApiConfig {
|
|
383
|
+
baseUrl: string; // Required: API base URL
|
|
384
|
+
apiKey?: string; // Optional: API key for authentication
|
|
385
|
+
jwt?: string; // Optional: JWT token for authentication
|
|
386
|
+
timeout?: number; // Optional: Request timeout in ms (default: 30000)
|
|
387
|
+
retries?: number; // Optional: Number of retries (default: 3)
|
|
388
|
+
headers?: Record<string, string>; // Optional: Additional headers
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## Error Handling
|
|
393
|
+
|
|
394
|
+
The SDK provides structured error handling:
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
import { createApiError } from 'perspectapi-ts-sdk';
|
|
398
|
+
|
|
399
|
+
try {
|
|
400
|
+
const content = await client.content.getContentById(999);
|
|
401
|
+
} catch (error) {
|
|
402
|
+
const apiError = createApiError(error);
|
|
403
|
+
|
|
404
|
+
console.log('Error message:', apiError.message);
|
|
405
|
+
console.log('Status code:', apiError.status);
|
|
406
|
+
console.log('Error code:', apiError.code);
|
|
407
|
+
console.log('Details:', apiError.details);
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
## Cloudflare Workers Usage
|
|
412
|
+
|
|
413
|
+
The SDK is fully compatible with Cloudflare Workers:
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
// worker.ts
|
|
417
|
+
import { createPerspectApiClient } from 'perspectapi-ts-sdk';
|
|
418
|
+
|
|
419
|
+
export default {
|
|
420
|
+
async fetch(request: Request, env: any): Promise<Response> {
|
|
421
|
+
const client = createPerspectApiClient({
|
|
422
|
+
baseUrl: env.PERSPECT_API_URL,
|
|
423
|
+
apiKey: env.PERSPECT_API_KEY
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
try {
|
|
427
|
+
const content = await client.content.getContent(env.PERSPECT_SITE_NAME, { limit: 10 });
|
|
428
|
+
|
|
429
|
+
return new Response(JSON.stringify(content.data), {
|
|
430
|
+
headers: { 'Content-Type': 'application/json' }
|
|
431
|
+
});
|
|
432
|
+
} catch (error) {
|
|
433
|
+
return new Response('Error fetching content', { status: 500 });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Advanced Usage
|
|
440
|
+
|
|
441
|
+
### Using Individual Clients
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import { HttpClient, ContentClient } from 'perspectapi-ts-sdk';
|
|
445
|
+
|
|
446
|
+
// Create HTTP client
|
|
447
|
+
const http = new HttpClient({
|
|
448
|
+
baseUrl: 'https://api.example.com',
|
|
449
|
+
apiKey: 'your-api-key'
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
// Use individual client
|
|
453
|
+
const contentClient = new ContentClient(http);
|
|
454
|
+
const content = await contentClient.getContent('your-site-name');
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Custom Headers
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
const client = createPerspectApiClient({
|
|
461
|
+
baseUrl: 'https://api.example.com',
|
|
462
|
+
apiKey: 'your-api-key',
|
|
463
|
+
headers: {
|
|
464
|
+
'X-Custom-Header': 'custom-value',
|
|
465
|
+
'User-Agent': 'MyApp/1.0.0'
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Timeout and Retries
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
const client = createPerspectApiClient({
|
|
474
|
+
baseUrl: 'https://api.example.com',
|
|
475
|
+
apiKey: 'your-api-key',
|
|
476
|
+
timeout: 60000, // 60 seconds
|
|
477
|
+
retries: 5 // Retry up to 5 times
|
|
478
|
+
});
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
## TypeScript Support
|
|
482
|
+
|
|
483
|
+
The SDK is written in TypeScript and provides comprehensive type definitions:
|
|
484
|
+
|
|
485
|
+
```typescript
|
|
486
|
+
import type {
|
|
487
|
+
Content,
|
|
488
|
+
Product,
|
|
489
|
+
ApiResponse,
|
|
490
|
+
PaginatedResponse
|
|
491
|
+
} from 'perspectapi-ts-sdk';
|
|
492
|
+
|
|
493
|
+
// Fully typed responses
|
|
494
|
+
const content: ApiResponse<Content> = await client.content.getContentById(123);
|
|
495
|
+
const products: PaginatedResponse<Product> = await client.products.getProducts('your-site-name');
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## Contributing
|
|
499
|
+
|
|
500
|
+
1. Fork the repository
|
|
501
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
502
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
503
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
504
|
+
5. Open a Pull Request
|
|
505
|
+
|
|
506
|
+
## License
|
|
507
|
+
|
|
508
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
509
|
+
|
|
510
|
+
## Support
|
|
511
|
+
|
|
512
|
+
- 📖 [Documentation](https://docs.perspectapi.com)
|
|
513
|
+
- 🐛 [Issue Tracker](https://github.com/perspectapi/perspectapi-ts-sdk/issues)
|
|
514
|
+
- 💬 [Discussions](https://github.com/perspectapi/perspectapi-ts-sdk/discussions)
|
|
515
|
+
- 📧 [Email Support](mailto:support@perspectapi.com)
|