perspectapi-ts-sdk 6.5.9 → 7.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.
Files changed (57) hide show
  1. package/README.md +46 -1011
  2. package/dist/chunk-K3T2AFYA.mjs +1393 -0
  3. package/dist/index-CWvUyMt3.d.mts +2224 -0
  4. package/dist/index-CWvUyMt3.d.ts +2224 -0
  5. package/dist/index.d.mts +130 -2221
  6. package/dist/index.d.ts +130 -2221
  7. package/dist/index.js +8 -2
  8. package/dist/index.mjs +13 -1364
  9. package/dist/v2/index.d.mts +1 -0
  10. package/dist/v2/index.d.ts +1 -0
  11. package/dist/v2/index.js +1419 -0
  12. package/dist/v2/index.mjs +40 -0
  13. package/docs/README.md +15 -0
  14. package/docs/v1-deprecated/README.md +9 -0
  15. package/docs/v1-deprecated/examples/README.md +324 -0
  16. package/docs/v1-deprecated/examples/basic-usage.ts +258 -0
  17. package/docs/v1-deprecated/examples/cloudflare-worker.ts +274 -0
  18. package/docs/v1-deprecated/examples/content-query-with-slug-prefix.ts +237 -0
  19. package/docs/v1-deprecated/examples/image-transforms.ts +200 -0
  20. package/docs/v1-deprecated/examples/site-user-checkout.ts +186 -0
  21. package/docs/v1-deprecated/examples/slug-prefix-examples.ts +491 -0
  22. package/docs/v1-deprecated/legacy-docs/caching.md +667 -0
  23. package/docs/v1-deprecated/legacy-docs/contact.md +1396 -0
  24. package/docs/v1-deprecated/legacy-docs/csrf-protection.md +664 -0
  25. package/docs/v1-deprecated/legacy-docs/image-transforms.md +523 -0
  26. package/docs/v1-deprecated/legacy-docs/loaders.md +304 -0
  27. package/docs/v1-deprecated/legacy-docs/newsletter.md +811 -0
  28. package/docs/v1-deprecated/legacy-docs/site-users.md +817 -0
  29. package/docs/v1-deprecated/legacy-notes/CHANGELOG-CHECKOUT.md +143 -0
  30. package/docs/v1-deprecated/legacy-notes/CSRF-CHECKOUT.md +271 -0
  31. package/docs/v1-deprecated/legacy-notes/IMAGE_TRANSFORMS_PORT.md +298 -0
  32. package/docs/v1-deprecated/sdk-readme.md +1076 -0
  33. package/examples/README.md +19 -0
  34. package/examples/basic-v2.ts +37 -0
  35. package/llms.txt +25 -0
  36. package/package.json +18 -7
  37. package/src/client/api-keys-client.ts +4 -0
  38. package/src/client/auth-client.ts +4 -0
  39. package/src/client/base-client.ts +7 -0
  40. package/src/client/bundles-client.ts +4 -0
  41. package/src/client/categories-client.ts +4 -0
  42. package/src/client/checkout-client.ts +4 -0
  43. package/src/client/contact-client.ts +4 -0
  44. package/src/client/content-client.ts +4 -0
  45. package/src/client/newsletter-client.ts +4 -0
  46. package/src/client/newsletter-management-client.ts +4 -0
  47. package/src/client/organizations-client.ts +4 -0
  48. package/src/client/products-client.ts +4 -0
  49. package/src/client/site-users-client.ts +10 -1
  50. package/src/client/sites-client.ts +4 -0
  51. package/src/client/webhooks-client.ts +4 -0
  52. package/src/deprecation.ts +2 -1
  53. package/src/index.ts +2 -1
  54. package/src/loaders.ts +59 -0
  55. package/src/perspect-api-client.ts +2 -2
  56. package/src/v2/client/orders-client.ts +6 -1
  57. package/src/v2/types.ts +3 -0
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Site User Profile & Checkout Prefill
3
+ *
4
+ * @deprecated Historical v1 example. Do not copy into new code. v1 sunsets on
5
+ * 2026-06-01; use createPerspectApiV2Client from perspectapi-ts-sdk/v2.
6
+ *
7
+ * Shows how to:
8
+ * 1. Authenticate a site user via OTP
9
+ * 2. Read and write profile data (shipping address, phone, etc.)
10
+ * 3. Create a checkout session that prefills Stripe with the user's details
11
+ */
12
+
13
+ import { createPerspectApiClient } from '../../../src';
14
+
15
+ const SITE_NAME = 'my-store';
16
+
17
+ // The SDK needs both an API key (for checkout) and a site user JWT (for profile).
18
+ // In a real app the API key lives server-side and the JWT is set after OTP login.
19
+ const client = createPerspectApiClient({
20
+ baseUrl: 'https://api.perspect.commm',
21
+ apiKey: 'pk_live_xxx',
22
+ });
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // 1. OTP Authentication
26
+ // ---------------------------------------------------------------------------
27
+
28
+ async function loginSiteUser(email: string, otpCode: string) {
29
+ // Request the OTP (sends an email with a 6-digit code)
30
+ await client.siteUsers.requestOtp(SITE_NAME, { email });
31
+
32
+ // Verify the code and set the JWT on the client in one call
33
+ const { data } = await client.siteUsers.verifyOtpAndSetAuth(SITE_NAME, {
34
+ email,
35
+ code: otpCode,
36
+ });
37
+
38
+ // data.user.id is the site_user_id you'll pass to checkout later
39
+ console.log('Logged in as', data.user.email, '— id:', data.user.id);
40
+ return data.user;
41
+ }
42
+
43
+ // ---------------------------------------------------------------------------
44
+ // 2. Profile: Read & Write
45
+ // ---------------------------------------------------------------------------
46
+
47
+ async function showProfile() {
48
+ const { data } = await client.siteUsers.getMe(SITE_NAME);
49
+
50
+ console.log('Name:', data.user.first_name, data.user.last_name);
51
+ console.log('Email:', data.user.email);
52
+ console.log('Profile keys:', Object.keys(data.profile));
53
+
54
+ return data;
55
+ }
56
+
57
+ async function saveShippingAddress(address: {
58
+ line1: string;
59
+ line2?: string;
60
+ city: string;
61
+ state: string;
62
+ postal_code: string;
63
+ country: string;
64
+ }) {
65
+ // Profile values are stored as strings. Serialize objects as JSON.
66
+ await client.siteUsers.setProfileValue(
67
+ SITE_NAME,
68
+ 'shipping_address',
69
+ JSON.stringify(address),
70
+ );
71
+ }
72
+
73
+ async function getShippingAddress() {
74
+ const { data } = await client.siteUsers.getProfile(SITE_NAME);
75
+ const raw = data.profile['shipping_address'];
76
+ if (!raw) return null;
77
+ return JSON.parse(raw.value);
78
+ }
79
+
80
+ async function savePhone(phone: string) {
81
+ await client.siteUsers.setProfileValue(SITE_NAME, 'phone', phone);
82
+ }
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // 3. Checkout with Prefill
86
+ // ---------------------------------------------------------------------------
87
+
88
+ /**
89
+ * Create a checkout session for the logged-in site user.
90
+ *
91
+ * Passing `site_user_id` tells the backend to create (or reuse) a gateway
92
+ * customer object. Stripe then prefills the checkout page with the
93
+ * customer's email, name, saved addresses, and payment methods.
94
+ *
95
+ * On the first checkout a new Stripe Customer is created automatically.
96
+ * Subsequent checkouts reuse the same Customer, so returning buyers see
97
+ * their saved details without re-entering anything.
98
+ */
99
+ async function createCheckout(siteUserId: string) {
100
+ const { data: session } = await client.checkout.createCheckoutSession(
101
+ SITE_NAME,
102
+ {
103
+ line_items: [
104
+ { price: 'prod_abc123', quantity: 1 },
105
+ ],
106
+ success_url: 'https://my-store.com/thank-you',
107
+ cancel_url: 'https://my-store.com/cart',
108
+ site_user_id: siteUserId,
109
+ },
110
+ );
111
+
112
+ console.log('Checkout URL:', session.url);
113
+ return session;
114
+ }
115
+
116
+ /**
117
+ * Checkout with a variant product (SKU).
118
+ */
119
+ async function createVariantCheckout(siteUserId: string) {
120
+ const { data: session } = await client.checkout.createCheckoutSession(
121
+ SITE_NAME,
122
+ {
123
+ line_items: [
124
+ { sku_id: 42, quantity: 2 },
125
+ ],
126
+ success_url: 'https://my-store.com/thank-you',
127
+ cancel_url: 'https://my-store.com/cart',
128
+ site_user_id: siteUserId,
129
+ },
130
+ );
131
+
132
+ console.log('Variant checkout URL:', session.url);
133
+ return session;
134
+ }
135
+
136
+ // ---------------------------------------------------------------------------
137
+ // 4. Order History
138
+ // ---------------------------------------------------------------------------
139
+
140
+ async function showOrders() {
141
+ const { data } = await client.siteUsers.getOrders(SITE_NAME);
142
+
143
+ for (const order of data.orders) {
144
+ console.log(
145
+ `${order.order_id ?? order.session_id} ${order.currency.toUpperCase()} ${(order.amount_total / 100).toFixed(2)} ${order.status}`,
146
+ );
147
+ }
148
+ }
149
+
150
+ // ---------------------------------------------------------------------------
151
+ // Full flow
152
+ // ---------------------------------------------------------------------------
153
+
154
+ async function main() {
155
+ // Step 1 — Log in (in a real app the code comes from the user's email)
156
+ const user = await loginSiteUser('jane@example.com', '123456');
157
+
158
+ // Step 2 — Save profile data (only needed once; persists across sessions)
159
+ await client.siteUsers.updateMe(SITE_NAME, {
160
+ first_name: 'Jane',
161
+ last_name: 'Doe',
162
+ });
163
+
164
+ await saveShippingAddress({
165
+ line1: '123 Main St',
166
+ city: 'Portland',
167
+ state: 'OR',
168
+ postal_code: '97201',
169
+ country: 'US',
170
+ });
171
+
172
+ await savePhone('+15035551234');
173
+
174
+ // Step 3 — Read it back
175
+ await showProfile();
176
+ const address = await getShippingAddress();
177
+ console.log('Saved shipping address:', address);
178
+
179
+ // Step 4 — Create a checkout session (Stripe prefills from the gateway customer)
180
+ await createCheckout(user.id);
181
+
182
+ // Step 5 — After purchase, view order history
183
+ await showOrders();
184
+ }
185
+
186
+ main();
@@ -0,0 +1,491 @@
1
+ /**
2
+ * Examples demonstrating slug_prefix filtering with perspectapi-ts-sdk
3
+ *
4
+ * @deprecated Historical v1 example. Do not copy into new code. v1 sunsets on
5
+ * 2026-06-01; use createPerspectApiV2Client from perspectapi-ts-sdk/v2.
6
+ *
7
+ * These examples show how to use the slug_prefix parameter to filter
8
+ * content and products by their URL prefix.
9
+ */
10
+
11
+ import { createPerspectApiClient } from '../../../src';
12
+
13
+ // Initialize the client
14
+ const client = createPerspectApiClient({
15
+ baseUrl: 'https://api.example.com',
16
+ apiKey: 'your-api-key-here'
17
+ });
18
+
19
+ const siteName = 'mysite';
20
+
21
+ /**
22
+ * CONTENT FILTERING EXAMPLES
23
+ */
24
+
25
+ // Example 1: Get all blog posts
26
+ async function getBlogPosts() {
27
+ const response = await client.content.getContent(siteName, {
28
+ slug_prefix: 'blog',
29
+ page_status: 'publish',
30
+ page_type: 'post',
31
+ page: 1,
32
+ limit: 20
33
+ });
34
+
35
+ console.log('Blog Posts:', response.data);
36
+ console.log('Total:', response.pagination?.total);
37
+ // URLs will be: /blog/post-1, /blog/post-2, etc.
38
+ }
39
+
40
+ // Example 2: Get all news articles
41
+ async function getNewsArticles() {
42
+ const response = await client.content.getContent(siteName, {
43
+ slug_prefix: 'news',
44
+ page_status: 'publish',
45
+ page: 1,
46
+ limit: 10
47
+ });
48
+
49
+ console.log('News Articles:', response.data);
50
+ // URLs will be: /news/article-1, /news/article-2, etc.
51
+ }
52
+
53
+ // Example 3: Get documentation pages
54
+ async function getDocumentation() {
55
+ const response = await client.content.getContent(siteName, {
56
+ slug_prefix: 'docs',
57
+ page_type: 'page',
58
+ page_status: 'publish'
59
+ });
60
+
61
+ console.log('Documentation Pages:', response.data);
62
+ // URLs will be: /docs/getting-started, /docs/api-reference, etc.
63
+ }
64
+
65
+ // Example 4: Search within blog posts only
66
+ async function searchBlogPosts(searchTerm: string) {
67
+ const response = await client.content.getContent(siteName, {
68
+ slug_prefix: 'blog',
69
+ search: searchTerm,
70
+ page_status: 'publish'
71
+ });
72
+
73
+ console.log(`Blog posts matching "${searchTerm}":`, response.data);
74
+ }
75
+
76
+ // Example 5: Get draft blog posts (for admin)
77
+ async function getDraftBlogPosts() {
78
+ const response = await client.content.getContent(siteName, {
79
+ slug_prefix: 'blog',
80
+ page_status: 'draft',
81
+ page_type: 'post'
82
+ });
83
+
84
+ console.log('Draft Blog Posts:', response.data);
85
+ }
86
+
87
+ // Example 6: Get blog posts by specific author
88
+ async function getBlogPostsByAuthor(userId: number) {
89
+ const response = await client.content.getContent(siteName, {
90
+ slug_prefix: 'blog',
91
+ user_id: userId,
92
+ page_status: 'publish'
93
+ });
94
+
95
+ console.log(`Blog posts by user ${userId}:`, response.data);
96
+ }
97
+
98
+ /**
99
+ * PRODUCT FILTERING EXAMPLES
100
+ */
101
+
102
+ // Example 7: Get all shop products
103
+ async function getShopProducts() {
104
+ const response = await client.products.getProducts(siteName, {
105
+ slug_prefix: 'shop',
106
+ isActive: true,
107
+ page: 1,
108
+ limit: 20
109
+ });
110
+
111
+ console.log('Shop Products:', response.data);
112
+ // URLs will be: /shop/product-1, /shop/product-2, etc.
113
+ }
114
+
115
+ // Example 8: Get artwork products
116
+ async function getArtworkProducts() {
117
+ const response = await client.products.getProducts(siteName, {
118
+ slug_prefix: 'artwork',
119
+ isActive: true
120
+ });
121
+
122
+ console.log('Artwork Products:', response.data);
123
+ // URLs will be: /artwork/painting-1, /artwork/sculpture-1, etc.
124
+ }
125
+
126
+ // Example 9: Search within shop products only
127
+ async function searchShopProducts(searchTerm: string) {
128
+ const response = await client.products.getProducts(siteName, {
129
+ slug_prefix: 'shop',
130
+ search: searchTerm,
131
+ isActive: true
132
+ });
133
+
134
+ console.log(`Shop products matching "${searchTerm}":`, response.data);
135
+ }
136
+
137
+ // Example 10: Get shop products in specific category
138
+ async function getShopProductsByCategory(categorySlug: string) {
139
+ const response = await client.products.getProducts(siteName, {
140
+ slug_prefix: 'shop',
141
+ category: categorySlug,
142
+ isActive: true
143
+ });
144
+
145
+ console.log(`Shop products in ${categorySlug}:`, response.data);
146
+ }
147
+
148
+ // Example 11: Get shop electronics
149
+ async function getShopElectronics() {
150
+ const response = await client.products.getProducts(siteName, {
151
+ slug_prefix: 'shop',
152
+ category: 'electronics',
153
+ isActive: true,
154
+ page: 1,
155
+ limit: 50
156
+ });
157
+
158
+ console.log('Shop Electronics:', response.data);
159
+ }
160
+
161
+ // Example 12: Get premium products (different prefix)
162
+ async function getPremiumProducts() {
163
+ const response = await client.products.getProducts(siteName, {
164
+ slug_prefix: 'premium',
165
+ isActive: true
166
+ });
167
+
168
+ console.log('Premium Products:', response.data);
169
+ // URLs will be: /premium/product-1, /premium/product-2, etc.
170
+ }
171
+
172
+ /**
173
+ * ADVANCED FILTERING EXAMPLES
174
+ */
175
+
176
+ // Example 13: Multi-section content aggregation
177
+ async function getRecentContentFromAllSections() {
178
+ // Get recent posts from different sections
179
+ const [blogPosts, newsArticles, guides] = await Promise.all([
180
+ client.content.getContent(siteName, {
181
+ slug_prefix: 'blog',
182
+ page_status: 'publish',
183
+ limit: 5
184
+ }),
185
+ client.content.getContent(siteName, {
186
+ slug_prefix: 'news',
187
+ page_status: 'publish',
188
+ limit: 5
189
+ }),
190
+ client.content.getContent(siteName, {
191
+ slug_prefix: 'guides',
192
+ page_status: 'publish',
193
+ limit: 5
194
+ })
195
+ ]);
196
+
197
+ return {
198
+ blog: blogPosts.data || [],
199
+ news: newsArticles.data || [],
200
+ guides: guides.data || []
201
+ };
202
+ }
203
+
204
+ // Example 14: Product catalog organization
205
+ async function getProductCatalog() {
206
+ // Get products from different sections
207
+ const [shopProducts, artworks, services] = await Promise.all([
208
+ client.products.getProducts(siteName, {
209
+ slug_prefix: 'shop',
210
+ isActive: true,
211
+ limit: 20
212
+ }),
213
+ client.products.getProducts(siteName, {
214
+ slug_prefix: 'artwork',
215
+ isActive: true,
216
+ limit: 20
217
+ }),
218
+ client.products.getProducts(siteName, {
219
+ slug_prefix: 'services',
220
+ isActive: true,
221
+ limit: 20
222
+ })
223
+ ]);
224
+
225
+ return {
226
+ shop: shopProducts.data || [],
227
+ artwork: artworks.data || [],
228
+ services: services.data || []
229
+ };
230
+ }
231
+
232
+ // Example 15: Paginated blog listing
233
+ async function getPaginatedBlogPosts(page: number = 1, limit: number = 20) {
234
+ const response = await client.content.getContent(siteName, {
235
+ slug_prefix: 'blog',
236
+ page_status: 'publish',
237
+ page_type: 'post',
238
+ page,
239
+ limit
240
+ });
241
+
242
+ return {
243
+ posts: response.data,
244
+ currentPage: page,
245
+ totalPages: response.pagination?.totalPages || 0,
246
+ totalPosts: response.pagination?.total || 0,
247
+ hasNextPage: page < (response.pagination?.totalPages || 0),
248
+ hasPrevPage: page > 1
249
+ };
250
+ }
251
+
252
+ // Example 16: Search across specific product categories with prefix
253
+ async function searchProductsInSection(
254
+ prefix: string,
255
+ searchTerm: string,
256
+ category?: string
257
+ ) {
258
+ const response = await client.products.getProducts(siteName, {
259
+ slug_prefix: prefix,
260
+ search: searchTerm,
261
+ category: category,
262
+ isActive: true
263
+ });
264
+
265
+ return response.data;
266
+ }
267
+
268
+ /**
269
+ * REAL-WORLD USE CASES
270
+ */
271
+
272
+ // Example 17: Blog homepage - recent posts
273
+ async function getBlogHomepage() {
274
+ const recentPosts = await client.content.getContent(siteName, {
275
+ slug_prefix: 'blog',
276
+ page_status: 'publish',
277
+ page_type: 'post',
278
+ limit: 10
279
+ });
280
+
281
+ return {
282
+ title: 'Blog',
283
+ posts: recentPosts.data || [],
284
+ total: recentPosts.pagination?.total
285
+ };
286
+ }
287
+
288
+ // Example 18: Shop homepage - featured products
289
+ async function getShopHomepage() {
290
+ const products = await client.products.getProducts(siteName, {
291
+ slug_prefix: 'shop',
292
+ isActive: true,
293
+ limit: 12
294
+ });
295
+
296
+ return {
297
+ title: 'Shop',
298
+ products: products.data || []
299
+ };
300
+ }
301
+
302
+ // Example 19: Documentation site structure
303
+ async function getDocumentationStructure() {
304
+ const [gettingStarted, apiDocs, guides, tutorials] = await Promise.all([
305
+ client.content.getContent(siteName, {
306
+ slug_prefix: 'docs',
307
+ search: 'getting started',
308
+ page_status: 'publish'
309
+ }),
310
+ client.content.getContent(siteName, {
311
+ slug_prefix: 'api',
312
+ page_status: 'publish'
313
+ }),
314
+ client.content.getContent(siteName, {
315
+ slug_prefix: 'guides',
316
+ page_status: 'publish'
317
+ }),
318
+ client.content.getContent(siteName, {
319
+ slug_prefix: 'tutorials',
320
+ page_status: 'publish'
321
+ })
322
+ ]);
323
+
324
+ return {
325
+ gettingStarted: gettingStarted.data || [],
326
+ api: apiDocs.data || [],
327
+ guides: guides.data || [],
328
+ tutorials: tutorials.data || []
329
+ };
330
+ }
331
+
332
+ // Example 20: E-commerce with multiple product types
333
+ async function getEcommerceProducts() {
334
+ const [physical, digital, services, subscriptions] = await Promise.all([
335
+ client.products.getProducts(siteName, {
336
+ slug_prefix: 'shop',
337
+ isActive: true
338
+ }),
339
+ client.products.getProducts(siteName, {
340
+ slug_prefix: 'downloads',
341
+ isActive: true
342
+ }),
343
+ client.products.getProducts(siteName, {
344
+ slug_prefix: 'services',
345
+ isActive: true
346
+ }),
347
+ client.products.getProducts(siteName, {
348
+ slug_prefix: 'subscriptions',
349
+ isActive: true
350
+ })
351
+ ]);
352
+
353
+ return {
354
+ physical: physical.data || [],
355
+ digital: digital.data || [],
356
+ services: services.data || [],
357
+ subscriptions: subscriptions.data || []
358
+ };
359
+ }
360
+
361
+ /**
362
+ * UTILITY FUNCTIONS
363
+ */
364
+
365
+ // Example 21: Get all available slug prefixes (for debugging)
366
+ async function getAvailableContentPrefixes() {
367
+ const allContent = await client.content.getContent(siteName, {
368
+ limit: 100
369
+ });
370
+
371
+ const prefixes = new Set(
372
+ (allContent.data || [])
373
+ .map(item => item.slug_prefix)
374
+ .filter(prefix => prefix !== null && prefix !== undefined)
375
+ );
376
+
377
+ return Array.from(prefixes);
378
+ }
379
+
380
+ // Example 22: Get all available product prefixes (for debugging)
381
+ async function getAvailableProductPrefixes() {
382
+ const allProducts = await client.products.getProducts(siteName, {
383
+ limit: 100
384
+ });
385
+
386
+ const prefixes = new Set(
387
+ (allProducts.data || [])
388
+ .map(item => item.slug_prefix)
389
+ .filter(prefix => prefix !== null && prefix !== undefined)
390
+ );
391
+
392
+ return Array.from(prefixes);
393
+ }
394
+
395
+ /**
396
+ * ERROR HANDLING EXAMPLES
397
+ */
398
+
399
+ // Example 23: Handle no results gracefully
400
+ async function safeGetBlogPosts() {
401
+ try {
402
+ const response = await client.content.getContent(siteName, {
403
+ slug_prefix: 'blog',
404
+ page_status: 'publish'
405
+ });
406
+
407
+ if (!response.data || response.data.length === 0) {
408
+ console.log('No blog posts found');
409
+ return [];
410
+ }
411
+
412
+ return response.data;
413
+ } catch (error) {
414
+ console.error('Error fetching blog posts:', error);
415
+ return [];
416
+ }
417
+ }
418
+
419
+ // Example 24: Validate prefix exists before querying
420
+ async function getContentByPrefix(prefix: string) {
421
+ const availablePrefixes = await getAvailableContentPrefixes();
422
+
423
+ if (!availablePrefixes.includes(prefix)) {
424
+ console.warn(`Prefix "${prefix}" not found. Available: ${availablePrefixes.join(', ')}`);
425
+ return [];
426
+ }
427
+
428
+ const response = await client.content.getContent(siteName, {
429
+ slug_prefix: prefix,
430
+ page_status: 'publish'
431
+ });
432
+
433
+ return response.data;
434
+ }
435
+
436
+ /**
437
+ * EXPORT ALL EXAMPLES
438
+ */
439
+ export {
440
+ // Content examples
441
+ getBlogPosts,
442
+ getNewsArticles,
443
+ getDocumentation,
444
+ searchBlogPosts,
445
+ getDraftBlogPosts,
446
+ getBlogPostsByAuthor,
447
+
448
+ // Product examples
449
+ getShopProducts,
450
+ getArtworkProducts,
451
+ searchShopProducts,
452
+ getShopProductsByCategory,
453
+ getShopElectronics,
454
+ getPremiumProducts,
455
+
456
+ // Advanced examples
457
+ getRecentContentFromAllSections,
458
+ getProductCatalog,
459
+ getPaginatedBlogPosts,
460
+ searchProductsInSection,
461
+
462
+ // Real-world use cases
463
+ getBlogHomepage,
464
+ getShopHomepage,
465
+ getDocumentationStructure,
466
+ getEcommerceProducts,
467
+
468
+ // Utility functions
469
+ getAvailableContentPrefixes,
470
+ getAvailableProductPrefixes,
471
+
472
+ // Error handling
473
+ safeGetBlogPosts,
474
+ getContentByPrefix
475
+ };
476
+
477
+ /**
478
+ * USAGE NOTES:
479
+ *
480
+ * 1. The slug_prefix parameter is optional - omit it to get all content/products
481
+ * 2. slug_prefix performs exact match (case-sensitive)
482
+ * 3. Combine slug_prefix with other filters for precise queries
483
+ * 4. Use consistent naming: 'blog', 'news', 'shop', 'artwork' (lowercase)
484
+ * 5. Plan your URL structure before setting prefixes
485
+ *
486
+ * URL STRUCTURE EXAMPLES:
487
+ * - slug_prefix: 'blog', slug: 'my-post' → /blog/my-post
488
+ * - slug_prefix: 'shop', slug: 'laptop' → /shop/laptop
489
+ * - slug_prefix: 'artwork', slug: 'painting' → /artwork/painting
490
+ * - slug_prefix: null, slug: 'about' → /about
491
+ */