perspectapi-ts-sdk 3.4.0 → 3.5.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/README.md CHANGED
@@ -93,7 +93,7 @@ import { PerspectApiClient } from 'perspectapi-ts-sdk';
93
93
  import { myCacheAdapter } from './cache-adapter';
94
94
 
95
95
  const perspect = new PerspectApiClient({
96
- baseUrl: 'https://api.perspect.co',
96
+ baseUrl: 'https://api.perspect.comm',
97
97
  apiKey: env.PERSPECT_API_KEY,
98
98
  cache: {
99
99
  adapter: myCacheAdapter,
@@ -248,7 +248,7 @@ const media = product.data.media?.[0];
248
248
 
249
249
  if (media) {
250
250
  // Generate all responsive sizes automatically
251
- const urls = transformMediaItem('https://api.perspect.co', media);
251
+ const urls = transformMediaItem('https://api.perspect.comm', media);
252
252
 
253
253
  console.log(urls.thumbnail); // 150x150 cover crop
254
254
  console.log(urls.small); // 400px wide
@@ -259,7 +259,7 @@ if (media) {
259
259
 
260
260
  // Or build custom transformations
261
261
  const customUrl = buildImageUrl(
262
- 'https://api.perspect.co',
262
+ 'https://api.perspect.comm',
263
263
  'media/mysite/photo.jpg',
264
264
  {
265
265
  width: 400,
package/dist/index.d.mts CHANGED
@@ -2416,6 +2416,15 @@ declare class SiteUsersClient extends BaseClient {
2416
2416
  changeSubscriptionPlan(siteName: string, subscriptionId: string, productId: number, csrfToken?: string): Promise<ApiResponse<{
2417
2417
  success: boolean;
2418
2418
  }>>;
2419
+ /**
2420
+ * Create a Stripe Billing Portal session for updating payment methods
2421
+ * @param siteName - The site name
2422
+ * @param returnUrl - URL to redirect back to after portal session
2423
+ * @param csrfToken - CSRF token (required)
2424
+ */
2425
+ createBillingPortalSession(siteName: string, returnUrl: string, csrfToken?: string): Promise<ApiResponse<{
2426
+ url: string;
2427
+ }>>;
2419
2428
  /**
2420
2429
  * Get linked newsletter subscriptions
2421
2430
  * @param siteName - The site name
@@ -2506,6 +2515,61 @@ declare class SiteUsersClient extends BaseClient {
2506
2515
  }): Promise<ApiResponse<{
2507
2516
  success: boolean;
2508
2517
  }>>;
2518
+ /**
2519
+ * Get a user's orders (admin only)
2520
+ * @param siteName - The site name
2521
+ * @param userId - User ID
2522
+ * @param params - Pagination params
2523
+ */
2524
+ getUserOrders(siteName: string, userId: string, params?: {
2525
+ limit?: number;
2526
+ offset?: number;
2527
+ }): Promise<ApiResponse<{
2528
+ orders: SiteUserOrder[];
2529
+ }>>;
2530
+ /**
2531
+ * Get a user's subscriptions (admin only)
2532
+ * @param siteName - The site name
2533
+ * @param userId - User ID
2534
+ */
2535
+ getUserSubscriptions(siteName: string, userId: string): Promise<ApiResponse<{
2536
+ subscriptions: SiteUserSubscription[];
2537
+ }>>;
2538
+ /**
2539
+ * Pause a user's subscription (admin only)
2540
+ * @param siteName - The site name
2541
+ * @param userId - User ID
2542
+ * @param subscriptionId - Subscription ID
2543
+ * @param resumesAt - Optional ISO date string when subscription should auto-resume
2544
+ */
2545
+ pauseUserSubscription(siteName: string, userId: string, subscriptionId: string, resumesAt?: string): Promise<ApiResponse<{
2546
+ success: boolean;
2547
+ }>>;
2548
+ /**
2549
+ * Resume a user's paused subscription (admin only)
2550
+ * @param siteName - The site name
2551
+ * @param userId - User ID
2552
+ * @param subscriptionId - Subscription ID
2553
+ */
2554
+ resumeUserSubscription(siteName: string, userId: string, subscriptionId: string): Promise<ApiResponse<{
2555
+ success: boolean;
2556
+ }>>;
2557
+ /**
2558
+ * Cancel a user's subscription (admin only)
2559
+ * @param siteName - The site name
2560
+ * @param userId - User ID
2561
+ * @param subscriptionId - Subscription ID
2562
+ */
2563
+ cancelUserSubscription(siteName: string, userId: string, subscriptionId: string): Promise<ApiResponse<{
2564
+ success: boolean;
2565
+ message: string;
2566
+ }>>;
2567
+ /**
2568
+ * Get a user's credit balance (admin only)
2569
+ * @param siteName - The site name
2570
+ * @param userId - User ID
2571
+ */
2572
+ getUserCreditBalance(siteName: string, userId: string): Promise<ApiResponse<CreditBalance>>;
2509
2573
  }
2510
2574
 
2511
2575
  /**
@@ -2714,7 +2778,7 @@ declare const DEFAULT_IMAGE_SIZES: ResponsiveImageSizes;
2714
2778
  /**
2715
2779
  * Build Cloudflare Image Resizing URL
2716
2780
  *
2717
- * @param baseUrl - The base URL of your API (e.g., "https://api.perspect.co")
2781
+ * @param baseUrl - The base URL of your API (e.g., "https://api.perspect.comm")
2718
2782
  * @param mediaPath - The path to the media file (e.g., "media/site/image.jpg")
2719
2783
  * @param options - Transform options
2720
2784
  * @returns Cloudflare Image Resizing URL
@@ -2722,11 +2786,11 @@ declare const DEFAULT_IMAGE_SIZES: ResponsiveImageSizes;
2722
2786
  * @example
2723
2787
  * ```typescript
2724
2788
  * const url = buildImageUrl(
2725
- * 'https://api.perspect.co',
2789
+ * 'https://api.perspect.comm',
2726
2790
  * 'media/mysite/photo.jpg',
2727
2791
  * { width: 400, format: 'webp', quality: 85 }
2728
2792
  * );
2729
- * // Returns: '/cdn-cgi/image/width=400,format=webp,quality=85/https://api.perspect.co/media/mysite/photo.jpg'
2793
+ * // Returns: '/cdn-cgi/image/width=400,format=webp,quality=85/https://api.perspect.comm/media/mysite/photo.jpg'
2730
2794
  * ```
2731
2795
  */
2732
2796
  declare function buildImageUrl(baseUrl: string, mediaPath: string, options?: ImageTransformOptions): string;
@@ -2736,7 +2800,7 @@ declare function buildImageUrl(baseUrl: string, mediaPath: string, options?: Ima
2736
2800
  * @example
2737
2801
  * ```typescript
2738
2802
  * const urls = generateResponsiveUrls(
2739
- * 'https://api.perspect.co',
2803
+ * 'https://api.perspect.comm',
2740
2804
  * 'media/mysite/photo.jpg'
2741
2805
  * );
2742
2806
  * // Returns: { thumbnail: '...', small: '...', medium: '...', large: '...', original: '...' }
@@ -2749,7 +2813,7 @@ declare function generateResponsiveUrls(baseUrl: string, mediaPath: string, size
2749
2813
  * @example
2750
2814
  * ```typescript
2751
2815
  * const srcset = generateSrcSet(
2752
- * 'https://api.perspect.co',
2816
+ * 'https://api.perspect.comm',
2753
2817
  * 'media/mysite/photo.jpg',
2754
2818
  * [400, 800, 1200]
2755
2819
  * );
@@ -2776,7 +2840,7 @@ declare function generateSizesAttribute(breakpoints?: Array<{
2776
2840
  * @example
2777
2841
  * ```typescript
2778
2842
  * const html = generateResponsiveImageHtml(
2779
- * 'https://api.perspect.co',
2843
+ * 'https://api.perspect.comm',
2780
2844
  * 'media/mysite/photo.jpg',
2781
2845
  * 'My photo',
2782
2846
  * { className: 'rounded-lg', loading: 'lazy' }
@@ -2802,7 +2866,7 @@ declare function generateResponsiveImageHtml(baseUrl: string, mediaPath: string,
2802
2866
  * const media = product.data.media?.[0];
2803
2867
  *
2804
2868
  * if (media) {
2805
- * const urls = transformMediaItem('https://api.perspect.co', media);
2869
+ * const urls = transformMediaItem('https://api.perspect.comm', media);
2806
2870
  * console.log(urls.thumbnail); // Cloudflare-transformed thumbnail URL
2807
2871
  * }
2808
2872
  * ```
package/dist/index.d.ts CHANGED
@@ -2416,6 +2416,15 @@ declare class SiteUsersClient extends BaseClient {
2416
2416
  changeSubscriptionPlan(siteName: string, subscriptionId: string, productId: number, csrfToken?: string): Promise<ApiResponse<{
2417
2417
  success: boolean;
2418
2418
  }>>;
2419
+ /**
2420
+ * Create a Stripe Billing Portal session for updating payment methods
2421
+ * @param siteName - The site name
2422
+ * @param returnUrl - URL to redirect back to after portal session
2423
+ * @param csrfToken - CSRF token (required)
2424
+ */
2425
+ createBillingPortalSession(siteName: string, returnUrl: string, csrfToken?: string): Promise<ApiResponse<{
2426
+ url: string;
2427
+ }>>;
2419
2428
  /**
2420
2429
  * Get linked newsletter subscriptions
2421
2430
  * @param siteName - The site name
@@ -2506,6 +2515,61 @@ declare class SiteUsersClient extends BaseClient {
2506
2515
  }): Promise<ApiResponse<{
2507
2516
  success: boolean;
2508
2517
  }>>;
2518
+ /**
2519
+ * Get a user's orders (admin only)
2520
+ * @param siteName - The site name
2521
+ * @param userId - User ID
2522
+ * @param params - Pagination params
2523
+ */
2524
+ getUserOrders(siteName: string, userId: string, params?: {
2525
+ limit?: number;
2526
+ offset?: number;
2527
+ }): Promise<ApiResponse<{
2528
+ orders: SiteUserOrder[];
2529
+ }>>;
2530
+ /**
2531
+ * Get a user's subscriptions (admin only)
2532
+ * @param siteName - The site name
2533
+ * @param userId - User ID
2534
+ */
2535
+ getUserSubscriptions(siteName: string, userId: string): Promise<ApiResponse<{
2536
+ subscriptions: SiteUserSubscription[];
2537
+ }>>;
2538
+ /**
2539
+ * Pause a user's subscription (admin only)
2540
+ * @param siteName - The site name
2541
+ * @param userId - User ID
2542
+ * @param subscriptionId - Subscription ID
2543
+ * @param resumesAt - Optional ISO date string when subscription should auto-resume
2544
+ */
2545
+ pauseUserSubscription(siteName: string, userId: string, subscriptionId: string, resumesAt?: string): Promise<ApiResponse<{
2546
+ success: boolean;
2547
+ }>>;
2548
+ /**
2549
+ * Resume a user's paused subscription (admin only)
2550
+ * @param siteName - The site name
2551
+ * @param userId - User ID
2552
+ * @param subscriptionId - Subscription ID
2553
+ */
2554
+ resumeUserSubscription(siteName: string, userId: string, subscriptionId: string): Promise<ApiResponse<{
2555
+ success: boolean;
2556
+ }>>;
2557
+ /**
2558
+ * Cancel a user's subscription (admin only)
2559
+ * @param siteName - The site name
2560
+ * @param userId - User ID
2561
+ * @param subscriptionId - Subscription ID
2562
+ */
2563
+ cancelUserSubscription(siteName: string, userId: string, subscriptionId: string): Promise<ApiResponse<{
2564
+ success: boolean;
2565
+ message: string;
2566
+ }>>;
2567
+ /**
2568
+ * Get a user's credit balance (admin only)
2569
+ * @param siteName - The site name
2570
+ * @param userId - User ID
2571
+ */
2572
+ getUserCreditBalance(siteName: string, userId: string): Promise<ApiResponse<CreditBalance>>;
2509
2573
  }
2510
2574
 
2511
2575
  /**
@@ -2714,7 +2778,7 @@ declare const DEFAULT_IMAGE_SIZES: ResponsiveImageSizes;
2714
2778
  /**
2715
2779
  * Build Cloudflare Image Resizing URL
2716
2780
  *
2717
- * @param baseUrl - The base URL of your API (e.g., "https://api.perspect.co")
2781
+ * @param baseUrl - The base URL of your API (e.g., "https://api.perspect.comm")
2718
2782
  * @param mediaPath - The path to the media file (e.g., "media/site/image.jpg")
2719
2783
  * @param options - Transform options
2720
2784
  * @returns Cloudflare Image Resizing URL
@@ -2722,11 +2786,11 @@ declare const DEFAULT_IMAGE_SIZES: ResponsiveImageSizes;
2722
2786
  * @example
2723
2787
  * ```typescript
2724
2788
  * const url = buildImageUrl(
2725
- * 'https://api.perspect.co',
2789
+ * 'https://api.perspect.comm',
2726
2790
  * 'media/mysite/photo.jpg',
2727
2791
  * { width: 400, format: 'webp', quality: 85 }
2728
2792
  * );
2729
- * // Returns: '/cdn-cgi/image/width=400,format=webp,quality=85/https://api.perspect.co/media/mysite/photo.jpg'
2793
+ * // Returns: '/cdn-cgi/image/width=400,format=webp,quality=85/https://api.perspect.comm/media/mysite/photo.jpg'
2730
2794
  * ```
2731
2795
  */
2732
2796
  declare function buildImageUrl(baseUrl: string, mediaPath: string, options?: ImageTransformOptions): string;
@@ -2736,7 +2800,7 @@ declare function buildImageUrl(baseUrl: string, mediaPath: string, options?: Ima
2736
2800
  * @example
2737
2801
  * ```typescript
2738
2802
  * const urls = generateResponsiveUrls(
2739
- * 'https://api.perspect.co',
2803
+ * 'https://api.perspect.comm',
2740
2804
  * 'media/mysite/photo.jpg'
2741
2805
  * );
2742
2806
  * // Returns: { thumbnail: '...', small: '...', medium: '...', large: '...', original: '...' }
@@ -2749,7 +2813,7 @@ declare function generateResponsiveUrls(baseUrl: string, mediaPath: string, size
2749
2813
  * @example
2750
2814
  * ```typescript
2751
2815
  * const srcset = generateSrcSet(
2752
- * 'https://api.perspect.co',
2816
+ * 'https://api.perspect.comm',
2753
2817
  * 'media/mysite/photo.jpg',
2754
2818
  * [400, 800, 1200]
2755
2819
  * );
@@ -2776,7 +2840,7 @@ declare function generateSizesAttribute(breakpoints?: Array<{
2776
2840
  * @example
2777
2841
  * ```typescript
2778
2842
  * const html = generateResponsiveImageHtml(
2779
- * 'https://api.perspect.co',
2843
+ * 'https://api.perspect.comm',
2780
2844
  * 'media/mysite/photo.jpg',
2781
2845
  * 'My photo',
2782
2846
  * { className: 'rounded-lg', loading: 'lazy' }
@@ -2802,7 +2866,7 @@ declare function generateResponsiveImageHtml(baseUrl: string, mediaPath: string,
2802
2866
  * const media = product.data.media?.[0];
2803
2867
  *
2804
2868
  * if (media) {
2805
- * const urls = transformMediaItem('https://api.perspect.co', media);
2869
+ * const urls = transformMediaItem('https://api.perspect.comm', media);
2806
2870
  * console.log(urls.thumbnail); // Cloudflare-transformed thumbnail URL
2807
2871
  * }
2808
2872
  * ```
package/dist/index.js CHANGED
@@ -2529,6 +2529,19 @@ var SiteUsersClient = class extends BaseClient {
2529
2529
  csrfToken
2530
2530
  );
2531
2531
  }
2532
+ /**
2533
+ * Create a Stripe Billing Portal session for updating payment methods
2534
+ * @param siteName - The site name
2535
+ * @param returnUrl - URL to redirect back to after portal session
2536
+ * @param csrfToken - CSRF token (required)
2537
+ */
2538
+ async createBillingPortalSession(siteName, returnUrl, csrfToken) {
2539
+ return this.create(
2540
+ this.siteUserEndpoint(siteName, "/users/me/billing-portal"),
2541
+ { return_url: returnUrl },
2542
+ csrfToken
2543
+ );
2544
+ }
2532
2545
  /**
2533
2546
  * Get linked newsletter subscriptions
2534
2547
  * @param siteName - The site name
@@ -2637,6 +2650,83 @@ var SiteUsersClient = class extends BaseClient {
2637
2650
  data
2638
2651
  );
2639
2652
  }
2653
+ // ============================================================================
2654
+ // ADMIN USER-SCOPED ENDPOINTS (API key auth required)
2655
+ // These mirror /me/* endpoints but target a specific user by ID.
2656
+ // ============================================================================
2657
+ /**
2658
+ * Get a user's orders (admin only)
2659
+ * @param siteName - The site name
2660
+ * @param userId - User ID
2661
+ * @param params - Pagination params
2662
+ */
2663
+ async getUserOrders(siteName, userId, params) {
2664
+ return this.http.get(
2665
+ this.buildPath(this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/orders`)),
2666
+ params
2667
+ );
2668
+ }
2669
+ /**
2670
+ * Get a user's subscriptions (admin only)
2671
+ * @param siteName - The site name
2672
+ * @param userId - User ID
2673
+ */
2674
+ async getUserSubscriptions(siteName, userId) {
2675
+ return this.getSingle(
2676
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions`)
2677
+ );
2678
+ }
2679
+ /**
2680
+ * Pause a user's subscription (admin only)
2681
+ * @param siteName - The site name
2682
+ * @param userId - User ID
2683
+ * @param subscriptionId - Subscription ID
2684
+ * @param resumesAt - Optional ISO date string when subscription should auto-resume
2685
+ */
2686
+ async pauseUserSubscription(siteName, userId, subscriptionId, resumesAt) {
2687
+ const body = {};
2688
+ if (resumesAt) {
2689
+ body.resumes_at = resumesAt;
2690
+ }
2691
+ return this.create(
2692
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/pause`),
2693
+ body
2694
+ );
2695
+ }
2696
+ /**
2697
+ * Resume a user's paused subscription (admin only)
2698
+ * @param siteName - The site name
2699
+ * @param userId - User ID
2700
+ * @param subscriptionId - Subscription ID
2701
+ */
2702
+ async resumeUserSubscription(siteName, userId, subscriptionId) {
2703
+ return this.create(
2704
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/resume`),
2705
+ {}
2706
+ );
2707
+ }
2708
+ /**
2709
+ * Cancel a user's subscription (admin only)
2710
+ * @param siteName - The site name
2711
+ * @param userId - User ID
2712
+ * @param subscriptionId - Subscription ID
2713
+ */
2714
+ async cancelUserSubscription(siteName, userId, subscriptionId) {
2715
+ return this.create(
2716
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/cancel`),
2717
+ {}
2718
+ );
2719
+ }
2720
+ /**
2721
+ * Get a user's credit balance (admin only)
2722
+ * @param siteName - The site name
2723
+ * @param userId - User ID
2724
+ */
2725
+ async getUserCreditBalance(siteName, userId) {
2726
+ return this.getSingle(
2727
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/credits/balance`)
2728
+ );
2729
+ }
2640
2730
  };
2641
2731
 
2642
2732
  // src/client/bundles-client.ts
package/dist/index.mjs CHANGED
@@ -2466,6 +2466,19 @@ var SiteUsersClient = class extends BaseClient {
2466
2466
  csrfToken
2467
2467
  );
2468
2468
  }
2469
+ /**
2470
+ * Create a Stripe Billing Portal session for updating payment methods
2471
+ * @param siteName - The site name
2472
+ * @param returnUrl - URL to redirect back to after portal session
2473
+ * @param csrfToken - CSRF token (required)
2474
+ */
2475
+ async createBillingPortalSession(siteName, returnUrl, csrfToken) {
2476
+ return this.create(
2477
+ this.siteUserEndpoint(siteName, "/users/me/billing-portal"),
2478
+ { return_url: returnUrl },
2479
+ csrfToken
2480
+ );
2481
+ }
2469
2482
  /**
2470
2483
  * Get linked newsletter subscriptions
2471
2484
  * @param siteName - The site name
@@ -2574,6 +2587,83 @@ var SiteUsersClient = class extends BaseClient {
2574
2587
  data
2575
2588
  );
2576
2589
  }
2590
+ // ============================================================================
2591
+ // ADMIN USER-SCOPED ENDPOINTS (API key auth required)
2592
+ // These mirror /me/* endpoints but target a specific user by ID.
2593
+ // ============================================================================
2594
+ /**
2595
+ * Get a user's orders (admin only)
2596
+ * @param siteName - The site name
2597
+ * @param userId - User ID
2598
+ * @param params - Pagination params
2599
+ */
2600
+ async getUserOrders(siteName, userId, params) {
2601
+ return this.http.get(
2602
+ this.buildPath(this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/orders`)),
2603
+ params
2604
+ );
2605
+ }
2606
+ /**
2607
+ * Get a user's subscriptions (admin only)
2608
+ * @param siteName - The site name
2609
+ * @param userId - User ID
2610
+ */
2611
+ async getUserSubscriptions(siteName, userId) {
2612
+ return this.getSingle(
2613
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions`)
2614
+ );
2615
+ }
2616
+ /**
2617
+ * Pause a user's subscription (admin only)
2618
+ * @param siteName - The site name
2619
+ * @param userId - User ID
2620
+ * @param subscriptionId - Subscription ID
2621
+ * @param resumesAt - Optional ISO date string when subscription should auto-resume
2622
+ */
2623
+ async pauseUserSubscription(siteName, userId, subscriptionId, resumesAt) {
2624
+ const body = {};
2625
+ if (resumesAt) {
2626
+ body.resumes_at = resumesAt;
2627
+ }
2628
+ return this.create(
2629
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/pause`),
2630
+ body
2631
+ );
2632
+ }
2633
+ /**
2634
+ * Resume a user's paused subscription (admin only)
2635
+ * @param siteName - The site name
2636
+ * @param userId - User ID
2637
+ * @param subscriptionId - Subscription ID
2638
+ */
2639
+ async resumeUserSubscription(siteName, userId, subscriptionId) {
2640
+ return this.create(
2641
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/resume`),
2642
+ {}
2643
+ );
2644
+ }
2645
+ /**
2646
+ * Cancel a user's subscription (admin only)
2647
+ * @param siteName - The site name
2648
+ * @param userId - User ID
2649
+ * @param subscriptionId - Subscription ID
2650
+ */
2651
+ async cancelUserSubscription(siteName, userId, subscriptionId) {
2652
+ return this.create(
2653
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/cancel`),
2654
+ {}
2655
+ );
2656
+ }
2657
+ /**
2658
+ * Get a user's credit balance (admin only)
2659
+ * @param siteName - The site name
2660
+ * @param userId - User ID
2661
+ */
2662
+ async getUserCreditBalance(siteName, userId) {
2663
+ return this.getSingle(
2664
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/credits/balance`)
2665
+ );
2666
+ }
2577
2667
  };
2578
2668
 
2579
2669
  // src/client/bundles-client.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perspectapi-ts-sdk",
3
- "version": "3.4.0",
3
+ "version": "3.5.1",
4
4
  "description": "TypeScript SDK for PerspectAPI - Cloudflare Workers compatible",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -355,6 +355,24 @@ export class SiteUsersClient extends BaseClient {
355
355
  );
356
356
  }
357
357
 
358
+ /**
359
+ * Create a Stripe Billing Portal session for updating payment methods
360
+ * @param siteName - The site name
361
+ * @param returnUrl - URL to redirect back to after portal session
362
+ * @param csrfToken - CSRF token (required)
363
+ */
364
+ async createBillingPortalSession(
365
+ siteName: string,
366
+ returnUrl: string,
367
+ csrfToken?: string
368
+ ): Promise<ApiResponse<{ url: string }>> {
369
+ return this.create<{ return_url: string }, { url: string }>(
370
+ this.siteUserEndpoint(siteName, '/users/me/billing-portal'),
371
+ { return_url: returnUrl },
372
+ csrfToken
373
+ );
374
+ }
375
+
358
376
  /**
359
377
  * Get linked newsletter subscriptions
360
378
  * @param siteName - The site name
@@ -496,4 +514,111 @@ export class SiteUsersClient extends BaseClient {
496
514
  data
497
515
  );
498
516
  }
517
+
518
+ // ============================================================================
519
+ // ADMIN USER-SCOPED ENDPOINTS (API key auth required)
520
+ // These mirror /me/* endpoints but target a specific user by ID.
521
+ // ============================================================================
522
+
523
+ /**
524
+ * Get a user's orders (admin only)
525
+ * @param siteName - The site name
526
+ * @param userId - User ID
527
+ * @param params - Pagination params
528
+ */
529
+ async getUserOrders(
530
+ siteName: string,
531
+ userId: string,
532
+ params?: { limit?: number; offset?: number }
533
+ ): Promise<ApiResponse<{ orders: SiteUserOrder[] }>> {
534
+ return this.http.get<{ orders: SiteUserOrder[] }>(
535
+ this.buildPath(this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/orders`)),
536
+ params
537
+ );
538
+ }
539
+
540
+ /**
541
+ * Get a user's subscriptions (admin only)
542
+ * @param siteName - The site name
543
+ * @param userId - User ID
544
+ */
545
+ async getUserSubscriptions(
546
+ siteName: string,
547
+ userId: string
548
+ ): Promise<ApiResponse<{ subscriptions: SiteUserSubscription[] }>> {
549
+ return this.getSingle<{ subscriptions: SiteUserSubscription[] }>(
550
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions`)
551
+ );
552
+ }
553
+
554
+ /**
555
+ * Pause a user's subscription (admin only)
556
+ * @param siteName - The site name
557
+ * @param userId - User ID
558
+ * @param subscriptionId - Subscription ID
559
+ * @param resumesAt - Optional ISO date string when subscription should auto-resume
560
+ */
561
+ async pauseUserSubscription(
562
+ siteName: string,
563
+ userId: string,
564
+ subscriptionId: string,
565
+ resumesAt?: string
566
+ ): Promise<ApiResponse<{ success: boolean }>> {
567
+ const body: Record<string, string> = {};
568
+ if (resumesAt) {
569
+ body.resumes_at = resumesAt;
570
+ }
571
+ return this.create<Record<string, string>, { success: boolean }>(
572
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/pause`),
573
+ body
574
+ );
575
+ }
576
+
577
+ /**
578
+ * Resume a user's paused subscription (admin only)
579
+ * @param siteName - The site name
580
+ * @param userId - User ID
581
+ * @param subscriptionId - Subscription ID
582
+ */
583
+ async resumeUserSubscription(
584
+ siteName: string,
585
+ userId: string,
586
+ subscriptionId: string
587
+ ): Promise<ApiResponse<{ success: boolean }>> {
588
+ return this.create<Record<string, never>, { success: boolean }>(
589
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/resume`),
590
+ {}
591
+ );
592
+ }
593
+
594
+ /**
595
+ * Cancel a user's subscription (admin only)
596
+ * @param siteName - The site name
597
+ * @param userId - User ID
598
+ * @param subscriptionId - Subscription ID
599
+ */
600
+ async cancelUserSubscription(
601
+ siteName: string,
602
+ userId: string,
603
+ subscriptionId: string
604
+ ): Promise<ApiResponse<{ success: boolean; message: string }>> {
605
+ return this.create<Record<string, never>, { success: boolean; message: string }>(
606
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/subscriptions/${encodeURIComponent(subscriptionId)}/cancel`),
607
+ {}
608
+ );
609
+ }
610
+
611
+ /**
612
+ * Get a user's credit balance (admin only)
613
+ * @param siteName - The site name
614
+ * @param userId - User ID
615
+ */
616
+ async getUserCreditBalance(
617
+ siteName: string,
618
+ userId: string
619
+ ): Promise<ApiResponse<CreditBalance>> {
620
+ return this.getSingle<CreditBalance>(
621
+ this.siteUserEndpoint(siteName, `/users/${encodeURIComponent(userId)}/credits/balance`)
622
+ );
623
+ }
499
624
  }
@@ -70,7 +70,7 @@ export const DEFAULT_IMAGE_SIZES: ResponsiveImageSizes = {
70
70
  /**
71
71
  * Build Cloudflare Image Resizing URL
72
72
  *
73
- * @param baseUrl - The base URL of your API (e.g., "https://api.perspect.co")
73
+ * @param baseUrl - The base URL of your API (e.g., "https://api.perspect.comm")
74
74
  * @param mediaPath - The path to the media file (e.g., "media/site/image.jpg")
75
75
  * @param options - Transform options
76
76
  * @returns Cloudflare Image Resizing URL
@@ -78,11 +78,11 @@ export const DEFAULT_IMAGE_SIZES: ResponsiveImageSizes = {
78
78
  * @example
79
79
  * ```typescript
80
80
  * const url = buildImageUrl(
81
- * 'https://api.perspect.co',
81
+ * 'https://api.perspect.comm',
82
82
  * 'media/mysite/photo.jpg',
83
83
  * { width: 400, format: 'webp', quality: 85 }
84
84
  * );
85
- * // Returns: '/cdn-cgi/image/width=400,format=webp,quality=85/https://api.perspect.co/media/mysite/photo.jpg'
85
+ * // Returns: '/cdn-cgi/image/width=400,format=webp,quality=85/https://api.perspect.comm/media/mysite/photo.jpg'
86
86
  * ```
87
87
  */
88
88
  export function buildImageUrl(
@@ -139,7 +139,7 @@ export function buildImageUrl(
139
139
  * @example
140
140
  * ```typescript
141
141
  * const urls = generateResponsiveUrls(
142
- * 'https://api.perspect.co',
142
+ * 'https://api.perspect.comm',
143
143
  * 'media/mysite/photo.jpg'
144
144
  * );
145
145
  * // Returns: { thumbnail: '...', small: '...', medium: '...', large: '...', original: '...' }
@@ -165,7 +165,7 @@ export function generateResponsiveUrls(
165
165
  * @example
166
166
  * ```typescript
167
167
  * const srcset = generateSrcSet(
168
- * 'https://api.perspect.co',
168
+ * 'https://api.perspect.comm',
169
169
  * 'media/mysite/photo.jpg',
170
170
  * [400, 800, 1200]
171
171
  * );
@@ -220,7 +220,7 @@ export function generateSizesAttribute(
220
220
  * @example
221
221
  * ```typescript
222
222
  * const html = generateResponsiveImageHtml(
223
- * 'https://api.perspect.co',
223
+ * 'https://api.perspect.comm',
224
224
  * 'media/mysite/photo.jpg',
225
225
  * 'My photo',
226
226
  * { className: 'rounded-lg', loading: 'lazy' }
@@ -271,7 +271,7 @@ export function generateResponsiveImageHtml(
271
271
  * const media = product.data.media?.[0];
272
272
  *
273
273
  * if (media) {
274
- * const urls = transformMediaItem('https://api.perspect.co', media);
274
+ * const urls = transformMediaItem('https://api.perspect.comm', media);
275
275
  * console.log(urls.thumbnail); // Cloudflare-transformed thumbnail URL
276
276
  * }
277
277
  * ```