@stackbe/sdk 0.1.0 → 0.2.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.
package/dist/index.d.mts CHANGED
@@ -7,6 +7,7 @@ interface HttpClientConfig {
7
7
  declare class HttpClient {
8
8
  private config;
9
9
  constructor(config: HttpClientConfig);
10
+ get baseUrl(): string;
10
11
  private request;
11
12
  get<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
12
13
  post<T>(path: string, body?: unknown, params?: Record<string, string | number | undefined>): Promise<T>;
@@ -109,6 +110,12 @@ interface UpdateCustomerOptions {
109
110
  name?: string;
110
111
  metadata?: Record<string, unknown>;
111
112
  }
113
+ interface MagicLinkOptions {
114
+ /** URL to redirect to after authentication */
115
+ redirectUrl?: string;
116
+ /** Use development callback URL (for localhost testing) */
117
+ useDev?: boolean;
118
+ }
112
119
  interface MagicLinkResponse {
113
120
  success: boolean;
114
121
  message: string;
@@ -124,6 +131,64 @@ interface SessionResponse {
124
131
  subscription?: Subscription;
125
132
  entitlements: Record<string, boolean | number | string>;
126
133
  }
134
+ interface CreateCheckoutOptions {
135
+ /** Customer ID or email */
136
+ customer: string | {
137
+ email: string;
138
+ name?: string;
139
+ };
140
+ /** Plan ID to subscribe to */
141
+ planId: string;
142
+ /** URL to redirect after successful checkout */
143
+ successUrl: string;
144
+ /** URL to redirect if checkout is canceled */
145
+ cancelUrl?: string;
146
+ /** Allow promotion codes */
147
+ allowPromotionCodes?: boolean;
148
+ /** Trial period in days */
149
+ trialDays?: number;
150
+ /** Metadata to attach to the subscription */
151
+ metadata?: Record<string, string>;
152
+ }
153
+ interface CheckoutSessionResponse {
154
+ /** Checkout session ID */
155
+ id: string;
156
+ /** URL to redirect customer to for checkout */
157
+ url: string;
158
+ /** Session status */
159
+ status: 'open' | 'complete' | 'expired';
160
+ /** Customer ID */
161
+ customerId: string;
162
+ /** Expiration time */
163
+ expiresAt: string;
164
+ }
165
+ interface SubscriptionWithPlan extends Subscription {
166
+ plan: {
167
+ id: string;
168
+ name: string;
169
+ price: number;
170
+ interval: 'month' | 'year';
171
+ currency: string;
172
+ };
173
+ }
174
+ interface CancelSubscriptionOptions {
175
+ /** Cancel immediately or at end of billing period */
176
+ immediate?: boolean;
177
+ /** Reason for cancellation */
178
+ reason?: string;
179
+ }
180
+ interface CancelSubscriptionResponse {
181
+ success: boolean;
182
+ subscription: Subscription;
183
+ /** When the subscription will actually end */
184
+ endsAt: string;
185
+ }
186
+ interface UpdateSubscriptionOptions {
187
+ /** New plan ID to switch to */
188
+ planId?: string;
189
+ /** Proration behavior */
190
+ prorate?: boolean;
191
+ }
127
192
  interface StackBEErrorResponse {
128
193
  statusCode: number;
129
194
  message: string;
@@ -347,14 +412,275 @@ declare class CustomersClient {
347
412
  getSession(token: string): Promise<SessionResponse>;
348
413
  }
349
414
 
415
+ declare class CheckoutClient {
416
+ private http;
417
+ private appId;
418
+ constructor(http: HttpClient, appId: string);
419
+ /**
420
+ * Create a checkout session for a customer to subscribe to a plan.
421
+ * Returns a URL to redirect the customer to Stripe checkout.
422
+ *
423
+ * @example
424
+ * ```typescript
425
+ * // With existing customer ID
426
+ * const { url } = await stackbe.checkout.createSession({
427
+ * customer: 'cust_123',
428
+ * planId: 'plan_pro_monthly',
429
+ * successUrl: 'https://myapp.com/success',
430
+ * cancelUrl: 'https://myapp.com/pricing',
431
+ * });
432
+ *
433
+ * // Redirect to checkout
434
+ * res.redirect(url);
435
+ * ```
436
+ *
437
+ * @example
438
+ * ```typescript
439
+ * // With new customer (will be created)
440
+ * const { url } = await stackbe.checkout.createSession({
441
+ * customer: { email: 'user@example.com', name: 'John' },
442
+ * planId: 'plan_pro_monthly',
443
+ * successUrl: 'https://myapp.com/success',
444
+ * trialDays: 14,
445
+ * });
446
+ * ```
447
+ */
448
+ createSession(options: CreateCheckoutOptions): Promise<CheckoutSessionResponse>;
449
+ /**
450
+ * Get an existing checkout session by ID.
451
+ *
452
+ * @example
453
+ * ```typescript
454
+ * const session = await stackbe.checkout.getSession('cs_123');
455
+ * if (session.status === 'complete') {
456
+ * // Payment successful
457
+ * }
458
+ * ```
459
+ */
460
+ getSession(sessionId: string): Promise<CheckoutSessionResponse>;
461
+ /**
462
+ * Generate a checkout URL for a plan.
463
+ * Convenience method that creates a session and returns just the URL.
464
+ *
465
+ * @example
466
+ * ```typescript
467
+ * const checkoutUrl = await stackbe.checkout.getCheckoutUrl({
468
+ * customer: 'cust_123',
469
+ * planId: 'plan_pro_monthly',
470
+ * successUrl: 'https://myapp.com/success',
471
+ * });
472
+ *
473
+ * // Send to frontend
474
+ * res.json({ checkoutUrl });
475
+ * ```
476
+ */
477
+ getCheckoutUrl(options: CreateCheckoutOptions): Promise<string>;
478
+ }
479
+
480
+ declare class SubscriptionsClient {
481
+ private http;
482
+ constructor(http: HttpClient);
483
+ /**
484
+ * Get a customer's current active subscription.
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * const subscription = await stackbe.subscriptions.get('cust_123');
489
+ *
490
+ * if (subscription) {
491
+ * console.log(`Plan: ${subscription.plan.name}`);
492
+ * console.log(`Status: ${subscription.status}`);
493
+ * console.log(`Renews: ${subscription.currentPeriodEnd}`);
494
+ * } else {
495
+ * console.log('No active subscription');
496
+ * }
497
+ * ```
498
+ */
499
+ get(customerId: string): Promise<SubscriptionWithPlan | null>;
500
+ /**
501
+ * Get a subscription by ID.
502
+ *
503
+ * @example
504
+ * ```typescript
505
+ * const subscription = await stackbe.subscriptions.getById('sub_123');
506
+ * ```
507
+ */
508
+ getById(subscriptionId: string): Promise<SubscriptionWithPlan>;
509
+ /**
510
+ * List all subscriptions for a customer.
511
+ *
512
+ * @example
513
+ * ```typescript
514
+ * const subscriptions = await stackbe.subscriptions.list('cust_123');
515
+ * ```
516
+ */
517
+ list(customerId: string): Promise<Subscription[]>;
518
+ /**
519
+ * Cancel a subscription.
520
+ *
521
+ * @example
522
+ * ```typescript
523
+ * // Cancel at end of billing period (default)
524
+ * await stackbe.subscriptions.cancel('sub_123');
525
+ *
526
+ * // Cancel immediately
527
+ * await stackbe.subscriptions.cancel('sub_123', { immediate: true });
528
+ *
529
+ * // Cancel with reason
530
+ * await stackbe.subscriptions.cancel('sub_123', {
531
+ * reason: 'Too expensive'
532
+ * });
533
+ * ```
534
+ */
535
+ cancel(subscriptionId: string, options?: CancelSubscriptionOptions): Promise<CancelSubscriptionResponse>;
536
+ /**
537
+ * Update a subscription (change plan).
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * // Upgrade/downgrade to a different plan
542
+ * await stackbe.subscriptions.update('sub_123', {
543
+ * planId: 'plan_enterprise_monthly',
544
+ * prorate: true,
545
+ * });
546
+ * ```
547
+ */
548
+ update(subscriptionId: string, options: UpdateSubscriptionOptions): Promise<Subscription>;
549
+ /**
550
+ * Reactivate a canceled subscription (before it ends).
551
+ *
552
+ * @example
553
+ * ```typescript
554
+ * // Customer changed their mind
555
+ * await stackbe.subscriptions.reactivate('sub_123');
556
+ * ```
557
+ */
558
+ reactivate(subscriptionId: string): Promise<Subscription>;
559
+ /**
560
+ * Check if a customer has an active subscription.
561
+ *
562
+ * @example
563
+ * ```typescript
564
+ * const isActive = await stackbe.subscriptions.isActive('cust_123');
565
+ * if (!isActive) {
566
+ * return res.redirect('/pricing');
567
+ * }
568
+ * ```
569
+ */
570
+ isActive(customerId: string): Promise<boolean>;
571
+ }
572
+
573
+ declare class AuthClient {
574
+ private http;
575
+ private appId;
576
+ constructor(http: HttpClient, appId: string);
577
+ /**
578
+ * Send a magic link email to a customer for passwordless authentication.
579
+ *
580
+ * @example
581
+ * ```typescript
582
+ * // Send magic link
583
+ * await stackbe.auth.sendMagicLink('user@example.com');
584
+ *
585
+ * // With redirect URL
586
+ * await stackbe.auth.sendMagicLink('user@example.com', {
587
+ * redirectUrl: 'https://myapp.com/dashboard',
588
+ * });
589
+ *
590
+ * // For localhost development
591
+ * await stackbe.auth.sendMagicLink('user@example.com', {
592
+ * useDev: true,
593
+ * });
594
+ * ```
595
+ */
596
+ sendMagicLink(email: string, options?: MagicLinkOptions): Promise<MagicLinkResponse>;
597
+ /**
598
+ * Verify a magic link token and get a session token.
599
+ * Call this when the user clicks the magic link.
600
+ *
601
+ * @example
602
+ * ```typescript
603
+ * // In your /verify route handler
604
+ * const { token } = req.query;
605
+ *
606
+ * const result = await stackbe.auth.verifyToken(token);
607
+ *
608
+ * if (result.valid) {
609
+ * // Set session cookie
610
+ * res.cookie('session', result.token, { httpOnly: true });
611
+ * res.redirect('/dashboard');
612
+ * } else {
613
+ * res.redirect('/login?error=invalid_token');
614
+ * }
615
+ * ```
616
+ */
617
+ verifyToken(token: string): Promise<VerifyTokenResponse>;
618
+ /**
619
+ * Get the current session for an authenticated customer.
620
+ * Use this to validate session tokens and get customer data.
621
+ *
622
+ * @example
623
+ * ```typescript
624
+ * // Validate session on each request
625
+ * const sessionToken = req.cookies.session;
626
+ *
627
+ * const session = await stackbe.auth.getSession(sessionToken);
628
+ *
629
+ * if (session) {
630
+ * req.customer = session.customer;
631
+ * req.subscription = session.subscription;
632
+ * req.entitlements = session.entitlements;
633
+ * }
634
+ * ```
635
+ */
636
+ getSession(sessionToken: string): Promise<SessionResponse | null>;
637
+ /**
638
+ * Create Express middleware that validates session tokens.
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * // Protect routes with authentication
643
+ * app.use('/dashboard', stackbe.auth.middleware({
644
+ * getToken: (req) => req.cookies.session,
645
+ * onUnauthenticated: (req, res) => res.redirect('/login'),
646
+ * }));
647
+ *
648
+ * app.get('/dashboard', (req, res) => {
649
+ * // req.customer is available
650
+ * res.json({ email: req.customer.email });
651
+ * });
652
+ * ```
653
+ */
654
+ middleware(options: {
655
+ getToken: (req: any) => string | undefined;
656
+ onUnauthenticated?: (req: any, res: any) => void;
657
+ }): (req: any, res: any, next: any) => Promise<any>;
658
+ /**
659
+ * Check if a session token is valid.
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * const isValid = await stackbe.auth.isAuthenticated(sessionToken);
664
+ * ```
665
+ */
666
+ isAuthenticated(sessionToken: string): Promise<boolean>;
667
+ }
668
+
350
669
  declare class StackBE {
351
670
  private http;
671
+ private appId;
352
672
  /** Usage tracking and limits */
353
673
  readonly usage: UsageClient;
354
674
  /** Feature entitlements */
355
675
  readonly entitlements: EntitlementsClient;
356
676
  /** Customer management */
357
677
  readonly customers: CustomersClient;
678
+ /** Checkout sessions for Stripe */
679
+ readonly checkout: CheckoutClient;
680
+ /** Subscription management */
681
+ readonly subscriptions: SubscriptionsClient;
682
+ /** Customer authentication (magic links) */
683
+ readonly auth: AuthClient;
358
684
  /**
359
685
  * Create a new StackBE client.
360
686
  *
@@ -373,8 +699,18 @@ declare class StackBE {
373
699
  * // Check entitlements
374
700
  * const { hasAccess } = await stackbe.entitlements.check('customer_123', 'premium');
375
701
  *
376
- * // Get customer
377
- * const customer = await stackbe.customers.get('customer_123');
702
+ * // Create checkout session
703
+ * const { url } = await stackbe.checkout.createSession({
704
+ * customer: 'cust_123',
705
+ * planId: 'plan_pro',
706
+ * successUrl: 'https://myapp.com/success',
707
+ * });
708
+ *
709
+ * // Get subscription
710
+ * const subscription = await stackbe.subscriptions.get('cust_123');
711
+ *
712
+ * // Send magic link
713
+ * await stackbe.auth.sendMagicLink('user@example.com');
378
714
  * ```
379
715
  */
380
716
  constructor(config: StackBEConfig);
@@ -445,4 +781,4 @@ declare class StackBE {
445
781
  }): (req: any, res: any, next: any) => Promise<any>;
446
782
  }
447
783
 
448
- export { type CheckEntitlementResponse, type CheckUsageResponse, type CreateCustomerOptions, type Customer, type CustomerUsageResponse, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type MagicLinkResponse, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorResponse, type Subscription, type TrackUsageOptions, type TrackUsageResponse, type UpdateCustomerOptions, UsageClient, type UsageMetric, type VerifyTokenResponse };
784
+ export { AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type Customer, type CustomerUsageResponse, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type MagicLinkOptions, type MagicLinkResponse, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorResponse, type Subscription, type SubscriptionWithPlan, SubscriptionsClient, type TrackUsageOptions, type TrackUsageResponse, type UpdateCustomerOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse };