@buildbase/sdk 0.0.27 → 0.0.29

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.
@@ -0,0 +1,3180 @@
1
+ import { z } from 'zod';
2
+ import * as react from 'react';
3
+ import react__default, { ReactNode } from 'react';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
+
6
+ interface IDocument {
7
+ _id: string;
8
+ /** Optional; some APIs only return _id. Prefer _id for identity. */
9
+ id?: string;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ deleted: boolean;
13
+ }
14
+ interface IUser extends IDocument {
15
+ _id: string;
16
+ name: string;
17
+ email: string;
18
+ /** Profile image URL. Often omitted or empty from API. */
19
+ image?: string;
20
+ role: string;
21
+ /** ISO country code. May be omitted. */
22
+ country?: string;
23
+ /** IANA timezone. May be omitted. */
24
+ timezone?: string;
25
+ /** Language code. May be omitted. */
26
+ language?: string;
27
+ /** Currency code. May be omitted. */
28
+ currency?: string;
29
+ attributes?: Record<string, string | number | boolean>;
30
+ }
31
+ interface IAsset extends IDocument {
32
+ _id: string;
33
+ createdAt: string;
34
+ updatedAt: string;
35
+ deleted: boolean;
36
+ name: string;
37
+ uniqueName: string;
38
+ mimeType: string;
39
+ size: number;
40
+ encoding: string;
41
+ bucket: {
42
+ name: string;
43
+ url: string;
44
+ path: string;
45
+ };
46
+ metadata: {
47
+ [key: string]: string | number | boolean | object | null;
48
+ };
49
+ image?: {
50
+ width: number;
51
+ height: number;
52
+ };
53
+ tags: string[];
54
+ public: boolean;
55
+ creator: string | IUser;
56
+ }
57
+ type BillingInterval = 'monthly' | 'yearly' | 'quarterly';
58
+ interface ISubscription {
59
+ _id: string;
60
+ subscriptionStatus: 'active' | 'trialing' | 'canceled' | 'past_due' | 'paused' | 'incomplete' | 'unpaid';
61
+ stripePriceId?: string;
62
+ stripeCurrentPeriodEnd?: string;
63
+ cancelAtPeriodEnd: boolean;
64
+ billingInterval?: BillingInterval;
65
+ /** Trial start date (ISO string). Set when subscription is in trial. */
66
+ trialStart?: string;
67
+ /** Trial end date (ISO string). Set when subscription is in trial. */
68
+ trialEnd?: string;
69
+ /** When the subscription was canceled (ISO string). Soft-delete marker. */
70
+ canceledAt?: string;
71
+ /** Dunning state: 'none', 'notified', 'warning', 'final', 'suspended'. */
72
+ dunningState?: string;
73
+ /** Whether this subscription uses per-seat pricing. */
74
+ seatPricingEnabled?: boolean;
75
+ /** Current billable seat count. */
76
+ currentSeatCount?: number;
77
+ createdAt: string;
78
+ updatedAt: string;
79
+ plan?: {
80
+ _id: string;
81
+ name: string;
82
+ slug: string;
83
+ description?: string;
84
+ /** Stripe currency code (e.g. 'usd', 'inr', 'eur'). */
85
+ currency?: string;
86
+ };
87
+ }
88
+ interface ISubscriptionItem {
89
+ _id: string;
90
+ type: 'feature' | 'limit' | 'quota';
91
+ name: string;
92
+ slug: string;
93
+ description?: string;
94
+ category: string;
95
+ }
96
+ /** Per-interval quota value (plan-group/versions and public plans schema). */
97
+ interface IQuotaIntervalValue {
98
+ included: number;
99
+ /** Overage price in cents. Omitted in public plans; use pricingVariant.quotaOverages for display. */
100
+ overage?: number;
101
+ /** Stripe price ID for overage. Omitted in public plans; use pricingVariant.quotaOveragePriceIds. */
102
+ priceId?: string;
103
+ /** Unit size for overage pricing (e.g. 1000 = price per 1000 units). */
104
+ unitSize?: number;
105
+ }
106
+ /** Quota defined per billing interval (new plan-group/versions schema) */
107
+ interface IQuotaByInterval {
108
+ monthly?: IQuotaIntervalValue;
109
+ yearly?: IQuotaIntervalValue;
110
+ quarterly?: IQuotaIntervalValue;
111
+ }
112
+ /** Base pricing per interval. Values are often in cents (Stripe); convert for display. */
113
+ interface IBasePricing {
114
+ monthly: number;
115
+ yearly: number;
116
+ quarterly: number;
117
+ }
118
+ /** Stripe price IDs per billing interval (for a single currency variant). */
119
+ interface IStripePricesByInterval {
120
+ monthlyPriceId?: string;
121
+ yearlyPriceId?: string;
122
+ quarterlyPriceId?: string;
123
+ monthly?: string;
124
+ yearly?: string;
125
+ }
126
+ /** Overage amounts in cents per interval, keyed by quota slug. Used in pricing variants. */
127
+ type IQuotaOveragesByInterval = Record<string, {
128
+ monthly?: number;
129
+ yearly?: number;
130
+ quarterly?: number;
131
+ }>;
132
+ /** Overage Stripe price IDs per interval, keyed by quota slug. Used in pricing variants. */
133
+ type IQuotaOveragePriceIdsByInterval = Record<string, {
134
+ monthly?: string;
135
+ yearly?: string;
136
+ quarterly?: string;
137
+ }>;
138
+ /**
139
+ * Multi-currency pricing variant at plan version level.
140
+ * Each plan version can have multiple variants (e.g. usd, eur, inr, sgd).
141
+ */
142
+ interface IPricingVariant {
143
+ _id: string;
144
+ currency: string;
145
+ basePricing: IBasePricing;
146
+ stripePrices: IStripePricesByInterval;
147
+ /** Per-seat pricing config. When enabled, a second recurring item is on the subscription. */
148
+ seatPricing?: {
149
+ enabled: boolean;
150
+ includedSeats: number;
151
+ /** Maximum seats allowed. 0 or undefined = unlimited. */
152
+ maxSeats?: number;
153
+ perSeat: IBasePricing;
154
+ };
155
+ /** Stripe Price IDs for the per-seat recurring price. */
156
+ seatStripePrices?: IStripePricesByInterval;
157
+ /** Overage cents per quota slug per interval. */
158
+ quotaOverages?: IQuotaOveragesByInterval;
159
+ /** Stripe price IDs for overage per quota slug per interval. */
160
+ quotaOveragePriceIds?: IQuotaOveragePriceIdsByInterval;
161
+ }
162
+ interface IPlanVersion {
163
+ _id: string;
164
+ version: number;
165
+ name: string;
166
+ status: 'draft' | 'published';
167
+ features?: Record<string, boolean>;
168
+ limits?: Record<string, number>;
169
+ /** Per-interval quotas (included, unitSize; overage from pricingVariant.quotaOverages). */
170
+ quotas?: Record<string, IQuotaByInterval>;
171
+ /** Multi-currency pricing. Each variant has currency, basePricing, stripePrices, quotaOverages. */
172
+ pricingVariants?: IPricingVariant[];
173
+ subscriptionItems?: ISubscriptionItem[];
174
+ isCurrent?: boolean;
175
+ isLegacy?: boolean;
176
+ archived?: boolean;
177
+ deleted?: boolean;
178
+ createdAt?: string;
179
+ updatedAt?: string;
180
+ id?: string;
181
+ stripeProductId?: string;
182
+ }
183
+ /** Plan version summary (e.g. plan.latestVersion from subscription API) with subscriptionItems as IDs. */
184
+ interface IPlanVersionSummary extends Omit<IPlanVersion, 'subscriptionItems'> {
185
+ subscriptionItems?: string[];
186
+ }
187
+ interface IPlan {
188
+ _id: string;
189
+ name: string;
190
+ slug: string;
191
+ description?: string;
192
+ /** Stripe currency code (e.g. 'usd', 'inr', 'eur'). Used for pricing display. */
193
+ currency?: string;
194
+ latestVersion?: IPlanVersionSummary;
195
+ archived?: boolean;
196
+ deleted?: boolean;
197
+ createdAt?: string;
198
+ updatedAt?: string;
199
+ id?: string;
200
+ }
201
+ interface IPlanGroupLatestVersion {
202
+ _id: string;
203
+ version: number;
204
+ planVersionIds: string[];
205
+ requiredItems: string[];
206
+ status: 'draft' | 'published';
207
+ isCurrent?: boolean;
208
+ isLegacy?: boolean;
209
+ archived?: boolean;
210
+ deleted?: boolean;
211
+ createdAt?: string;
212
+ updatedAt?: string;
213
+ description?: string;
214
+ }
215
+ interface IPlanGroup {
216
+ _id: string;
217
+ name: string;
218
+ slug: string;
219
+ description?: string;
220
+ latestVersion?: IPlanGroupLatestVersion;
221
+ archived?: boolean;
222
+ deleted?: boolean;
223
+ createdAt?: string;
224
+ updatedAt?: string;
225
+ id?: string;
226
+ }
227
+ interface IPlanGroupVersion {
228
+ _id: string;
229
+ version: number;
230
+ description?: string;
231
+ group?: {
232
+ _id: string;
233
+ name: string;
234
+ description?: string;
235
+ };
236
+ planVersionIds: IPlanVersionWithPlan[] | string[];
237
+ requiredItems?: string[];
238
+ status?: 'draft' | 'published';
239
+ isCurrent?: boolean;
240
+ isLegacy?: boolean;
241
+ archived?: boolean;
242
+ deleted?: boolean;
243
+ createdAt?: string;
244
+ updatedAt?: string;
245
+ id?: string;
246
+ }
247
+ interface ISubscriptionResponse {
248
+ subscription: ISubscription | null;
249
+ planVersion: IPlanVersion | null;
250
+ plan: IPlan | null;
251
+ group: IPlanGroup | null;
252
+ groupVersion: IPlanGroupVersion | null;
253
+ }
254
+ /** Plan version with nested plan info (name, slug, currency for display). */
255
+ interface IPlanVersionWithPlan extends IPlanVersion {
256
+ plan: IPlan;
257
+ }
258
+ /**
259
+ * Plan group version with full plan versions (for GET .../plan-group/versions).
260
+ * Each plan has plan, subscriptionItems, quotas (per-interval), pricingVariants.
261
+ */
262
+ interface IPlanGroupVersionWithPlans {
263
+ _id: string;
264
+ version: number;
265
+ description?: string;
266
+ /** Full plan versions with nested plan (name, slug, currency). */
267
+ plans: IPlanVersionWithPlan[];
268
+ isCurrent?: boolean;
269
+ whatsNew?: {
270
+ newPlans: IPlanVersionWithPlan[];
271
+ updatedPlans: IPlanVersionWithPlan[];
272
+ removedPlans: IPlanVersionWithPlan[];
273
+ };
274
+ }
275
+ interface IPlanGroupInfo {
276
+ _id: string;
277
+ name: string;
278
+ slug: string;
279
+ description?: string;
280
+ }
281
+ /** Response from GET workspaces/:id/subscription/plan-group (and by version). */
282
+ interface IPlanGroupResponse {
283
+ /** Plan group with latestVersion, archived, deleted, timestamps. May be null in some API responses. */
284
+ group: IPlanGroup | null;
285
+ /** Current group version with populated planVersionIds (or IDs). */
286
+ groupVersion: IPlanGroupVersion;
287
+ /** Full plan versions for display (subscriptionItems, pricingVariants, quotas). */
288
+ plans: IPlanVersionWithPlan[];
289
+ }
290
+ /**
291
+ * Response from GET workspaces/:workspaceId/subscription/plan-group/versions.
292
+ * Group summary plus current and available group versions; each version has plans with
293
+ * per-interval quotas and pricingVariants.
294
+ */
295
+ interface IPlanGroupVersionsResponse {
296
+ /** Plan group summary (_id, name, slug). */
297
+ group: IPlanGroupInfo;
298
+ /** Current group version (user's version when subscribed, or latest published when not). */
299
+ currentVersion: IPlanGroupVersionWithPlans;
300
+ /** Newer versions when user has subscription; empty when no subscription. */
301
+ availableVersions: IPlanGroupVersionWithPlans[];
302
+ }
303
+ /** Request body for POST .../workspaces/:id/subscription/checkout. Only these fields are allowed. */
304
+ interface ICheckoutSessionRequest {
305
+ planVersionId: string;
306
+ billingInterval?: BillingInterval;
307
+ currency?: string;
308
+ successUrl?: string;
309
+ cancelUrl?: string;
310
+ }
311
+ interface ICheckoutSessionResponse {
312
+ /** Response type discriminator. Added for centralized checkout flow. */
313
+ type?: 'checkout' | 'trial_started' | 'existing';
314
+ success: boolean;
315
+ checkoutUrl: string;
316
+ sessionId: string;
317
+ message: string;
318
+ planVersion?: {
319
+ _id: string;
320
+ version: number;
321
+ name: string;
322
+ };
323
+ }
324
+ /** No-card trial started server-side; no redirect needed. */
325
+ interface ICheckoutTrialResult {
326
+ type: 'trial_started';
327
+ success: boolean;
328
+ checkoutUrl: null;
329
+ sessionId: null;
330
+ subscription: ISubscription;
331
+ message: string;
332
+ }
333
+ /** Workspace already has a matching active subscription. */
334
+ interface ICheckoutExistingResult {
335
+ type: 'existing';
336
+ success: boolean;
337
+ checkoutUrl: null;
338
+ sessionId: null;
339
+ message: string;
340
+ existingSubscription?: {
341
+ _id: string;
342
+ subscriptionStatus: string;
343
+ stripePriceId?: string;
344
+ };
345
+ }
346
+ /**
347
+ * Discriminated union for POST /subscription/checkout responses.
348
+ * - `checkout`: Stripe checkout session created, redirect user to checkoutUrl
349
+ * - `trial_started`: No-card trial started server-side, no redirect needed
350
+ * - `existing`: Workspace already has a matching subscription
351
+ */
352
+ type CheckoutResult = (ICheckoutSessionResponse & {
353
+ type: 'checkout';
354
+ }) | ICheckoutTrialResult | ICheckoutExistingResult;
355
+ /** Request body for PATCH .../workspaces/:id/subscription. Only these fields are allowed. */
356
+ interface ISubscriptionUpdateRequest {
357
+ planVersionId: string;
358
+ billingInterval?: BillingInterval;
359
+ successUrl?: string;
360
+ cancelUrl?: string;
361
+ }
362
+ interface ISubscriptionUpdateResponse {
363
+ _id: string;
364
+ subscriptionStatus: string;
365
+ workspace: string;
366
+ planVersion: string;
367
+ plan: string;
368
+ planGroup?: string;
369
+ planGroupVersion?: string;
370
+ cancelAtPeriodEnd: boolean;
371
+ createdAt: string;
372
+ updatedAt: string;
373
+ }
374
+ interface IPublicPlanItemCategory {
375
+ name: string;
376
+ slug: string;
377
+ }
378
+ interface IPublicPlanItem {
379
+ _id: string;
380
+ name: string;
381
+ slug: string;
382
+ description?: string;
383
+ type: 'feature' | 'limit' | 'quota';
384
+ category: IPublicPlanItemCategory;
385
+ }
386
+ /**
387
+ * Public plan version (e.g. from GET /api/v1/public/:orgId/plans/:slug).
388
+ * Each plan has _id, name (plan display name), version, status, pricingVariants, quotas, features, limits.
389
+ * Pricing is in cents (see response.notes).
390
+ */
391
+ interface IPublicPlanVersion {
392
+ _id: string;
393
+ /** Plan display name (e.g. "Pro", "Base Plan"). */
394
+ name: string;
395
+ version: number;
396
+ status: 'draft' | 'published';
397
+ /** Multi-currency pricing. Use getBasePriceCents(plan, currency, interval) and getQuotaDisplayWithVariant for display. */
398
+ pricingVariants?: IPricingVariant[];
399
+ /** Keyed by item slug. Per-interval: included, unitSize; overage from pricingVariant.quotaOverages. */
400
+ quotas: Record<string, IQuotaByInterval>;
401
+ features: Record<string, boolean>;
402
+ limits: Record<string, number>;
403
+ }
404
+ interface IPublicPlansResponse {
405
+ items: IPublicPlanItem[];
406
+ plans: IPublicPlanVersion[];
407
+ /** Optional note from API (e.g. "Pricing is in cents. Please convert to dollars for display."). */
408
+ notes?: string;
409
+ }
410
+ type InvoiceStatus = 'draft' | 'open' | 'paid' | 'uncollectible' | 'void';
411
+ interface IInvoice {
412
+ id: string;
413
+ amount_due: number;
414
+ number: string | null;
415
+ amount_paid: number;
416
+ currency: string;
417
+ status: InvoiceStatus;
418
+ created: number;
419
+ due_date: number | null;
420
+ hosted_invoice_url: string;
421
+ invoice_pdf: string | null;
422
+ description: string | null;
423
+ subscription: string;
424
+ }
425
+ interface IInvoiceListResponse {
426
+ success: boolean;
427
+ invoices: IInvoice[];
428
+ has_more: boolean;
429
+ }
430
+ interface IInvoiceResponse {
431
+ success: boolean;
432
+ invoice: IInvoice;
433
+ }
434
+ /** Request body for POST .../workspaces/:id/subscription/usage */
435
+ interface IRecordUsageRequest {
436
+ quotaSlug: string;
437
+ quantity: number;
438
+ metadata?: Record<string, unknown>;
439
+ source?: string;
440
+ idempotencyKey?: string;
441
+ }
442
+ /** Response from POST .../workspaces/:id/subscription/usage */
443
+ interface IRecordUsageResponse {
444
+ used: number;
445
+ consumed: number;
446
+ included: number;
447
+ available: number;
448
+ overage: number;
449
+ billedAsync: boolean;
450
+ }
451
+ /** Single quota usage status (shared between status and all endpoints). */
452
+ interface IQuotaUsageStatus {
453
+ consumed: number;
454
+ included: number;
455
+ available: number;
456
+ overage: number;
457
+ hasOverage: boolean;
458
+ }
459
+ /** Response from GET .../workspaces/:id/subscription/usage/status?quotaSlug=X */
460
+ interface IQuotaUsageStatusResponse extends IQuotaUsageStatus {
461
+ quotaSlug: string;
462
+ }
463
+ /** Response from GET .../workspaces/:id/subscription/usage/all */
464
+ interface IAllQuotaUsageResponse {
465
+ quotas: Record<string, IQuotaUsageStatus>;
466
+ }
467
+ /** Single usage log entry from GET .../usage/logs */
468
+ interface IUsageLogEntry {
469
+ _id: string;
470
+ quotaSlug: string;
471
+ quantity: number;
472
+ source?: string;
473
+ workspace: string;
474
+ createdAt: string;
475
+ updatedAt: string;
476
+ }
477
+ /** Query parameters for GET .../workspaces/:id/subscription/usage/logs */
478
+ interface IUsageLogsQuery {
479
+ quotaSlug?: string;
480
+ from?: string;
481
+ to?: string;
482
+ source?: string;
483
+ page?: number;
484
+ limit?: number;
485
+ }
486
+ /** Paginated response from GET .../workspaces/:id/subscription/usage/logs */
487
+ interface IUsageLogsResponse {
488
+ docs: IUsageLogEntry[];
489
+ totalDocs: number;
490
+ limit: number;
491
+ page: number;
492
+ totalPages: number;
493
+ hasNextPage: boolean;
494
+ hasPrevPage: boolean;
495
+ }
496
+
497
+ interface IWorkspace {
498
+ _id: string;
499
+ name: string;
500
+ image?: string;
501
+ workspaceId: string;
502
+ users: IUser[];
503
+ roles: string[];
504
+ createdBy: string | IUser;
505
+ features: Record<string, boolean>;
506
+ /**
507
+ * Quota usage tracking: { [quotaSlug]: number } – how much of each quota has been used.
508
+ */
509
+ quotas?: Record<string, number>;
510
+ /**
511
+ * Subscription limits snapshot: { [limitSlug]: number | null } – synced from subscription plan.
512
+ * Limits are maximum values (e.g. max-users, max-workspaces). Updated when subscription is assigned/updated.
513
+ */
514
+ limits?: Record<string, number | null>;
515
+ subscription?: ISubscription | string | null;
516
+ /** Stripe Customer ID for this workspace. */
517
+ stripeCustomerId?: string;
518
+ /**
519
+ * Billing currency locked for this workspace (set on first subscription).
520
+ * Stripe allows one currency per customer; all future subscriptions must use this currency.
521
+ * When set, subscription UI only shows/uses this currency.
522
+ */
523
+ billingCurrency?: string | null;
524
+ /** Workspace onboarding config. Set on creation based on org settings. SDK shows trial CTA. */
525
+ pendingOnboarding?: {
526
+ mode: 'trial';
527
+ planVersionId: string;
528
+ } | null;
529
+ }
530
+ interface IWorkspaceFeature {
531
+ _id: string;
532
+ name: string;
533
+ description: string;
534
+ userManaged: boolean;
535
+ defaultValue: boolean;
536
+ slug: string;
537
+ category: string;
538
+ createdAt: Date;
539
+ updatedAt: Date;
540
+ }
541
+ interface IWorkspaceUser {
542
+ _id: string;
543
+ workspace: string | IWorkspace;
544
+ user: string | IUser;
545
+ role: string;
546
+ }
547
+
548
+ /**
549
+ * Event types for all SDK events
550
+ */
551
+ type EventType = 'user:created' | 'user:updated' | 'workspace:changed' | 'workspace:updated' | 'workspace:user-added' | 'workspace:user-removed' | 'workspace:user-role-changed' | 'workspace:created' | 'workspace:deleted';
552
+ /**
553
+ * Event data types for each event
554
+ */
555
+ interface UserCreatedEventData {
556
+ user: IUser;
557
+ }
558
+ interface UserUpdatedEventData {
559
+ user: IUser;
560
+ previousUser?: IUser;
561
+ }
562
+ interface WorkspaceChangedEventData {
563
+ workspace: IWorkspace;
564
+ previousWorkspace?: IWorkspace | null;
565
+ }
566
+ interface WorkspaceUpdatedEventData {
567
+ workspace: IWorkspace;
568
+ }
569
+ interface WorkspaceUserAddedEventData {
570
+ userId: string;
571
+ workspace: IWorkspace;
572
+ role: string;
573
+ }
574
+ interface WorkspaceUserRemovedEventData {
575
+ userId: string;
576
+ workspace: IWorkspace;
577
+ role: string;
578
+ }
579
+ interface WorkspaceUserRoleChangedEventData {
580
+ userId: string;
581
+ workspace: IWorkspace;
582
+ previousRole: string;
583
+ newRole: string;
584
+ }
585
+ interface WorkspaceCreatedEventData {
586
+ workspace: IWorkspace;
587
+ }
588
+ interface WorkspaceDeletedEventData {
589
+ workspace: IWorkspace;
590
+ }
591
+ /**
592
+ * Union type for all event data
593
+ */
594
+ type EventData = UserCreatedEventData | UserUpdatedEventData | WorkspaceChangedEventData | WorkspaceUpdatedEventData | WorkspaceUserAddedEventData | WorkspaceUserRemovedEventData | WorkspaceUserRoleChangedEventData | WorkspaceCreatedEventData | WorkspaceDeletedEventData;
595
+ /**
596
+ * Single event callback function
597
+ * Handles all events with conditional logic based on event type
598
+ */
599
+ interface IEventCallbacks {
600
+ /**
601
+ * Called when any event occurs
602
+ * @param eventType - The type of event that occurred
603
+ * @param data - The event data (type varies based on eventType)
604
+ */
605
+ handleEvent?: (eventType: EventType, data: EventData) => void | Promise<void>;
606
+ }
607
+
608
+ declare enum AuthStatus {
609
+ loading = "loading",
610
+ redirecting = "redirecting",
611
+ authenticated = "authenticated",
612
+ unauthenticated = "unauthenticated",
613
+ authenticating = "authenticating"
614
+ }
615
+ interface AuthUser {
616
+ id: string;
617
+ name: string;
618
+ org: string;
619
+ email: string;
620
+ emailVerified: boolean;
621
+ clientId: string;
622
+ role: string;
623
+ image?: string;
624
+ }
625
+ interface AuthSession {
626
+ user: AuthUser;
627
+ sessionId: string;
628
+ expires: string;
629
+ }
630
+ interface IAuthConfig {
631
+ clientId: string;
632
+ redirectUrl: string;
633
+ callbacks?: IAuthCallbacks;
634
+ }
635
+ interface IAuthCallbacks {
636
+ handleAuthentication: (code: string) => Promise<{
637
+ sessionId: string;
638
+ }>;
639
+ onSignOut: () => Promise<void>;
640
+ /**
641
+ * Called on page refresh to restore the session.
642
+ * Return the sessionId if the user is still authenticated, or null to log out.
643
+ *
644
+ * The SDK calls this instead of reading from localStorage.
645
+ * Implement this to read from an httpOnly cookie via a server endpoint.
646
+ *
647
+ * @example Next.js — read from httpOnly cookie via API route
648
+ * ```ts
649
+ * getSession: async () => {
650
+ * const res = await fetch('/api/auth/session')
651
+ * const data = await res.json()
652
+ * return data.sessionId ?? null
653
+ * }
654
+ * ```
655
+ */
656
+ getSession: () => Promise<string | null>;
657
+ /**
658
+ * Event handler for User and Workspace events
659
+ * @param eventType - The type of event that occurred
660
+ * @param data - The event data (type varies based on eventType)
661
+ */
662
+ handleEvent?: (eventType: EventType, data: EventData) => void | Promise<void>;
663
+ /**
664
+ * Called before switching workspace (e.g. generate token, save state).
665
+ * Used when user clicks "Switch to" and when restoring from storage on page refresh.
666
+ * Switch proceeds only when this resolves; reject to abort.
667
+ */
668
+ onWorkspaceChange?: (params: OnWorkspaceChangeParams) => Promise<void>;
669
+ }
670
+ interface OnWorkspaceChangeParams {
671
+ workspace: IWorkspace;
672
+ user: AuthUser | null;
673
+ role: string | null;
674
+ }
675
+
676
+ interface ISettings {
677
+ workspace: {
678
+ roles: string[];
679
+ defaultRole: string;
680
+ maxWorkspaces: number;
681
+ maxWorkspaceUsers: number;
682
+ };
683
+ [key: string]: any;
684
+ }
685
+
686
+ /**
687
+ * Supported API versions
688
+ */
689
+ declare enum ApiVersion {
690
+ V1 = "v1"
691
+ }
692
+ interface IOsConfig {
693
+ serverUrl: string;
694
+ version: ApiVersion;
695
+ orgId: string;
696
+ }
697
+ interface IOsState extends IOsConfig {
698
+ auth?: IAuthConfig;
699
+ settings?: ISettings | null;
700
+ }
701
+
702
+ /**
703
+ * Base API client for SDK endpoints.
704
+ * All domain API classes (WorkspaceApi, UserApi, etc.) extend this to share
705
+ * URL building, auth headers, and request/response handling.
706
+ *
707
+ * Supports two auth modes:
708
+ * 1. **Client-side (default):** reads sessionId from localStorage automatically.
709
+ * 2. **Server-side:** pass `sessionId` in config — no localStorage access.
710
+ *
711
+ * @example Server-side usage
712
+ * ```ts
713
+ * const api = new WorkspaceApi({
714
+ * serverUrl: "https://api.buildbase.app",
715
+ * version: "v1",
716
+ * orgId: "...",
717
+ * sessionId: req.headers["x-session-id"], // from your request
718
+ * });
719
+ * const sub = await api.getCurrentSubscription(workspaceId);
720
+ * ```
721
+ */
722
+
723
+ interface IBaseApiConfig {
724
+ serverUrl: string;
725
+ version: ApiVersion;
726
+ orgId?: string;
727
+ /** When true, ensureReady() also requires orgId. Used by WorkspaceApi and SettingsApi. */
728
+ requireOrgId?: boolean;
729
+ /** API path segment after version (default 'public'). e.g. 'public' => .../v1/public, 'beta' => .../v1/beta */
730
+ basePath?: string;
731
+ /**
732
+ * Session ID for server-side usage. When provided, this is used for auth
733
+ * instead of reading from localStorage. Pass the session token from your
734
+ * request headers, cookies, or any server-side session store.
735
+ */
736
+ sessionId?: string;
737
+ /** Request timeout in milliseconds. 0 = no timeout. */
738
+ timeout?: number;
739
+ /** Max automatic retries for network errors / 5xx. */
740
+ maxRetries?: number;
741
+ /** Enable debug logging for all requests. */
742
+ debug?: boolean;
743
+ /** Custom headers merged into every request. */
744
+ headers?: Record<string, string>;
745
+ /** Error callback — called before error is thrown. */
746
+ onError?: (error: Error, context: {
747
+ method: string;
748
+ path: string;
749
+ }) => void;
750
+ /** Custom fetch implementation. */
751
+ fetch?: typeof globalThis.fetch;
752
+ }
753
+ /**
754
+ * Base class for SDK API clients.
755
+ * Provides:
756
+ * - baseUrl: `${serverUrl}/api/${version}/public`
757
+ * - getAuthHeaders()
758
+ * - fetchJson<T>(path, init, errorMessage): GET/POST/etc. with handleApiResponse
759
+ * - fetchResponse(path, init): raw Response for custom parsing (e.g. non-JSON or custom error handling)
760
+ */
761
+ declare abstract class BaseApi {
762
+ protected readonly serverUrl: string;
763
+ protected readonly version: ApiVersion;
764
+ protected readonly orgId: string | undefined;
765
+ private readonly requireOrgId;
766
+ private readonly basePath;
767
+ private readonly _sessionId;
768
+ private readonly _timeout;
769
+ private readonly _maxRetries;
770
+ private readonly _debug;
771
+ private readonly _customHeaders;
772
+ private readonly _onError?;
773
+ private readonly _fetch;
774
+ constructor(config: IBaseApiConfig);
775
+ /** Throws if config is not ready for API calls. Called automatically by fetchJson/fetchResponse. */
776
+ protected ensureReady(): void;
777
+ /** Base URL: ${serverUrl}/api/${version}/${basePath} */
778
+ protected get baseUrl(): string;
779
+ /**
780
+ * Auth headers (x-session-id).
781
+ * Uses injected sessionId (server-side) or falls back to localStorage (client-side).
782
+ * Subclasses can override to add more headers.
783
+ */
784
+ protected getAuthHeaders(): Record<string, string>;
785
+ /** Build full URL from path (path can be "workspaces" or "/workspaces"). */
786
+ protected url(path: string): string;
787
+ /** Merge auth + custom + per-request headers. */
788
+ private buildHeaders;
789
+ /** Execute fetch with timeout, retries, debug logging, and error callback. */
790
+ private executeFetch;
791
+ /**
792
+ * Execute request and parse JSON with handleApiResponse (throws on !response.ok).
793
+ * Use for standard JSON APIs.
794
+ */
795
+ protected fetchJson<T>(path: string, init?: RequestInit, errorMessage?: string): Promise<T>;
796
+ /**
797
+ * Execute request and return raw Response (for custom parsing or error handling).
798
+ * Caller is responsible for checking response.ok and parsing body.
799
+ */
800
+ protected fetchResponse(path: string, init?: RequestInit): Promise<Response>;
801
+ }
802
+
803
+ /**
804
+ * API client for authentication.
805
+ * Extends BaseApi for shared URL/auth/request handling.
806
+ */
807
+
808
+ interface AuthRequestParams {
809
+ orgId: string;
810
+ clientId: string;
811
+ redirect: {
812
+ success: string;
813
+ error: string;
814
+ };
815
+ }
816
+ interface AuthRequestResponse {
817
+ success: boolean;
818
+ data: {
819
+ redirectUrl: string;
820
+ };
821
+ message: string;
822
+ }
823
+ declare class AuthApi extends BaseApi {
824
+ constructor(config: Pick<IOsConfig, 'serverUrl' | 'version'> & {
825
+ sessionId?: string;
826
+ });
827
+ /**
828
+ * Initiate OAuth sign-in flow. Returns redirect URL to the auth provider.
829
+ * Uses /api/v1/auth/request (no 'public' prefix — auth endpoints are at the root).
830
+ */
831
+ requestAuth(params: AuthRequestParams): Promise<AuthRequestResponse>;
832
+ /** Fetch user profile with the given session ID (used after OAuth redirect or from storage). */
833
+ getProfile(sessionId: string, signal?: AbortSignal): Promise<IUser>;
834
+ }
835
+
836
+ interface IScreenDetail {
837
+ title: string;
838
+ description: string;
839
+ }
840
+ interface IBetaConfig extends IDocument {
841
+ name: string;
842
+ smallName: string;
843
+ description: string;
844
+ logoFallBack: string;
845
+ logo: string | IAsset;
846
+ privacyPolicy: string;
847
+ termsOfService: string;
848
+ enabled: boolean;
849
+ screen: {
850
+ register: IScreenDetail;
851
+ thankYou: IScreenDetail;
852
+ };
853
+ }
854
+
855
+ declare class PushApi extends BaseApi {
856
+ constructor(config: Pick<IBaseApiConfig, 'serverUrl' | 'version' | 'orgId' | 'sessionId'>);
857
+ getVapidPublicKey(): Promise<{
858
+ publicKey: string;
859
+ }>;
860
+ subscribe(subscription: {
861
+ endpoint: string;
862
+ keys: {
863
+ p256dh: string;
864
+ auth: string;
865
+ };
866
+ }, userAgent: string): Promise<void>;
867
+ unsubscribe(endpoint: string): Promise<void>;
868
+ }
869
+
870
+ /**
871
+ * Centralized API client for organization (OS) settings.
872
+ * Extends BaseApi for shared URL/auth/request handling.
873
+ */
874
+
875
+ declare class SettingsApi extends BaseApi {
876
+ constructor(config: IOsConfig & {
877
+ sessionId?: string;
878
+ });
879
+ getSettings(signal?: AbortSignal): Promise<ISettings>;
880
+ }
881
+
882
+ /**
883
+ * API client for user attributes and features.
884
+ * Extends BaseApi for shared URL/auth/request handling.
885
+ */
886
+
887
+ declare class UserApi extends BaseApi {
888
+ constructor(config: Pick<IOsConfig, 'serverUrl' | 'version'> & {
889
+ sessionId?: string;
890
+ });
891
+ getAttributes(signal?: AbortSignal): Promise<Record<string, string | number | boolean>>;
892
+ updateAttributes(updates: Record<string, string | number | boolean>): Promise<IUser>;
893
+ updateAttribute(attributeKey: string, value: string | number | boolean): Promise<IUser>;
894
+ getFeatures(signal?: AbortSignal): Promise<Record<string, boolean>>;
895
+ }
896
+
897
+ declare class WorkspaceApi extends BaseApi {
898
+ constructor(config: IOsConfig & {
899
+ sessionId?: string;
900
+ });
901
+ getWorkspaces(): Promise<IWorkspace[]>;
902
+ createWorkspace(data: {
903
+ name: string;
904
+ image?: string;
905
+ }): Promise<IWorkspace>;
906
+ updateWorkspace(id: string, data: Partial<IWorkspace>): Promise<IWorkspace>;
907
+ deleteWorkspace(id: string): Promise<{
908
+ success: boolean;
909
+ }>;
910
+ getWorkspaceUsers(workspaceId: string): Promise<IWorkspaceUser[]>;
911
+ addUser(workspaceId: string, config: {
912
+ email: string;
913
+ role: string;
914
+ }): Promise<{
915
+ userId: string;
916
+ workspace: IWorkspace;
917
+ message: string;
918
+ }>;
919
+ removeUser(workspaceId: string, userId: string): Promise<{
920
+ userId: string;
921
+ workspace: IWorkspace;
922
+ message: string;
923
+ }>;
924
+ updateUser(workspaceId: string, userId: string, data: Partial<IWorkspaceUser>): Promise<{
925
+ userId: string;
926
+ workspace: IWorkspace;
927
+ message: string;
928
+ }>;
929
+ getFeatures(): Promise<IWorkspaceFeature[]>;
930
+ updateFeature(workspaceId: string, key: string, value: boolean): Promise<IWorkspace>;
931
+ getWorkspace(workspaceId: string): Promise<IWorkspace>;
932
+ getProfile(): Promise<IUser>;
933
+ updateUserProfile(config: Partial<IUser>): Promise<IUser>;
934
+ /**
935
+ * Get current subscription for a workspace
936
+ * Returns subscription details including plan, plan version, and group information
937
+ */
938
+ getCurrentSubscription(workspaceId: string): Promise<ISubscriptionResponse>;
939
+ /**
940
+ * Get plan group for a workspace
941
+ * Returns the plan group containing the current plan if subscription exists,
942
+ * otherwise returns the latest published group
943
+ */
944
+ getPlanGroup(workspaceId: string): Promise<IPlanGroupResponse>;
945
+ /**
946
+ * Get plan group for a workspace with a specific version
947
+ * @param workspaceId - The workspace ID
948
+ * @param groupVersionId - The plan group version ID to fetch
949
+ * @returns Plan group response with the specified version
950
+ */
951
+ getPlanGroupByVersion(workspaceId: string, groupVersionId: string): Promise<IPlanGroupResponse>;
952
+ /**
953
+ * Get current group version and available newer versions of the same group
954
+ * - If user has active subscription: returns their current group version + newer versions
955
+ * - If no subscription: returns the latest published group version
956
+ * Shows what's new in newer versions to help users upgrade
957
+ * Example: User on Group v1 (Basic Plan) can see Group v2 (Basic + Pro Plan)
958
+ * @param workspaceId - The workspace ID
959
+ * @returns Plan group versions response with currentVersion and availableVersions
960
+ */
961
+ getPlanGroupVersions(workspaceId: string): Promise<IPlanGroupVersionsResponse>;
962
+ /**
963
+ * Get plan group versions by slug (public, no auth required).
964
+ * Returns the latest published plan group versions for the given plan group slug.
965
+ * Use this for public pricing pages when you want to show a specific plan group.
966
+ *
967
+ * @param slug - Plan group slug (e.g. 'default', 'enterprise')
968
+ * @returns Plan group versions response with currentVersion and availableVersions
969
+ */
970
+ getPublicPlans(slug: string): Promise<IPublicPlansResponse>;
971
+ /**
972
+ * Get plan group version details by ID (public, no auth required).
973
+ * Returns the full plan group version with populated plan versions.
974
+ * Use this for public pricing pages when you have the groupVersionId (e.g. from config or URL).
975
+ *
976
+ * @param groupVersionId - The plan group version ID to fetch
977
+ * @returns Plan group version with populated plan versions
978
+ */
979
+ getPlanGroupVersion(groupVersionId: string): Promise<IPlanGroupVersion>;
980
+ /**
981
+ * Create checkout session for new subscription
982
+ * @param workspaceId - The workspace ID
983
+ * @param request - Checkout session request with planVersionId and optional billing interval/URLs
984
+ * @returns Checkout session response with checkoutUrl to redirect user
985
+ */
986
+ createCheckoutSession(workspaceId: string, request: ICheckoutSessionRequest): Promise<CheckoutResult>;
987
+ /**
988
+ * Update subscription (upgrade/downgrade)
989
+ * Only allows plan changes within the same plan group
990
+ * Returns checkout session if payment is required, otherwise returns subscription update response
991
+ */
992
+ updateSubscription(workspaceId: string, request: ISubscriptionUpdateRequest): Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
993
+ /**
994
+ * Create a Stripe Customer Portal session for managing payment methods, invoices, etc.
995
+ * Returns the portal URL — redirect user to it.
996
+ */
997
+ createBillingPortalSession(workspaceId: string, returnUrl?: string): Promise<{
998
+ url: string;
999
+ }>;
1000
+ /**
1001
+ * List invoices for a workspace subscription
1002
+ * @param workspaceId - The workspace ID
1003
+ * @param limit - Number of invoices to return (default: 10)
1004
+ * @param startingAfter - Invoice ID to start after (for pagination)
1005
+ * @returns List of invoices with pagination info
1006
+ */
1007
+ listInvoices(workspaceId: string, limit?: number, startingAfter?: string): Promise<IInvoiceListResponse>;
1008
+ /**
1009
+ * Get a single invoice by ID
1010
+ * @param workspaceId - The workspace ID
1011
+ * @param invoiceId - The invoice ID
1012
+ * @returns Invoice details
1013
+ */
1014
+ getInvoice(workspaceId: string, invoiceId: string): Promise<IInvoiceResponse>;
1015
+ /**
1016
+ * Cancel subscription at the end of the current billing period
1017
+ * Sets cancelAtPeriodEnd: true - subscription remains active until period ends
1018
+ * @param workspaceId - The workspace ID
1019
+ * @returns Updated subscription with cancelAtPeriodEnd and stripeCurrentPeriodEnd
1020
+ */
1021
+ cancelSubscriptionAtPeriodEnd(workspaceId: string): Promise<ISubscriptionResponse>;
1022
+ /**
1023
+ * Resume a subscription that was scheduled for cancellation
1024
+ * Sets cancelAtPeriodEnd: false - subscription will continue after period ends
1025
+ * @param workspaceId - The workspace ID
1026
+ * @returns Updated subscription with cancelAtPeriodEnd set to false
1027
+ */
1028
+ resumeSubscription(workspaceId: string): Promise<ISubscriptionResponse>;
1029
+ /**
1030
+ * Record quota usage for a workspace
1031
+ * @param workspaceId - The workspace ID
1032
+ * @param request - Usage request with quotaSlug, quantity, and optional metadata/source
1033
+ * @returns Usage result with consumed/included/available/overage
1034
+ */
1035
+ recordUsage(workspaceId: string, request: IRecordUsageRequest): Promise<IRecordUsageResponse>;
1036
+ /**
1037
+ * Get usage status for a single quota
1038
+ * @param workspaceId - The workspace ID
1039
+ * @param quotaSlug - The quota slug to check
1040
+ * @returns Quota usage status with consumed/included/available/overage/hasOverage
1041
+ */
1042
+ getQuotaUsageStatus(workspaceId: string, quotaSlug: string): Promise<IQuotaUsageStatusResponse>;
1043
+ /**
1044
+ * Get usage status for all quotas in the workspace's current plan
1045
+ * @param workspaceId - The workspace ID
1046
+ * @returns All quota usage statuses keyed by quota slug
1047
+ */
1048
+ getAllQuotaUsage(workspaceId: string): Promise<IAllQuotaUsageResponse>;
1049
+ /**
1050
+ * Get paginated usage logs for a workspace
1051
+ * @param workspaceId - The workspace ID
1052
+ * @param query - Optional filters: quotaSlug, from, to, source, page, limit
1053
+ * @returns Paginated usage log entries
1054
+ */
1055
+ getUsageLogs(workspaceId: string, query?: IUsageLogsQuery): Promise<IUsageLogsResponse>;
1056
+ }
1057
+
1058
+ /**
1059
+ * EventEmitter class to handle and trigger event callbacks
1060
+ * This class manages all event listeners and provides methods to trigger events
1061
+ */
1062
+ declare class EventEmitter {
1063
+ private callbacks;
1064
+ /**
1065
+ * Set the event callbacks
1066
+ * @param callbacks - The event callbacks to register
1067
+ */
1068
+ setCallbacks(callbacks: IEventCallbacks | null): void;
1069
+ /**
1070
+ * Get the current event callbacks
1071
+ * @returns The current event callbacks or null
1072
+ */
1073
+ getCallbacks(): IEventCallbacks | null;
1074
+ /**
1075
+ * Emit an event
1076
+ * @param eventType - The type of event
1077
+ * @param data - The event data
1078
+ */
1079
+ private emit;
1080
+ /**
1081
+ * Trigger user created event
1082
+ * @param user - The newly created user
1083
+ */
1084
+ emitUserCreated(user: IUser): Promise<void>;
1085
+ /**
1086
+ * Trigger user updated event
1087
+ * @param user - The updated user
1088
+ * @param previousUser - The user data before the update (optional)
1089
+ */
1090
+ emitUserUpdated(user: IUser, previousUser?: IUser): Promise<void>;
1091
+ /**
1092
+ * Trigger workspace changed event
1093
+ * @param workspace - The newly selected workspace
1094
+ * @param previousWorkspace - The previously selected workspace (optional)
1095
+ */
1096
+ emitWorkspaceChanged(workspace: IWorkspace, previousWorkspace?: IWorkspace | null): Promise<void>;
1097
+ /**
1098
+ * Trigger workspace updated event
1099
+ * @param workspace - The updated workspace
1100
+ */
1101
+ emitWorkspaceUpdated(workspace: IWorkspace): Promise<void>;
1102
+ /**
1103
+ * Trigger workspace user added event
1104
+ * @param userId - The ID of the user that was added
1105
+ * @param workspace - The workspace the user was added to
1106
+ * @param role - The role assigned to the user
1107
+ */
1108
+ emitWorkspaceUserAdded(userId: string, workspace: IWorkspace, role: string): Promise<void>;
1109
+ /**
1110
+ * Trigger workspace user removed event
1111
+ * @param userId - The ID of the user that was removed
1112
+ * @param workspace - The workspace the user was removed from
1113
+ * @param role - The role the user had in the workspace
1114
+ */
1115
+ emitWorkspaceUserRemoved(userId: string, workspace: IWorkspace, role: string): Promise<void>;
1116
+ /**
1117
+ * Trigger workspace user role changed event
1118
+ * @param userId - The ID of the user whose role was changed
1119
+ * @param workspace - The workspace where the role was changed
1120
+ * @param previousRole - The previous role of the user
1121
+ * @param newRole - The new role of the user
1122
+ */
1123
+ emitWorkspaceUserRoleChanged(userId: string, workspace: IWorkspace, previousRole: string, newRole: string): Promise<void>;
1124
+ /**
1125
+ * Trigger workspace created event
1126
+ * @param workspace - The newly created workspace
1127
+ */
1128
+ emitWorkspaceCreated(workspace: IWorkspace): Promise<void>;
1129
+ /**
1130
+ * Trigger workspace deleted event
1131
+ * @param workspace - The deleted workspace
1132
+ */
1133
+ emitWorkspaceDeleted(workspace: IWorkspace): Promise<void>;
1134
+ }
1135
+ declare const eventEmitter: EventEmitter;
1136
+
1137
+ /**
1138
+ * Notify all subscribers to refetch subscription (e.g. after update/cancel/resume).
1139
+ * Called internally by useUpdateSubscription, useCancelSubscription, useResumeSubscription on success.
1140
+ */
1141
+ declare function invalidateSubscription(): void;
1142
+
1143
+ /**
1144
+ * Notify all subscribers to refetch quota usage (e.g. after recording usage).
1145
+ * Called internally by useRecordUsage on success.
1146
+ */
1147
+ declare function invalidateQuotaUsage(): void;
1148
+
1149
+ /**
1150
+ * Centralized formatting for subscription/quota display: cents, overage rates, included + overage text.
1151
+ * Currency must be provided by the caller (e.g. workspace.billingCurrency, plan.currency, or selected currency).
1152
+ */
1153
+ /** Common currency display (code or symbol). Use lowercase Stripe codes (usd, eur, etc.). */
1154
+ declare const CURRENCY_DISPLAY: Record<string, string>;
1155
+ /** Currency code to flag emoji (country/region associated with the currency). Use for dropdowns. */
1156
+ declare const CURRENCY_FLAG: Record<string, string>;
1157
+ /** Get flag emoji for a currency code. Returns empty string when unknown or empty. */
1158
+ declare function getCurrencyFlag(currency: string): string;
1159
+ /** Get currency symbol for display. Use lowercase Stripe codes (usd, eur). Returns code when unknown; empty string when currency is empty. */
1160
+ declare function getCurrencySymbol(currency: string): string;
1161
+ /** Allowed plan/pricing currency codes (must match server ALLOWED_BILLING_CURRENCIES). Use for dropdowns and validation. */
1162
+ declare const PLAN_CURRENCY_CODES: readonly ["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny", "hkd", "sgd", "inr", "mxn", "brl", "nzd", "sek", "nok", "dkk", "pln", "thb"];
1163
+ /** Options for plan currency select: { value, label } with symbol. Use in CreateOrEditPlan and anywhere a currency dropdown is needed. */
1164
+ declare const PLAN_CURRENCY_OPTIONS: {
1165
+ value: "usd" | "eur" | "gbp" | "jpy" | "cad" | "aud" | "chf" | "cny" | "hkd" | "sgd" | "inr" | "mxn" | "brl" | "nzd" | "sek" | "nok" | "dkk" | "pln" | "thb";
1166
+ label: string;
1167
+ }[];
1168
+ /** Format cents as money string (e.g. 1999, "usd" -> "$19.99"). Caller must pass currency (e.g. from plan or workspace). */
1169
+ declare function formatCents(cents: number, currency: string): string;
1170
+ /**
1171
+ * Format overage rate for display. When unitSize > 1: "$1.00/1,000 units"; else "$1.00/unit".
1172
+ * Returns null if overageCents is missing or negative.
1173
+ */
1174
+ declare function formatOverageRate(overageCents: number | undefined, unitSize: number | undefined, currency: string): string | null;
1175
+ /**
1176
+ * Format overage rate with optional unit label for comparison/preview UIs.
1177
+ * e.g. formatOverageRateWithLabel(50, 1000, "video") -> "$0.50/1,000 videos"
1178
+ * formatOverageRateWithLabel(46, 1, "video") -> "$0.46/video"
1179
+ * When unitLabel is omitted, falls back to formatOverageRate behavior.
1180
+ */
1181
+ declare function formatOverageRateWithLabel(overageCents: number | undefined, unitSize: number | undefined, unitLabel: string | undefined, currency: string): string | null;
1182
+ /**
1183
+ * Get singular unit label from item name or slug (e.g. "Videos" -> "video", "reels" -> "reel").
1184
+ * Used for quota display in comparison and preview.
1185
+ */
1186
+ declare function getQuotaUnitLabelFromName(nameOrSlug: string): string;
1187
+ /**
1188
+ * Format quota "included + overage" for display.
1189
+ * When unitSize >= 2: "Included: 1,000, after that $1.00/1,000 emails".
1190
+ * Otherwise: "Included: 5, after that $0.30/image".
1191
+ */
1192
+ declare function formatQuotaIncludedOverage(included: number | undefined, overageCents: number | undefined, unitLabel: string, currency: string, unitSize?: number): string;
1193
+
1194
+ type QuotaDisplayValue = {
1195
+ included: number;
1196
+ overage?: number;
1197
+ unitSize?: number;
1198
+ } | null;
1199
+ /**
1200
+ * Normalize a per-interval quota value to a display shape for the given billing interval.
1201
+ */
1202
+ declare function getQuotaDisplayValue(value: IQuotaByInterval | null | undefined, interval?: BillingInterval): QuotaDisplayValue;
1203
+ /** Options for formatting quota with price. */
1204
+ interface FormatQuotaWithPriceOptions {
1205
+ /** If true, overage is in cents (Stripe); format as dollars. Default true. */
1206
+ overageInCents?: boolean;
1207
+ /** Currency symbol override. When omitted, derived from `currency` (empty if no currency). */
1208
+ currencySymbol?: string;
1209
+ /** Stripe currency code (e.g. 'usd', 'inr'). Used to resolve symbol when currencySymbol is not set. */
1210
+ currency?: string;
1211
+ }
1212
+ /**
1213
+ * Format a quota display value as "X included, then $Y.YY / unit" (e.g. "10 included, then $10.00 / video").
1214
+ * Assumes overage is the per-unit price (in cents when overageInCents is true).
1215
+ */
1216
+ declare function formatQuotaWithPrice(value: QuotaDisplayValue, unitName: string, options?: FormatQuotaWithPriceOptions): string;
1217
+
1218
+ /**
1219
+ * Helpers for multi-currency plan version pricing (pricingVariants).
1220
+ */
1221
+
1222
+ /** Get the pricing variant for a currency, or null if not available. */
1223
+ declare function getPricingVariant(planVersion: IPlanVersion, currency: string): IPricingVariant | null;
1224
+ /**
1225
+ * Get base price in cents for a plan version and currency/interval.
1226
+ */
1227
+ declare function getBasePriceCents(planVersion: IPlanVersion, currency: string, interval: BillingInterval): number | null;
1228
+ /**
1229
+ * Get Stripe price ID for the given plan version, currency, and interval.
1230
+ */
1231
+ declare function getStripePriceIdForInterval(planVersion: IPlanVersion, currency: string, interval: BillingInterval): string | null;
1232
+ /**
1233
+ * Get overage amount in cents for a quota in a given currency and interval.
1234
+ * Returns undefined if not defined in the pricing variant.
1235
+ */
1236
+ declare function getQuotaOverageCents(planVersion: IPlanVersion, currency: string, quotaSlug: string, interval: BillingInterval): number | undefined;
1237
+ /**
1238
+ * Get display currency for a plan version when using a given currency.
1239
+ * Returns the requested currency if the variant exists; otherwise plan.currency or null.
1240
+ */
1241
+ declare function getDisplayCurrency(planVersion: IPlanVersionWithPlan, currency: string): string;
1242
+ /** Minimal shape for extracting currencies (IPlanVersionWithPlan or IPublicPlanVersion). */
1243
+ type PlanVersionWithPricingVariants = {
1244
+ pricingVariants?: IPricingVariant[];
1245
+ };
1246
+ /**
1247
+ * Collect all unique currency codes from plan versions (from their pricingVariants).
1248
+ * Use for currency selector. Accepts IPlanVersionWithPlan[] or IPublicPlanVersion[].
1249
+ */
1250
+ declare function getAvailableCurrenciesFromPlans(planVersions: PlanVersionWithPricingVariants[]): string[];
1251
+ /**
1252
+ * Quota display shape: included count and optional overage (cents) and unitSize from plan + variant.
1253
+ */
1254
+ type QuotaDisplayWithOverage = {
1255
+ included: number;
1256
+ overage?: number;
1257
+ unitSize?: number;
1258
+ } | null;
1259
+ /**
1260
+ * Get quota display value for a slug/interval, merging plan version quotas (included, unitSize)
1261
+ * with pricing variant overage (cents) when available.
1262
+ */
1263
+ declare function getQuotaDisplayWithVariant(planVersion: IPlanVersion, currency: string, quotaSlug: string, interval: BillingInterval): QuotaDisplayWithOverage;
1264
+ /**
1265
+ * Resolve billing interval and currency from a Stripe price ID by checking all plan versions' pricingVariants.
1266
+ */
1267
+ declare function getBillingIntervalAndCurrencyFromPriceId(priceId: string | null | undefined, planVersions: IPlanVersionWithPlan[]): {
1268
+ interval: BillingInterval;
1269
+ currency: string;
1270
+ } | null;
1271
+ /** Get per-seat pricing config for a plan version and currency. Null if not enabled. */
1272
+ declare function getSeatPricing(planVersion: IPlanVersion, currency: string): IPricingVariant['seatPricing'] | null;
1273
+ /** Get per-seat price in cents for a billing interval. Null if seat pricing not enabled. */
1274
+ declare function getPerSeatPriceCents(planVersion: IPlanVersion, currency: string, interval: BillingInterval): number | null;
1275
+ /** Calculate billable seats: max(0, currentSeats - includedSeats). */
1276
+ declare function calculateBillableSeats(currentSeatCount: number, includedSeats: number): number;
1277
+ /** Calculate total seat overage cost in cents. Null if seat pricing not enabled. */
1278
+ declare function calculateSeatOverageCents(planVersion: IPlanVersion, currency: string, interval: BillingInterval, currentSeatCount: number): number | null;
1279
+ /**
1280
+ * Calculate total subscription price in cents: base + seat overage (if enabled).
1281
+ * Does not include metered usage (billed at period end).
1282
+ */
1283
+ declare function calculateTotalSubscriptionCents(planVersion: IPlanVersion, currency: string, interval: BillingInterval, currentSeatCount?: number): number | null;
1284
+ interface MaxUsersConfig {
1285
+ /** The resolved maximum number of users allowed. 0 = unlimited. */
1286
+ maxUsers: number;
1287
+ /** Where the limit comes from. */
1288
+ source: 'seat_pricing' | 'settings' | 'none';
1289
+ /** Seats included in the base plan price (0 if no seat pricing). */
1290
+ includedSeats: number;
1291
+ /** Whether seat-based pricing is active. */
1292
+ hasSeatPricing: boolean;
1293
+ }
1294
+ /**
1295
+ * Resolve the effective max users limit from the plan's seat pricing config,
1296
+ * falling back to settings when no seat pricing is configured.
1297
+ *
1298
+ * Priority:
1299
+ * 1. Seat pricing `maxSeats` (from plan version's pricing variant) — the plan controls the limit
1300
+ * 2. Settings fallback (`workspace.maxWorkspaceUsers`) — for workspaces without a subscription
1301
+ *
1302
+ * Returns 0 if no limit is set (unlimited).
1303
+ */
1304
+ declare function resolveMaxUsers(opts: {
1305
+ planVersion?: IPlanVersion | null;
1306
+ currency?: string;
1307
+ settingsMaxUsers?: number | null;
1308
+ }): MaxUsersConfig;
1309
+ type InviteBlockReason = 'seat_limit_reached' | 'settings_user_limit_reached' | 'no_subscription' | null;
1310
+ interface InviteValidation {
1311
+ /** Whether a new user can be invited. */
1312
+ canInvite: boolean;
1313
+ /** Reason the invite is blocked, or null if allowed. */
1314
+ blockReason: InviteBlockReason;
1315
+ /** Human-readable message for the block reason. */
1316
+ blockMessage: string | null;
1317
+ }
1318
+ /**
1319
+ * Validate whether a new member can be invited given current seat/user limits.
1320
+ */
1321
+ declare function validateInvite(opts: {
1322
+ memberCount: number;
1323
+ maxUsersConfig: MaxUsersConfig;
1324
+ hasSubscription?: boolean;
1325
+ requireSubscription?: boolean;
1326
+ }): InviteValidation;
1327
+
1328
+ /**
1329
+ * Push notification service worker source code.
1330
+ * Export this string and write it to a file in your app's `public/` directory.
1331
+ *
1332
+ * @example
1333
+ * ```ts
1334
+ * // scripts/generate-sw.ts
1335
+ * import { PUSH_SERVICE_WORKER_SCRIPT } from '@buildbase/sdk';
1336
+ * import fs from 'fs';
1337
+ * fs.writeFileSync('public/push-sw.js', PUSH_SERVICE_WORKER_SCRIPT);
1338
+ * ```
1339
+ *
1340
+ * Or manually create `public/push-sw.js` with this content.
1341
+ */
1342
+ declare const PUSH_SERVICE_WORKER_SCRIPT = "\n// BuildBase Push Notification Service Worker\n// Place this file in your app's public directory (e.g. public/push-sw.js)\n\nself.addEventListener('push', function(event) {\n if (!event.data) return;\n\n try {\n var payload = event.data.json();\n var title = payload.title || 'Notification';\n var options = {\n body: payload.body || '',\n icon: payload.icon || undefined,\n badge: payload.icon || undefined,\n data: { url: payload.url, ...(payload.data || {}) },\n tag: 'buildbase-push-' + Date.now(),\n };\n\n event.waitUntil(\n self.registration.showNotification(title, options)\n );\n } catch (e) {\n console.error('[PushSW] Failed to show notification:', e);\n }\n});\n\nself.addEventListener('notificationclick', function(event) {\n event.notification.close();\n\n var url = event.notification.data && event.notification.data.url;\n if (url) {\n event.waitUntil(\n clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {\n for (var i = 0; i < clientList.length; i++) {\n var client = clientList[i];\n if (client.url === url && 'focus' in client) {\n return client.focus();\n }\n }\n if (clients.openWindow) {\n return clients.openWindow(url);\n }\n })\n );\n }\n});\n";
1343
+
1344
+ declare const countries: {
1345
+ value: string;
1346
+ flag: string;
1347
+ text: string;
1348
+ currencyCode: string;
1349
+ currencyIcon: string;
1350
+ }[];
1351
+
1352
+ declare const uniqueCurrencies: {
1353
+ value: string;
1354
+ text: string;
1355
+ icon: any;
1356
+ }[];
1357
+
1358
+ declare const languages: {
1359
+ value: string;
1360
+ label: string;
1361
+ flag: string;
1362
+ }[];
1363
+
1364
+ declare const timezones: {
1365
+ value: string;
1366
+ abbr: string;
1367
+ offset: number;
1368
+ isdst: boolean;
1369
+ text: string;
1370
+ utc: string[];
1371
+ }[];
1372
+
1373
+ declare const formSchema: z.ZodObject<{
1374
+ name: z.ZodString;
1375
+ email: z.ZodString;
1376
+ }, z.core.$strip>;
1377
+ type formValuesType = z.infer<typeof formSchema>;
1378
+
1379
+ interface BetaFormData {
1380
+ name?: string;
1381
+ email: string;
1382
+ }
1383
+ interface BetaFormResponse {
1384
+ success: boolean;
1385
+ message: string;
1386
+ }
1387
+
1388
+ interface SaaSOSProviderProps extends IOsState {
1389
+ children: react__default.ReactNode;
1390
+ }
1391
+ declare const SaaSOSProvider: react__default.FC<SaaSOSProviderProps>;
1392
+
1393
+ type WorkspaceSettingsSection = 'profile' | 'general' | 'users' | 'subscription' | 'usage' | 'features' | 'notifications' | 'danger';
1394
+
1395
+ declare function useSaaSAuth(): {
1396
+ signIn: () => Promise<void>;
1397
+ signOut: () => Promise<void>;
1398
+ openWorkspaceSettings: (section?: WorkspaceSettingsSection) => void;
1399
+ isAuthenticated: boolean;
1400
+ isLoading: boolean;
1401
+ isRedirecting: boolean;
1402
+ user: AuthUser | undefined;
1403
+ session: AuthSession | null;
1404
+ status: AuthStatus;
1405
+ };
1406
+
1407
+ interface IProps$2 {
1408
+ children: React.ReactNode;
1409
+ }
1410
+ /**
1411
+ * Conditional component that renders children only when user is authenticated.
1412
+ * Returns null if user is not authenticated or authentication status is still loading.
1413
+ *
1414
+ * @param props - Component props
1415
+ * @param props.children - Content to render when authenticated
1416
+ *
1417
+ * @example
1418
+ * ```tsx
1419
+ * function App() {
1420
+ * return (
1421
+ * <SaaSOSProvider {...config}>
1422
+ * <WhenAuthenticated>
1423
+ * <Dashboard />
1424
+ * </WhenAuthenticated>
1425
+ * <WhenUnauthenticated>
1426
+ * <LoginPage />
1427
+ * </WhenUnauthenticated>
1428
+ * </SaaSOSProvider>
1429
+ * );
1430
+ * }
1431
+ * ```
1432
+ */
1433
+ declare const WhenAuthenticated: {
1434
+ (props: IProps$2): react.ReactNode;
1435
+ displayName: string;
1436
+ };
1437
+ /**
1438
+ * Conditional component that renders children only when user is NOT authenticated.
1439
+ * Returns null if user is authenticated.
1440
+ * Note: Also renders during loading/redirecting states (when not yet authenticated).
1441
+ *
1442
+ * @param props - Component props
1443
+ * @param props.children - Content to render when unauthenticated
1444
+ *
1445
+ * @example
1446
+ * ```tsx
1447
+ * function App() {
1448
+ * return (
1449
+ * <SaaSOSProvider {...config}>
1450
+ * <WhenUnauthenticated>
1451
+ * <LoginPage />
1452
+ * </WhenUnauthenticated>
1453
+ * <WhenAuthenticated>
1454
+ * <Dashboard />
1455
+ * </WhenAuthenticated>
1456
+ * </SaaSOSProvider>
1457
+ * );
1458
+ * }
1459
+ * ```
1460
+ *
1461
+ * @example
1462
+ * ```tsx
1463
+ * // Handle loading state separately
1464
+ * function App() {
1465
+ * const { isLoading } = useSaaSAuth();
1466
+ *
1467
+ * if (isLoading) return <LoadingSpinner />;
1468
+ *
1469
+ * return (
1470
+ * <>
1471
+ * <WhenUnauthenticated><LoginPage /></WhenUnauthenticated>
1472
+ * <WhenAuthenticated><Dashboard /></WhenAuthenticated>
1473
+ * </>
1474
+ * );
1475
+ * }
1476
+ * ```
1477
+ */
1478
+ declare const WhenUnauthenticated: {
1479
+ (props: IProps$2): react.ReactNode;
1480
+ displayName: string;
1481
+ };
1482
+
1483
+ interface IProps$1 {
1484
+ roles: string[];
1485
+ children: React.ReactNode;
1486
+ fallback?: React.ReactNode;
1487
+ }
1488
+ /**
1489
+ * Conditional component that renders children only when user has one of the specified roles.
1490
+ * Checks the user's global role (not workspace-specific).
1491
+ *
1492
+ * @param props - Component props
1493
+ * @param props.roles - Array of role strings to check against user's role
1494
+ * @param props.children - Content to render when user has matching role
1495
+ * @param props.fallback - Optional content to render when user doesn't have matching role (default: null)
1496
+ *
1497
+ * @example
1498
+ * ```tsx
1499
+ * function AdminPanel() {
1500
+ * return (
1501
+ * <WhenRoles roles={['admin', 'super-admin']}>
1502
+ * <AdminContent />
1503
+ * </WhenRoles>
1504
+ * );
1505
+ * }
1506
+ * ```
1507
+ *
1508
+ * @example
1509
+ * ```tsx
1510
+ * // With fallback
1511
+ * function SettingsPage() {
1512
+ * return (
1513
+ * <WhenRoles
1514
+ * roles={['admin']}
1515
+ * fallback={<p>You don't have permission to access this page.</p>}
1516
+ * >
1517
+ * <AdminSettings />
1518
+ * </WhenRoles>
1519
+ * );
1520
+ * }
1521
+ * ```
1522
+ */
1523
+ declare const WhenRoles: {
1524
+ (props: IProps$1): react.ReactNode;
1525
+ displayName: string;
1526
+ };
1527
+ /**
1528
+ * Conditional component that renders children only when user has one of the specified roles
1529
+ * in the current workspace. Checks workspace-specific role, not global role.
1530
+ *
1531
+ * @param props - Component props
1532
+ * @param props.roles - Array of role strings to check against user's workspace role
1533
+ * @param props.children - Content to render when user has matching workspace role
1534
+ * @param props.fallback - Optional content to render when user doesn't have matching role (default: null)
1535
+ *
1536
+ * @example
1537
+ * ```tsx
1538
+ * function WorkspaceSettings() {
1539
+ * return (
1540
+ * <WhenWorkspaceRoles roles={['owner', 'admin']}>
1541
+ * <SettingsContent />
1542
+ * </WhenWorkspaceRoles>
1543
+ * );
1544
+ * }
1545
+ * ```
1546
+ *
1547
+ * @example
1548
+ * ```tsx
1549
+ * // Edge case: User not in current workspace
1550
+ * function WorkspaceContent() {
1551
+ * return (
1552
+ * <WhenWorkspaceRoles
1553
+ * roles={['member']}
1554
+ * fallback={<p>You are not a member of this workspace.</p>}
1555
+ * >
1556
+ * <WorkspaceDashboard />
1557
+ * </WhenWorkspaceRoles>
1558
+ * );
1559
+ * }
1560
+ * ```
1561
+ */
1562
+ declare const WhenWorkspaceRoles: {
1563
+ (props: IProps$1): react.ReactNode;
1564
+ displayName: string;
1565
+ };
1566
+
1567
+ interface IProps {
1568
+ slug: string;
1569
+ children: React.ReactNode;
1570
+ }
1571
+ /**
1572
+ * Conditional component that renders children only when the specified workspace feature is enabled.
1573
+ * Checks feature flags at the workspace level.
1574
+ *
1575
+ * @param props - Component props
1576
+ * @param props.slug - Feature flag slug/key to check
1577
+ * @param props.children - Content to render when feature is enabled
1578
+ *
1579
+ * @example
1580
+ * ```tsx
1581
+ * function PremiumFeature() {
1582
+ * return (
1583
+ * <WhenWorkspaceFeatureEnabled slug="premium-analytics">
1584
+ * <AnalyticsDashboard />
1585
+ * </WhenWorkspaceFeatureEnabled>
1586
+ * );
1587
+ * }
1588
+ * ```
1589
+ *
1590
+ * @example
1591
+ * ```tsx
1592
+ * // Multiple features
1593
+ * function FeatureContent() {
1594
+ * return (
1595
+ * <>
1596
+ * <WhenWorkspaceFeatureEnabled slug="feature-a">
1597
+ * <FeatureA />
1598
+ * </WhenWorkspaceFeatureEnabled>
1599
+ * <WhenWorkspaceFeatureEnabled slug="feature-b">
1600
+ * <FeatureB />
1601
+ * </WhenWorkspaceFeatureEnabled>
1602
+ * </>
1603
+ * );
1604
+ * }
1605
+ * ```
1606
+ */
1607
+ declare const WhenWorkspaceFeatureEnabled: {
1608
+ (props: IProps): react.ReactNode;
1609
+ displayName: string;
1610
+ };
1611
+ /**
1612
+ * Conditional component that renders children only when the specified workspace feature is disabled.
1613
+ * Checks feature flags at the workspace level.
1614
+ *
1615
+ * @param props - Component props
1616
+ * @param props.slug - Feature flag slug/key to check
1617
+ * @param props.children - Content to render when feature is disabled
1618
+ *
1619
+ * @example
1620
+ * ```tsx
1621
+ * function UpgradePrompt() {
1622
+ * return (
1623
+ * <WhenWorkspaceFeatureDisabled slug="premium-feature">
1624
+ * <UpgradeButton />
1625
+ * </WhenWorkspaceFeatureDisabled>
1626
+ * );
1627
+ * }
1628
+ * ```
1629
+ */
1630
+ declare const WhenWorkspaceFeatureDisabled: {
1631
+ (props: IProps): react.ReactNode;
1632
+ displayName: string;
1633
+ };
1634
+ /**
1635
+ * Conditional component that renders children only when the specified user feature is enabled.
1636
+ * Checks feature flags at the user level (from UserProvider).
1637
+ *
1638
+ * @param props - Component props
1639
+ * @param props.slug - Feature flag slug/key to check
1640
+ * @param props.children - Content to render when feature is enabled
1641
+ *
1642
+ * @example
1643
+ * ```tsx
1644
+ * function BetaFeature() {
1645
+ * return (
1646
+ * <WhenUserFeatureEnabled slug="beta-access">
1647
+ * <BetaContent />
1648
+ * </WhenUserFeatureEnabled>
1649
+ * );
1650
+ * }
1651
+ * ```
1652
+ *
1653
+ * @example
1654
+ * ```tsx
1655
+ * // Edge case: Feature not loaded yet
1656
+ * function FeatureContent() {
1657
+ * const { isLoading } = useUserFeatures();
1658
+ *
1659
+ * if (isLoading) return <Loading />;
1660
+ *
1661
+ * return (
1662
+ * <WhenUserFeatureEnabled slug="feature-x">
1663
+ * <FeatureX />
1664
+ * </WhenUserFeatureEnabled>
1665
+ * );
1666
+ * }
1667
+ * ```
1668
+ */
1669
+ declare const WhenUserFeatureEnabled: {
1670
+ (props: IProps): react.ReactNode;
1671
+ displayName: string;
1672
+ };
1673
+ /**
1674
+ * Conditional component that renders children only when the specified user feature is disabled.
1675
+ * Checks feature flags at the user level (from UserProvider).
1676
+ *
1677
+ * @param props - Component props
1678
+ * @param props.slug - Feature flag slug/key to check
1679
+ * @param props.children - Content to render when feature is disabled
1680
+ *
1681
+ * @example
1682
+ * ```tsx
1683
+ * function UpgradePrompt() {
1684
+ * return (
1685
+ * <WhenUserFeatureDisabled slug="premium-access">
1686
+ * <UpgradeButton />
1687
+ * </WhenUserFeatureDisabled>
1688
+ * );
1689
+ * }
1690
+ * ```
1691
+ */
1692
+ declare const WhenUserFeatureDisabled: {
1693
+ (props: IProps): react.ReactNode;
1694
+ displayName: string;
1695
+ };
1696
+
1697
+ interface IWhenSubscriptionProps {
1698
+ /** Content to render when the condition is met (workspace has an active subscription). */
1699
+ children: React.ReactNode;
1700
+ /** Optional component/element to show while subscription is loading (e.g. <Skeleton />). */
1701
+ loadingComponent?: React.ReactNode;
1702
+ /** Optional component/element to show when condition is not met (e.g. <UpgradePrompt />). */
1703
+ fallbackComponent?: React.ReactNode;
1704
+ }
1705
+ /**
1706
+ * Renders children only when the current workspace has an active subscription (any plan).
1707
+ * Optionally pass loadingComponent (while loading) or fallbackComponent (when not subscribed).
1708
+ * Must be used within SubscriptionContextProvider.
1709
+ *
1710
+ * @param props - Component props
1711
+ * @param props.children - Content to render when subscribed
1712
+ * @param props.loadingComponent - Optional component/element to show while loading
1713
+ * @param props.fallbackComponent - Optional component/element to show when not subscribed
1714
+ * @returns ReactNode - children when subscribed, loadingComponent when loading, fallbackComponent when not subscribed, or null
1715
+ *
1716
+ * @example
1717
+ * ```tsx
1718
+ * <WhenSubscription>
1719
+ * <BillingSettings />
1720
+ * </WhenSubscription>
1721
+ * ```
1722
+ *
1723
+ * @example
1724
+ * ```tsx
1725
+ * <WhenSubscription
1726
+ * loadingComponent={<Skeleton />}
1727
+ * fallbackComponent={<UpgradePrompt />}
1728
+ * >
1729
+ * <BillingSettings />
1730
+ * </WhenSubscription>
1731
+ * ```
1732
+ */
1733
+ declare const WhenSubscription: {
1734
+ (props: IWhenSubscriptionProps): react.ReactNode;
1735
+ displayName: string;
1736
+ };
1737
+ /**
1738
+ * Renders children only when the current workspace has no subscription (or no current workspace).
1739
+ * Optionally pass loadingComponent (while loading) or fallbackComponent (when already subscribed).
1740
+ * Must be used within SubscriptionContextProvider.
1741
+ *
1742
+ * @param props - Component props
1743
+ * @param props.children - Content to render when not subscribed
1744
+ * @param props.loadingComponent - Optional component/element to show while loading
1745
+ * @param props.fallbackComponent - Optional component/element to show when already subscribed
1746
+ * @returns ReactNode - children when not subscribed, loadingComponent when loading, fallbackComponent when subscribed, or null
1747
+ *
1748
+ * @example
1749
+ * ```tsx
1750
+ * <WhenNoSubscription>
1751
+ * <UpgradePrompt />
1752
+ * </WhenNoSubscription>
1753
+ * ```
1754
+ *
1755
+ * @example
1756
+ * ```tsx
1757
+ * <WhenNoSubscription
1758
+ * loadingComponent={<Spinner />}
1759
+ * fallbackComponent={null}
1760
+ * >
1761
+ * <UpgradePrompt />
1762
+ * </WhenNoSubscription>
1763
+ * ```
1764
+ */
1765
+ declare const WhenNoSubscription: {
1766
+ (props: IWhenSubscriptionProps): react.ReactNode;
1767
+ displayName: string;
1768
+ };
1769
+ interface IWhenSubscriptionToPlansProps {
1770
+ /** Plan slugs to match (e.g. ['pro', 'enterprise']). Matching is case-insensitive. */
1771
+ plans: string[];
1772
+ /** Content to render when the workspace is on one of the given plans. */
1773
+ children: React.ReactNode;
1774
+ /** Optional component/element to show while subscription is loading (e.g. <Skeleton />). */
1775
+ loadingComponent?: React.ReactNode;
1776
+ /** Optional component/element to show when not on a matching plan (e.g. <UpgradeToPro />). */
1777
+ fallbackComponent?: React.ReactNode;
1778
+ }
1779
+ /**
1780
+ * Renders children only when the current workspace is subscribed to one of the given plans.
1781
+ * Matches by plan slug only. Optionally pass loadingComponent (while loading) or fallbackComponent (when not on a matching plan).
1782
+ * Must be used within SubscriptionContextProvider.
1783
+ *
1784
+ * @param props - Component props
1785
+ * @param props.plans - Plan slugs to match (e.g. ['pro', 'enterprise'])
1786
+ * @param props.children - Content to render when on a matching plan
1787
+ * @param props.loadingComponent - Optional component/element to show while loading
1788
+ * @param props.fallbackComponent - Optional component/element to show when not on a matching plan
1789
+ * @returns ReactNode - children when on a matching plan, loadingComponent when loading, fallbackComponent when not matching, or null
1790
+ *
1791
+ * @example
1792
+ * ```tsx
1793
+ * <WhenSubscriptionToPlans plans={['pro', 'enterprise']}>
1794
+ * <AdvancedAnalytics />
1795
+ * </WhenSubscriptionToPlans>
1796
+ * ```
1797
+ *
1798
+ * @example
1799
+ * ```tsx
1800
+ * <WhenSubscriptionToPlans
1801
+ * plans={['pro', 'enterprise']}
1802
+ * loadingComponent={<Skeleton />}
1803
+ * fallbackComponent={<UpgradeToPro />}
1804
+ * >
1805
+ * <AdvancedAnalytics />
1806
+ * </WhenSubscriptionToPlans>
1807
+ * ```
1808
+ */
1809
+ declare const WhenSubscriptionToPlans: {
1810
+ (props: IWhenSubscriptionToPlansProps): react.ReactNode;
1811
+ displayName: string;
1812
+ };
1813
+ interface IWhenTrialingProps {
1814
+ /** Content to render when the condition is met. */
1815
+ children: React.ReactNode;
1816
+ /** Optional component/element to show while subscription is loading. */
1817
+ loadingComponent?: React.ReactNode;
1818
+ /** Optional component/element to show when condition is not met. */
1819
+ fallbackComponent?: React.ReactNode;
1820
+ }
1821
+ /**
1822
+ * Renders children only when the current workspace subscription is in trial (status === 'trialing').
1823
+ * Must be used within SubscriptionContextProvider.
1824
+ *
1825
+ * @example
1826
+ * ```tsx
1827
+ * <WhenTrialing fallbackComponent={<NormalContent />}>
1828
+ * <TrialBanner />
1829
+ * </WhenTrialing>
1830
+ * ```
1831
+ */
1832
+ declare const WhenTrialing: {
1833
+ (props: IWhenTrialingProps): react.ReactNode;
1834
+ displayName: string;
1835
+ };
1836
+ /**
1837
+ * Renders children only when the current workspace subscription is NOT in trial.
1838
+ * This includes: no subscription, active, canceled, past_due, etc.
1839
+ * Must be used within SubscriptionContextProvider.
1840
+ *
1841
+ * @example
1842
+ * ```tsx
1843
+ * <WhenNotTrialing>
1844
+ * <RegularPricingPage />
1845
+ * </WhenNotTrialing>
1846
+ * ```
1847
+ */
1848
+ declare const WhenNotTrialing: {
1849
+ (props: IWhenTrialingProps): react.ReactNode;
1850
+ displayName: string;
1851
+ };
1852
+ interface IWhenTrialEndingProps {
1853
+ /** Content to render when trial is ending soon. */
1854
+ children: React.ReactNode;
1855
+ /** Optional component/element to show while subscription is loading. */
1856
+ loadingComponent?: React.ReactNode;
1857
+ /** Optional component/element to show when trial is not ending soon. */
1858
+ fallbackComponent?: React.ReactNode;
1859
+ /** Number of days threshold to consider "ending soon". Defaults to 3. */
1860
+ daysThreshold?: number;
1861
+ }
1862
+ /**
1863
+ * Renders children only when the subscription is trialing AND the trial ends within
1864
+ * the given threshold (default 3 days). Useful for showing urgent upgrade prompts.
1865
+ * Must be used within SubscriptionContextProvider.
1866
+ *
1867
+ * @example
1868
+ * ```tsx
1869
+ * <WhenTrialEnding daysThreshold={5}>
1870
+ * <UpgradeBanner />
1871
+ * </WhenTrialEnding>
1872
+ * ```
1873
+ */
1874
+ declare const WhenTrialEnding: {
1875
+ (props: IWhenTrialEndingProps): react.ReactNode;
1876
+ displayName: string;
1877
+ };
1878
+
1879
+ interface IWhenQuotaProps {
1880
+ /** Quota slug to check (e.g. 'api_calls', 'emails', 'storage'). */
1881
+ slug: string;
1882
+ /** Content to render when the condition is met. */
1883
+ children: React.ReactNode;
1884
+ /** Optional component/element to show while quota usage is loading (e.g. <Skeleton />). */
1885
+ loadingComponent?: React.ReactNode;
1886
+ /** Optional component/element to show when condition is not met (e.g. <UpgradePrompt />). */
1887
+ fallbackComponent?: React.ReactNode;
1888
+ }
1889
+ interface IWhenQuotaThresholdProps extends IWhenQuotaProps {
1890
+ /** Usage percentage threshold (0-100). Children render when usage >= this percentage. */
1891
+ threshold: number;
1892
+ }
1893
+ /**
1894
+ * Renders children only when the specified quota has remaining units (available > 0).
1895
+ * Must be used within QuotaUsageContextProvider (included in SaaSOSProvider by default).
1896
+ *
1897
+ * @example
1898
+ * ```tsx
1899
+ * <WhenQuotaAvailable slug="api_calls">
1900
+ * <MakeApiCallButton />
1901
+ * </WhenQuotaAvailable>
1902
+ * ```
1903
+ *
1904
+ * @example
1905
+ * ```tsx
1906
+ * <WhenQuotaAvailable
1907
+ * slug="emails"
1908
+ * loadingComponent={<Skeleton />}
1909
+ * fallbackComponent={<p>Email quota exhausted. <UpgradeLink /></p>}
1910
+ * >
1911
+ * <SendEmailButton />
1912
+ * </WhenQuotaAvailable>
1913
+ * ```
1914
+ */
1915
+ declare const WhenQuotaAvailable: {
1916
+ (props: IWhenQuotaProps): react.ReactNode;
1917
+ displayName: string;
1918
+ };
1919
+ /**
1920
+ * Renders children only when the specified quota is fully consumed (available <= 0).
1921
+ * Must be used within QuotaUsageContextProvider (included in SaaSOSProvider by default).
1922
+ *
1923
+ * @example
1924
+ * ```tsx
1925
+ * <WhenQuotaExhausted slug="api_calls">
1926
+ * <UpgradePrompt message="You've used all your API calls this month." />
1927
+ * </WhenQuotaExhausted>
1928
+ * ```
1929
+ *
1930
+ * @example
1931
+ * ```tsx
1932
+ * <WhenQuotaExhausted
1933
+ * slug="storage"
1934
+ * loadingComponent={<Spinner />}
1935
+ * fallbackComponent={null}
1936
+ * >
1937
+ * <StorageFullBanner />
1938
+ * </WhenQuotaExhausted>
1939
+ * ```
1940
+ */
1941
+ declare const WhenQuotaExhausted: {
1942
+ (props: IWhenQuotaProps): react.ReactNode;
1943
+ displayName: string;
1944
+ };
1945
+ /**
1946
+ * Renders children only when the specified quota is in overage (consumed > included).
1947
+ * Must be used within QuotaUsageContextProvider (included in SaaSOSProvider by default).
1948
+ *
1949
+ * @example
1950
+ * ```tsx
1951
+ * <WhenQuotaOverage slug="api_calls">
1952
+ * <OverageBillingWarning />
1953
+ * </WhenQuotaOverage>
1954
+ * ```
1955
+ *
1956
+ * @example
1957
+ * ```tsx
1958
+ * <WhenQuotaOverage
1959
+ * slug="emails"
1960
+ * loadingComponent={<Skeleton />}
1961
+ * fallbackComponent={null}
1962
+ * >
1963
+ * <p>You are being billed for overage usage.</p>
1964
+ * </WhenQuotaOverage>
1965
+ * ```
1966
+ */
1967
+ declare const WhenQuotaOverage: {
1968
+ (props: IWhenQuotaProps): react.ReactNode;
1969
+ displayName: string;
1970
+ };
1971
+ /**
1972
+ * Renders children when the specified quota's usage percentage reaches or exceeds the threshold.
1973
+ * Usage percentage = (consumed / included) * 100. If included is 0 and consumed > 0, treats as 100%.
1974
+ * Must be used within QuotaUsageContextProvider (included in SaaSOSProvider by default).
1975
+ *
1976
+ * @example
1977
+ * ```tsx
1978
+ * <WhenQuotaThreshold slug="api_calls" threshold={80}>
1979
+ * <p>Warning: You've used over 80% of your API calls.</p>
1980
+ * </WhenQuotaThreshold>
1981
+ * ```
1982
+ *
1983
+ * @example
1984
+ * ```tsx
1985
+ * <WhenQuotaThreshold
1986
+ * slug="storage"
1987
+ * threshold={90}
1988
+ * loadingComponent={<Spinner />}
1989
+ * fallbackComponent={null}
1990
+ * >
1991
+ * <StorageWarningBanner />
1992
+ * </WhenQuotaThreshold>
1993
+ * ```
1994
+ */
1995
+ declare const WhenQuotaThreshold: {
1996
+ (props: IWhenQuotaThresholdProps): react.ReactNode;
1997
+ displayName: string;
1998
+ };
1999
+
2000
+ /**
2001
+ * Value provided by SubscriptionContext and returned by useSubscriptionContext.
2002
+ */
2003
+ interface SubscriptionContextValue {
2004
+ /** Current subscription response for the current workspace, or null if none or not loaded. */
2005
+ response: ISubscriptionResponse | null;
2006
+ /** True while subscription is being fetched. */
2007
+ loading: boolean;
2008
+ /** Error message if the last fetch failed, or null. */
2009
+ error: string | null;
2010
+ /** Refetch subscription for the current workspace. Call after plan change (e.g. upgrade) or when subscription was updated elsewhere. */
2011
+ refetch: () => Promise<void>;
2012
+ }
2013
+
2014
+ /**
2015
+ * Provides subscription data for the current workspace to subscription gate components.
2016
+ * Fetches when workspace changes; refetches when subscription is invalidated (e.g. after plan change).
2017
+ * Must wrap (or be ancestor of) any component that uses WhenSubscription, WhenNoSubscription,
2018
+ * WhenSubscriptionToPlans, or useSubscriptionContext. Included in SaaSOSProvider by default.
2019
+ *
2020
+ * @param props - Component props
2021
+ * @param props.children - React tree that may use subscription gates or useSubscriptionContext
2022
+ * @returns Provider element that supplies subscription context to descendants
2023
+ */
2024
+ declare const SubscriptionContextProvider: react__default.FC<{
2025
+ children: ReactNode;
2026
+ }>;
2027
+ /**
2028
+ * Returns subscription data for the current workspace. Must be used within SubscriptionContextProvider.
2029
+ *
2030
+ * @returns SubscriptionContextValue - { response, loading, refetch }
2031
+ * @throws Error if used outside SubscriptionContextProvider
2032
+ */
2033
+ declare function useSubscriptionContext(): SubscriptionContextValue;
2034
+
2035
+ /**
2036
+ * Value provided by QuotaUsageContext and returned by useQuotaUsageContext.
2037
+ */
2038
+ interface QuotaUsageContextValue {
2039
+ /** Current quota usage statuses keyed by slug, or null if not loaded. */
2040
+ quotas: Record<string, IQuotaUsageStatus> | null;
2041
+ /** True while quota usage is being fetched. */
2042
+ loading: boolean;
2043
+ /** Error message if the last fetch failed, or null. */
2044
+ error: string | null;
2045
+ /** Refetch all quota usage for the current workspace. Call after recording usage or when usage was updated elsewhere. */
2046
+ refetch: () => Promise<void>;
2047
+ }
2048
+
2049
+ /**
2050
+ * Provides quota usage data for the current workspace to quota gate components.
2051
+ * Fetches when workspace changes; refetches when quota usage is invalidated (e.g. after recording usage).
2052
+ * Must wrap (or be ancestor of) any component that uses WhenQuotaAvailable, WhenQuotaExhausted,
2053
+ * WhenQuotaOverage, WhenQuotaThreshold, or useQuotaUsageContext. Included in SaaSOSProvider by default.
2054
+ *
2055
+ * @param props - Component props
2056
+ * @param props.children - React tree that may use quota gates or useQuotaUsageContext
2057
+ * @returns Provider element that supplies quota usage context to descendants
2058
+ */
2059
+ declare const QuotaUsageContextProvider: react__default.FC<{
2060
+ children: ReactNode;
2061
+ }>;
2062
+ /**
2063
+ * Returns quota usage data for the current workspace. Must be used within QuotaUsageContextProvider.
2064
+ *
2065
+ * @returns QuotaUsageContextValue - { quotas, loading, refetch }
2066
+ * @throws Error if used outside QuotaUsageContextProvider
2067
+ */
2068
+ declare function useQuotaUsageContext(): QuotaUsageContextValue;
2069
+
2070
+ /**
2071
+ * Hook to access OS (organization) state (serverUrl, version, orgId, auth, settings).
2072
+ * Prefer useSaaSSettings() when you only need settings.
2073
+ */
2074
+ declare function useSaaSOs(): IOsState;
2075
+ /**
2076
+ * Hook to access organization settings from the OS context.
2077
+ * Automatically fetches settings once when OS config is ready.
2078
+ * Safe to call from multiple components — only one fetch is made.
2079
+ */
2080
+ declare function useSaaSSettings(): {
2081
+ settings: ISettings | null | undefined;
2082
+ getSettings: (signal?: AbortSignal) => Promise<ISettings | null>;
2083
+ };
2084
+
2085
+ interface UserContextValue {
2086
+ attributes: Record<string, string | number | boolean>;
2087
+ features: Record<string, boolean>;
2088
+ isLoading: boolean;
2089
+ error: Error | null;
2090
+ updateAttributes: (updates: Record<string, string | number | boolean>) => Promise<IUser>;
2091
+ updateAttribute: (attributeKey: string, value: string | number | boolean) => Promise<IUser>;
2092
+ refreshAttributes: () => Promise<void>;
2093
+ refreshFeatures: () => Promise<void>;
2094
+ }
2095
+
2096
+ /**
2097
+ * Hook to access user attributes from the UserProvider.
2098
+ * Must be used within a UserProvider component.
2099
+ *
2100
+ * @returns User context object containing:
2101
+ * - `attributes`: Record of user attribute key-value pairs
2102
+ * - `isLoading`: Boolean indicating if attributes are being loaded
2103
+ * - `error`: Error message string (null if no error)
2104
+ * - `refreshAttributes()`: Function to manually refresh attributes
2105
+ *
2106
+ * @throws {Error} If used outside of UserProvider
2107
+ *
2108
+ * @example
2109
+ * ```tsx
2110
+ * function UserProfile() {
2111
+ * const { attributes, isLoading } = useUserAttributes();
2112
+ *
2113
+ * if (isLoading) return <Loading />;
2114
+ *
2115
+ * return (
2116
+ * <div>
2117
+ * <p>Plan: {attributes?.plan}</p>
2118
+ * <p>Company: {attributes?.company}</p>
2119
+ * </div>
2120
+ * );
2121
+ * }
2122
+ * ```
2123
+ */
2124
+ declare function useUserAttributes(): UserContextValue;
2125
+ /**
2126
+ * Hook to access user feature flags from the UserProvider.
2127
+ * Must be used within a UserProvider component.
2128
+ *
2129
+ * @returns An object containing:
2130
+ * - `features`: Record of feature flag key-value pairs (boolean values)
2131
+ * - `isLoading`: Boolean indicating if features are being loaded
2132
+ * - `error`: Error message string (null if no error)
2133
+ * - `refreshFeatures()`: Function to manually refresh features
2134
+ * - `isFeatureEnabled(featureId)`: Function to check if a specific feature is enabled
2135
+ *
2136
+ * @throws {Error} If used outside of UserProvider
2137
+ *
2138
+ * @example
2139
+ * ```tsx
2140
+ * function FeatureContent() {
2141
+ * const { isFeatureEnabled, isLoading } = useUserFeatures();
2142
+ *
2143
+ * if (isLoading) return <Loading />;
2144
+ *
2145
+ * if (isFeatureEnabled('premium-feature')) {
2146
+ * return <PremiumFeature />;
2147
+ * }
2148
+ *
2149
+ * return <BasicFeature />;
2150
+ * }
2151
+ * ```
2152
+ *
2153
+ * @example
2154
+ * ```tsx
2155
+ * // Check multiple features
2156
+ * function Dashboard() {
2157
+ * const { isFeatureEnabled } = useUserFeatures();
2158
+ *
2159
+ * return (
2160
+ * <div>
2161
+ * {isFeatureEnabled('analytics') && <Analytics />}
2162
+ * {isFeatureEnabled('reports') && <Reports />}
2163
+ * </div>
2164
+ * );
2165
+ * }
2166
+ * ```
2167
+ */
2168
+ declare function useUserFeatures(): {
2169
+ features: Record<string, boolean>;
2170
+ isLoading: boolean;
2171
+ error: Error | null;
2172
+ refreshFeatures: () => Promise<void>;
2173
+ isFeatureEnabled: (featureId: string) => boolean;
2174
+ };
2175
+
2176
+ declare const useSaaSWorkspaces: () => {
2177
+ workspaces: IWorkspace[];
2178
+ loading: boolean;
2179
+ error: string | null;
2180
+ fetchWorkspaces: () => Promise<void>;
2181
+ refreshWorkspaces: () => Promise<void>;
2182
+ refreshing: boolean;
2183
+ currentWorkspace: IWorkspace | null;
2184
+ setCurrentWorkspace: (ws: IWorkspace, options?: {
2185
+ forceEmit?: boolean;
2186
+ }) => void;
2187
+ switchToWorkspace: (ws: IWorkspace, options?: {
2188
+ forceEmit?: boolean;
2189
+ }) => Promise<void>;
2190
+ resetCurrentWorkspace: () => void;
2191
+ createWorkspace: (name: string, image?: string) => Promise<void>;
2192
+ allFeatures: IWorkspaceFeature[];
2193
+ getFeatures: () => Promise<IWorkspaceFeature[] | null>;
2194
+ updateFeature: (workspaceId: string, key: string, value: boolean) => Promise<IWorkspace>;
2195
+ getWorkspace: (workspaceId: string) => Promise<IWorkspace>;
2196
+ updateWorkspace: (ws: IWorkspace, _data: Partial<IWorkspace>) => Promise<void>;
2197
+ getUsers: (workspaceId: string) => Promise<IWorkspaceUser[]>;
2198
+ addUser: (workspaceId: string, email: string, role: string) => Promise<{
2199
+ userId: string;
2200
+ workspace: IWorkspace;
2201
+ message: string;
2202
+ }>;
2203
+ removeUser: (workspaceId: string, userId: string) => Promise<{
2204
+ userId: string;
2205
+ workspace: IWorkspace;
2206
+ message: string;
2207
+ }>;
2208
+ updateUser: (workspaceId: string, userId: string, config: Partial<IWorkspaceUser>) => Promise<{
2209
+ userId: string;
2210
+ workspace: IWorkspace;
2211
+ message: string;
2212
+ }>;
2213
+ getProfile: () => Promise<IUser>;
2214
+ updateUserProfile: (config: Partial<IUser>) => Promise<IUser>;
2215
+ deleteWorkspace: (workspaceId: string) => Promise<{
2216
+ success: boolean;
2217
+ }>;
2218
+ switching: boolean;
2219
+ switchingToId: string | null;
2220
+ };
2221
+
2222
+ /**
2223
+ * Hook to get public plans by slug (no auth required).
2224
+ * Returns items (features, limits, quotas) and plans (with pricing).
2225
+ * Uses orgId from SaaSOSProvider - must be inside provider.
2226
+ *
2227
+ * @param slug - Plan group slug (e.g. 'main-pricing', 'enterprise')
2228
+ * @returns { items, plans, loading, error, refetch }
2229
+ */
2230
+ declare const usePublicPlans: (slug: string) => {
2231
+ items: IPublicPlanItem[];
2232
+ plans: IPublicPlanVersion[];
2233
+ notes: string | undefined;
2234
+ loading: boolean;
2235
+ error: string | null;
2236
+ refetch: () => Promise<void>;
2237
+ };
2238
+ /**
2239
+ * Hook to get a single plan group version by ID (no auth required).
2240
+ * Use this for public pricing pages when you have the groupVersionId (e.g. from config or URL).
2241
+ *
2242
+ * @param groupVersionId - The plan group version ID to fetch. Pass null/undefined to disable fetching.
2243
+ * @returns An object containing:
2244
+ * - `planGroupVersion`: Plan group version data (null if not loaded)
2245
+ * - `loading`: Boolean indicating if data is being fetched
2246
+ * - `error`: Error message string (null if no error)
2247
+ * - `refetch()`: Function to manually refetch
2248
+ *
2249
+ * @example
2250
+ * ```tsx
2251
+ * function PublicPricingPage() {
2252
+ * const groupVersionId = 'your-plan-group-version-id'; // from config or URL
2253
+ * const { planGroupVersion, loading } = usePublicPlanGroupVersion(groupVersionId);
2254
+ *
2255
+ * if (loading) return <Loading />;
2256
+ * if (!planGroupVersion) return null;
2257
+ *
2258
+ * const plans = Array.isArray(planGroupVersion.planVersionIds)
2259
+ * ? planGroupVersion.planVersionIds.filter((p): p is IPlanVersionWithPlan => typeof p !== 'string')
2260
+ * : [];
2261
+ *
2262
+ * return (
2263
+ * <div>
2264
+ * {plans.map(plan => <PlanCard key={plan._id} plan={plan} />)}
2265
+ * </div>
2266
+ * );
2267
+ * }
2268
+ * ```
2269
+ */
2270
+ declare const usePublicPlanGroupVersion: (groupVersionId: string | null | undefined) => {
2271
+ planGroupVersion: IPlanGroupVersion | null;
2272
+ loading: boolean;
2273
+ error: string | null;
2274
+ refetch: () => Promise<void>;
2275
+ };
2276
+ /**
2277
+ * Hook to get and manage the current subscription for a workspace.
2278
+ * Automatically fetches subscription when workspaceId changes.
2279
+ *
2280
+ * @param workspaceId - The workspace ID to get subscription for. Can be null/undefined to disable fetching.
2281
+ * @returns An object containing:
2282
+ * - `subscription`: Current subscription data (null if no subscription or not loaded)
2283
+ * - `loading`: Boolean indicating if subscription is being fetched
2284
+ * - `error`: Error message string (null if no error)
2285
+ * - `refetch()`: Function to manually refetch the subscription
2286
+ *
2287
+ * @example
2288
+ * ```tsx
2289
+ * function SubscriptionStatus() {
2290
+ * const { currentWorkspace } = useSaaSWorkspaces();
2291
+ * const { subscription, loading, error } = useSubscription(currentWorkspace?._id);
2292
+ *
2293
+ * if (loading) return <Loading />;
2294
+ * if (error) return <Error message={error} />;
2295
+ * if (!subscription) return <p>No active subscription</p>;
2296
+ *
2297
+ * return <p>Plan: {subscription.plan.name}</p>;
2298
+ * }
2299
+ * ```
2300
+ *
2301
+ * @example
2302
+ * ```tsx
2303
+ * // Edge case: Workspace ID changes
2304
+ * function SubscriptionComponent({ workspaceId }) {
2305
+ * const { subscription, refetch } = useSubscription(workspaceId);
2306
+ *
2307
+ * // Subscription automatically refetches when workspaceId changes
2308
+ * // Use refetch() to manually refresh after mutations
2309
+ * return <SubscriptionDetails subscription={subscription} />;
2310
+ * }
2311
+ * ```
2312
+ */
2313
+ declare const useSubscription: (workspaceId: string | null | undefined) => {
2314
+ subscription: ISubscriptionResponse | null;
2315
+ loading: boolean;
2316
+ error: string | null;
2317
+ refetch: () => Promise<void>;
2318
+ };
2319
+ /**
2320
+ * Hook to get the plan group for a workspace.
2321
+ * Returns the plan group containing the current plan if subscription exists,
2322
+ * otherwise returns the latest published group.
2323
+ * Automatically fetches when workspaceId or groupVersionId changes.
2324
+ *
2325
+ * @param workspaceId - The workspace ID to get plan group for. Can be null/undefined to disable fetching.
2326
+ * @param groupVersionId - Optional: specific group version ID to fetch (for viewing historical versions)
2327
+ * @returns An object containing:
2328
+ * - `planGroup`: Plan group data (null if not loaded)
2329
+ * - `loading`: Boolean indicating if plan group is being fetched
2330
+ * - `error`: Error message string (null if no error)
2331
+ * - `refetch()`: Function to manually refetch the plan group
2332
+ *
2333
+ * @example
2334
+ * ```tsx
2335
+ * function PlanGroupDisplay() {
2336
+ * const { currentWorkspace } = useSaaSWorkspaces();
2337
+ * const { planGroup, loading } = usePlanGroup(currentWorkspace?._id);
2338
+ *
2339
+ * if (loading) return <Loading />;
2340
+ * if (!planGroup) return <p>No plan group available</p>;
2341
+ *
2342
+ * return (
2343
+ * <div>
2344
+ * <h3>{planGroup.group.name}</h3>
2345
+ * {planGroup.plans.map(plan => (
2346
+ * <PlanCard key={plan._id} plan={plan} />
2347
+ * ))}
2348
+ * </div>
2349
+ * );
2350
+ * }
2351
+ * ```
2352
+ *
2353
+ * @example
2354
+ * ```tsx
2355
+ * // Fetch specific version for comparison
2356
+ * function PlanVersionComparison() {
2357
+ * const { currentWorkspace } = useSaaSWorkspaces();
2358
+ * const current = usePlanGroup(currentWorkspace?._id);
2359
+ * const previous = usePlanGroup(currentWorkspace?._id, 'previous-version-id');
2360
+ *
2361
+ * return <ComparePlans current={current.planGroup} previous={previous.planGroup} />;
2362
+ * }
2363
+ * ```
2364
+ */
2365
+ declare const usePlanGroup: (workspaceId: string | null | undefined, groupVersionId?: string | null) => {
2366
+ planGroup: IPlanGroupResponse | null;
2367
+ loading: boolean;
2368
+ error: string | null;
2369
+ refetch: () => Promise<void>;
2370
+ };
2371
+ /**
2372
+ * Hook to get all available versions of a plan group for a workspace.
2373
+ * Shows current version and available newer versions for upgrade paths.
2374
+ * Automatically fetches when workspaceId changes.
2375
+ *
2376
+ * @param workspaceId - The workspace ID to get plan group versions for. Can be null/undefined to disable fetching.
2377
+ * @returns An object containing:
2378
+ * - `versions`: Plan group versions response with currentVersion and availableVersions
2379
+ * - `loading`: Boolean indicating if versions are being fetched
2380
+ * - `error`: Error message string (null if no error)
2381
+ * - `refetch()`: Function to manually refetch the versions
2382
+ *
2383
+ * @example
2384
+ * ```tsx
2385
+ * function UpgradeOptions() {
2386
+ * const { currentWorkspace } = useSaaSWorkspaces();
2387
+ * const { versions, loading } = usePlanGroupVersions(currentWorkspace?._id);
2388
+ *
2389
+ * if (loading) return <Loading />;
2390
+ *
2391
+ * return (
2392
+ * <div>
2393
+ * <p>Current: {versions?.currentVersion.name}</p>
2394
+ * <h4>Available Upgrades:</h4>
2395
+ * {versions?.availableVersions.map(version => (
2396
+ * <UpgradeCard key={version._id} version={version} />
2397
+ * ))}
2398
+ * </div>
2399
+ * );
2400
+ * }
2401
+ * ```
2402
+ */
2403
+ declare const usePlanGroupVersions: (workspaceId: string | null | undefined) => {
2404
+ versions: IPlanGroupVersionsResponse | null;
2405
+ loading: boolean;
2406
+ error: string | null;
2407
+ refetch: () => Promise<void>;
2408
+ };
2409
+ /**
2410
+ * Hook to create a checkout session for a new subscription.
2411
+ * Returns a function to initiate the checkout process.
2412
+ *
2413
+ * @param workspaceId - The workspace ID to create checkout session for. Can be null/undefined.
2414
+ * @returns An object containing:
2415
+ * - `createCheckoutSession(request)`: Function to create checkout session (throws if workspaceId is null)
2416
+ * - `loading`: Boolean indicating if checkout session is being created
2417
+ * - `error`: Error message string (null if no error)
2418
+ *
2419
+ * @example
2420
+ * ```tsx
2421
+ * function SubscribeButton({ planVersionId }) {
2422
+ * const { currentWorkspace } = useSaaSWorkspaces();
2423
+ * const { createCheckoutSession, loading } = useCreateCheckoutSession(currentWorkspace?._id);
2424
+ *
2425
+ * const handleSubscribe = async () => {
2426
+ * try {
2427
+ * const result = await createCheckoutSession({
2428
+ * planVersionId,
2429
+ * successUrl: window.location.href,
2430
+ * cancelUrl: window.location.href,
2431
+ * });
2432
+ * // Redirect to checkout
2433
+ * window.location.href = result.checkoutUrl;
2434
+ * } catch (error) {
2435
+ * console.error('Failed to create checkout:', error);
2436
+ * }
2437
+ * };
2438
+ *
2439
+ * return (
2440
+ * <button onClick={handleSubscribe} disabled={loading}>
2441
+ * {loading ? 'Loading...' : 'Subscribe'}
2442
+ * </button>
2443
+ * );
2444
+ * }
2445
+ * ```
2446
+ *
2447
+ * @example
2448
+ * ```tsx
2449
+ * // Edge case: Workspace ID not available
2450
+ * function SubscribeButton() {
2451
+ * const { currentWorkspace } = useSaaSWorkspaces();
2452
+ * const { createCheckoutSession } = useCreateCheckoutSession(currentWorkspace?._id);
2453
+ *
2454
+ * const handleSubscribe = async () => {
2455
+ * try {
2456
+ * await createCheckoutSession({ planVersionId: 'plan-123' });
2457
+ * } catch (error) {
2458
+ * // Error: "Workspace ID is required"
2459
+ * alert('Please select a workspace first');
2460
+ * }
2461
+ * };
2462
+ *
2463
+ * return <button onClick={handleSubscribe}>Subscribe</button>;
2464
+ * }
2465
+ * ```
2466
+ */
2467
+ declare const useCreateCheckoutSession: (workspaceId: string | null | undefined) => {
2468
+ createCheckoutSession: (request: ICheckoutSessionRequest) => Promise<CheckoutResult>;
2469
+ loading: boolean;
2470
+ error: string | null;
2471
+ };
2472
+ /**
2473
+ * Hook to update subscription (upgrade/downgrade).
2474
+ * Returns checkout session if payment is required, otherwise returns subscription update response.
2475
+ *
2476
+ * @param workspaceId - The workspace ID to update subscription for. Can be null/undefined.
2477
+ * @returns An object containing:
2478
+ * - `updateSubscription(planVersionId, options?)`: Function to update subscription (throws if workspaceId is null)
2479
+ * - `loading`: Boolean indicating if subscription is being updated
2480
+ * - `error`: Error message string (null if no error)
2481
+ *
2482
+ * @example
2483
+ * ```tsx
2484
+ * function UpgradeButton({ planVersionId }) {
2485
+ * const { currentWorkspace } = useSaaSWorkspaces();
2486
+ * const { updateSubscription, loading } = useUpdateSubscription(currentWorkspace?._id);
2487
+ *
2488
+ * const handleUpgrade = async () => {
2489
+ * try {
2490
+ * const result = await updateSubscription(planVersionId, {
2491
+ * billingInterval: 'monthly',
2492
+ * successUrl: window.location.href,
2493
+ * cancelUrl: window.location.href,
2494
+ * });
2495
+ *
2496
+ * // Check if payment is required
2497
+ * if ('checkoutUrl' in result) {
2498
+ * window.location.href = result.checkoutUrl;
2499
+ * } else {
2500
+ * // Subscription updated without payment
2501
+ * alert('Subscription updated successfully!');
2502
+ * }
2503
+ * } catch (error) {
2504
+ * console.error('Failed to update subscription:', error);
2505
+ * }
2506
+ * };
2507
+ *
2508
+ * return (
2509
+ * <button onClick={handleUpgrade} disabled={loading}>
2510
+ * {loading ? 'Upgrading...' : 'Upgrade'}
2511
+ * </button>
2512
+ * );
2513
+ * }
2514
+ * ```
2515
+ *
2516
+ * @example
2517
+ * ```tsx
2518
+ * // Handle both checkout and direct update responses
2519
+ * function SubscriptionUpdater({ planVersionId }) {
2520
+ * const { updateSubscription } = useUpdateSubscription(workspaceId);
2521
+ *
2522
+ * const handleUpdate = async () => {
2523
+ * const result = await updateSubscription(planVersionId);
2524
+ *
2525
+ * // Type guard to check response type
2526
+ * if ('checkoutUrl' in result) {
2527
+ * // Redirect to payment
2528
+ * window.location.href = result.checkoutUrl;
2529
+ * } else {
2530
+ * // Direct update successful
2531
+ * console.log('Updated subscription:', result.subscription);
2532
+ * }
2533
+ * };
2534
+ *
2535
+ * return <button onClick={handleUpdate}>Update</button>;
2536
+ * }
2537
+ * ```
2538
+ */
2539
+ declare const useUpdateSubscription: (workspaceId: string | null | undefined) => {
2540
+ updateSubscription: (planVersionId: string, options?: {
2541
+ billingInterval?: BillingInterval;
2542
+ successUrl?: string;
2543
+ cancelUrl?: string;
2544
+ }) => Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
2545
+ loading: boolean;
2546
+ error: string | null;
2547
+ };
2548
+ /**
2549
+ * Combined hook that provides both subscription and plan group data.
2550
+ * Useful for subscription management pages that need both pieces of data.
2551
+ * Combines useSubscription, usePlanGroup, and useUpdateSubscription.
2552
+ *
2553
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
2554
+ * @param groupVersionId - Optional: specific group version ID to fetch
2555
+ * @returns An object containing:
2556
+ * - `subscription`: Current subscription data (from useSubscription)
2557
+ * - `planGroup`: Plan group data (from usePlanGroup)
2558
+ * - `loading`: Boolean indicating if any operation is in progress
2559
+ * - `error`: Error message string (null if no error)
2560
+ * - `updateSubscription(planVersionId, options?)`: Function to update subscription
2561
+ * - `refetch()`: Function to refetch both subscription and plan group
2562
+ *
2563
+ * @example
2564
+ * ```tsx
2565
+ * function SubscriptionManagementPage() {
2566
+ * const { currentWorkspace } = useSaaSWorkspaces();
2567
+ * const {
2568
+ * subscription,
2569
+ * planGroup,
2570
+ * loading,
2571
+ * updateSubscription,
2572
+ * refetch,
2573
+ * } = useSubscriptionManagement(currentWorkspace?._id);
2574
+ *
2575
+ * if (loading) return <Loading />;
2576
+ *
2577
+ * return (
2578
+ * <div>
2579
+ * <CurrentPlan subscription={subscription} />
2580
+ * <AvailablePlans planGroup={planGroup} onSelect={updateSubscription} />
2581
+ * <button onClick={refetch}>Refresh</button>
2582
+ * </div>
2583
+ * );
2584
+ * }
2585
+ * ```
2586
+ */
2587
+ declare const useSubscriptionManagement: (workspaceId: string | null | undefined, groupVersionId?: string | null) => {
2588
+ subscription: ISubscriptionResponse | null;
2589
+ planGroup: IPlanGroupResponse | null;
2590
+ loading: boolean;
2591
+ error: string | null;
2592
+ updateSubscription: (planVersionId: string, options?: {
2593
+ billingInterval?: BillingInterval;
2594
+ successUrl?: string;
2595
+ cancelUrl?: string;
2596
+ }) => Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
2597
+ refetch: () => Promise<void>;
2598
+ };
2599
+ /**
2600
+ * Hook to list invoices for a workspace subscription with pagination support.
2601
+ * Automatically fetches when workspaceId, limit, or startingAfter changes.
2602
+ *
2603
+ * @param workspaceId - The workspace ID to get invoices for. Can be null/undefined to disable fetching.
2604
+ * @param limit - Number of invoices to return (default: 10)
2605
+ * @param startingAfter - Invoice ID to start after (for pagination)
2606
+ * @returns An object containing:
2607
+ * - `invoices`: Array of invoice objects
2608
+ * - `hasMore`: Boolean indicating if there are more invoices to load
2609
+ * - `loading`: Boolean indicating if invoices are being fetched
2610
+ * - `error`: Error message string (null if no error)
2611
+ * - `refetch()`: Function to manually refetch invoices
2612
+ *
2613
+ * @example
2614
+ * ```tsx
2615
+ * function InvoiceList() {
2616
+ * const { currentWorkspace } = useSaaSWorkspaces();
2617
+ * const { invoices, hasMore, loading, refetch } = useInvoices(currentWorkspace?._id, 10);
2618
+ *
2619
+ * if (loading) return <Loading />;
2620
+ *
2621
+ * return (
2622
+ * <div>
2623
+ * {invoices.map(invoice => (
2624
+ * <InvoiceCard key={invoice._id} invoice={invoice} />
2625
+ * ))}
2626
+ * {hasMore && <button onClick={() => refetch()}>Load More</button>}
2627
+ * </div>
2628
+ * );
2629
+ * }
2630
+ * ```
2631
+ *
2632
+ * @example
2633
+ * ```tsx
2634
+ * // Pagination example
2635
+ * function PaginatedInvoices() {
2636
+ * const [lastInvoiceId, setLastInvoiceId] = useState<string | undefined>();
2637
+ * const { currentWorkspace } = useSaaSWorkspaces();
2638
+ * const { invoices, hasMore, refetch } = useInvoices(
2639
+ * currentWorkspace?._id,
2640
+ * 10,
2641
+ * lastInvoiceId
2642
+ * );
2643
+ *
2644
+ * const loadMore = () => {
2645
+ * if (invoices.length > 0) {
2646
+ * setLastInvoiceId(invoices[invoices.length - 1]._id);
2647
+ * }
2648
+ * };
2649
+ *
2650
+ * return (
2651
+ * <div>
2652
+ * {invoices.map(invoice => <InvoiceCard key={invoice._id} invoice={invoice} />)}
2653
+ * {hasMore && <button onClick={loadMore}>Load More</button>}
2654
+ * </div>
2655
+ * );
2656
+ * }
2657
+ * ```
2658
+ */
2659
+ declare const useInvoices: (workspaceId: string | null | undefined, limit?: number, startingAfter?: string) => {
2660
+ invoices: IInvoice[];
2661
+ hasMore: boolean;
2662
+ loading: boolean;
2663
+ error: string | null;
2664
+ refetch: () => Promise<void>;
2665
+ };
2666
+ /**
2667
+ * Hook to open the Stripe Customer Portal for managing payment methods, invoices, and subscription.
2668
+ *
2669
+ * @example
2670
+ * ```tsx
2671
+ * const { openBillingPortal, loading } = useBillingPortal(workspaceId);
2672
+ * <Button onClick={() => openBillingPortal()} disabled={loading}>
2673
+ * Manage Payment Method
2674
+ * </Button>
2675
+ * ```
2676
+ */
2677
+ declare const useBillingPortal: (workspaceId: string | null | undefined) => {
2678
+ openBillingPortal: (returnUrl?: string) => Promise<{
2679
+ url: string;
2680
+ }>;
2681
+ loading: boolean;
2682
+ error: string | null;
2683
+ };
2684
+ /**
2685
+ * Hook to get a single invoice by ID.
2686
+ * Automatically fetches when workspaceId or invoiceId changes.
2687
+ *
2688
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
2689
+ * @param invoiceId - The invoice ID to fetch. Can be null/undefined to disable fetching.
2690
+ * @returns An object containing:
2691
+ * - `invoice`: Invoice data object (null if not loaded)
2692
+ * - `loading`: Boolean indicating if invoice is being fetched
2693
+ * - `error`: Error message string (null if no error)
2694
+ * - `refetch()`: Function to manually refetch the invoice
2695
+ *
2696
+ * @example
2697
+ * ```tsx
2698
+ * function InvoiceDetails({ invoiceId }) {
2699
+ * const { currentWorkspace } = useSaaSWorkspaces();
2700
+ * const { invoice, loading, error } = useInvoice(currentWorkspace?._id, invoiceId);
2701
+ *
2702
+ * if (loading) return <Loading />;
2703
+ * if (error) return <Error message={error} />;
2704
+ * if (!invoice) return <p>Invoice not found</p>;
2705
+ *
2706
+ * return (
2707
+ * <div>
2708
+ * <h2>Invoice #{invoice.invoiceNumber}</h2>
2709
+ * <p>Amount: ${invoice.amount}</p>
2710
+ * <p>Status: {invoice.status}</p>
2711
+ * </div>
2712
+ * );
2713
+ * }
2714
+ * ```
2715
+ */
2716
+ declare const useInvoice: (workspaceId: string | null | undefined, invoiceId: string | null | undefined) => {
2717
+ invoice: IInvoice | null;
2718
+ loading: boolean;
2719
+ error: string | null;
2720
+ refetch: () => Promise<void>;
2721
+ };
2722
+ /**
2723
+ * Hook to cancel a subscription at the end of the current billing period.
2724
+ * Sets cancelAtPeriodEnd: true - subscription remains active until period ends.
2725
+ *
2726
+ * @param workspaceId - The workspace ID. Can be null/undefined.
2727
+ * @returns An object containing:
2728
+ * - `cancelSubscription()`: Function to cancel subscription at period end
2729
+ * - `loading`: Boolean indicating if cancellation is in progress
2730
+ * - `error`: Error message string (null if no error)
2731
+ *
2732
+ * @example
2733
+ * ```tsx
2734
+ * function CancelSubscriptionButton() {
2735
+ * const { currentWorkspace } = useSaaSWorkspaces();
2736
+ * const { cancelSubscription, loading } = useCancelSubscription(currentWorkspace?._id);
2737
+ * const { refetch } = useSubscription(currentWorkspace?._id);
2738
+ *
2739
+ * const handleCancel = async () => {
2740
+ * try {
2741
+ * await cancelSubscription();
2742
+ * await refetch(); // Refresh subscription data
2743
+ * alert('Subscription will be canceled at the end of the billing period');
2744
+ * } catch (error) {
2745
+ * console.error('Failed to cancel:', error);
2746
+ * }
2747
+ * };
2748
+ *
2749
+ * return (
2750
+ * <button onClick={handleCancel} disabled={loading}>
2751
+ * {loading ? 'Canceling...' : 'Cancel Subscription'}
2752
+ * </button>
2753
+ * );
2754
+ * }
2755
+ * ```
2756
+ */
2757
+ declare const useCancelSubscription: (workspaceId: string | null | undefined) => {
2758
+ cancelSubscription: () => Promise<ISubscriptionResponse>;
2759
+ loading: boolean;
2760
+ error: string | null;
2761
+ };
2762
+ /**
2763
+ * Hook to resume a subscription that was scheduled for cancellation.
2764
+ * Sets cancelAtPeriodEnd: false - subscription will continue after period ends.
2765
+ *
2766
+ * @param workspaceId - The workspace ID. Can be null/undefined.
2767
+ * @returns An object containing:
2768
+ * - `resumeSubscription()`: Function to resume subscription
2769
+ * - `loading`: Boolean indicating if resume is in progress
2770
+ * - `error`: Error message string (null if no error)
2771
+ *
2772
+ * @example
2773
+ * ```tsx
2774
+ * function ResumeSubscriptionButton() {
2775
+ * const { currentWorkspace } = useSaaSWorkspaces();
2776
+ * const { resumeSubscription, loading } = useResumeSubscription(currentWorkspace?._id);
2777
+ * const { refetch } = useSubscription(currentWorkspace?._id);
2778
+ *
2779
+ * const handleResume = async () => {
2780
+ * try {
2781
+ * await resumeSubscription();
2782
+ * await refetch(); // Refresh subscription data
2783
+ * alert('Subscription has been resumed');
2784
+ * } catch (error) {
2785
+ * console.error('Failed to resume:', error);
2786
+ * }
2787
+ * };
2788
+ *
2789
+ * return (
2790
+ * <button onClick={handleResume} disabled={loading}>
2791
+ * {loading ? 'Resuming...' : 'Resume Subscription'}
2792
+ * </button>
2793
+ * );
2794
+ * }
2795
+ * ```
2796
+ */
2797
+ declare const useResumeSubscription: (workspaceId: string | null | undefined) => {
2798
+ resumeSubscription: () => Promise<ISubscriptionResponse>;
2799
+ loading: boolean;
2800
+ error: string | null;
2801
+ };
2802
+ /**
2803
+ * Hook to record quota usage for a workspace.
2804
+ * Returns a function to record usage (mutation pattern).
2805
+ *
2806
+ * @param workspaceId - The workspace ID. Can be null/undefined.
2807
+ * @returns An object containing:
2808
+ * - `recordUsage(request)`: Function to record usage (throws if workspaceId is null)
2809
+ * - `loading`: Boolean indicating if recording is in progress
2810
+ * - `error`: Error message string (null if no error)
2811
+ *
2812
+ * @example
2813
+ * ```tsx
2814
+ * function RecordUsageButton() {
2815
+ * const { currentWorkspace } = useSaaSWorkspaces();
2816
+ * const { recordUsage, loading } = useRecordUsage(currentWorkspace?._id);
2817
+ *
2818
+ * const handleRecord = async () => {
2819
+ * try {
2820
+ * const result = await recordUsage({
2821
+ * quotaSlug: 'api_calls',
2822
+ * quantity: 1,
2823
+ * source: 'web-app',
2824
+ * });
2825
+ * console.log(`Used: ${result.consumed}/${result.included}`);
2826
+ * } catch (error) {
2827
+ * console.error('Failed to record usage:', error);
2828
+ * }
2829
+ * };
2830
+ *
2831
+ * return (
2832
+ * <button onClick={handleRecord} disabled={loading}>
2833
+ * {loading ? 'Recording...' : 'Record Usage'}
2834
+ * </button>
2835
+ * );
2836
+ * }
2837
+ * ```
2838
+ */
2839
+ declare const useRecordUsage: (workspaceId: string | null | undefined) => {
2840
+ recordUsage: (request: IRecordUsageRequest) => Promise<IRecordUsageResponse>;
2841
+ loading: boolean;
2842
+ error: string | null;
2843
+ };
2844
+ /**
2845
+ * Hook to get usage status for a single quota.
2846
+ * Automatically fetches when workspaceId or quotaSlug changes.
2847
+ *
2848
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
2849
+ * @param quotaSlug - The quota slug to check. Can be null/undefined to disable fetching.
2850
+ * @returns An object containing:
2851
+ * - `status`: Quota usage status (null if not loaded)
2852
+ * - `loading`: Boolean indicating if status is being fetched
2853
+ * - `error`: Error message string (null if no error)
2854
+ * - `refetch()`: Function to manually refetch the status
2855
+ *
2856
+ * @example
2857
+ * ```tsx
2858
+ * function QuotaStatusDisplay() {
2859
+ * const { currentWorkspace } = useSaaSWorkspaces();
2860
+ * const { status, loading } = useQuotaUsageStatus(currentWorkspace?._id, 'api_calls');
2861
+ *
2862
+ * if (loading) return <Loading />;
2863
+ * if (!status) return null;
2864
+ *
2865
+ * return (
2866
+ * <div>
2867
+ * <p>Used: {status.consumed} / {status.included}</p>
2868
+ * <p>Available: {status.available}</p>
2869
+ * {status.hasOverage && <p>Overage: {status.overage}</p>}
2870
+ * </div>
2871
+ * );
2872
+ * }
2873
+ * ```
2874
+ */
2875
+ declare const useQuotaUsageStatus: (workspaceId: string | null | undefined, quotaSlug: string | null | undefined) => {
2876
+ status: IQuotaUsageStatusResponse | null;
2877
+ loading: boolean;
2878
+ error: string | null;
2879
+ refetch: () => Promise<void>;
2880
+ };
2881
+ /**
2882
+ * Hook to get usage status for all quotas in the workspace's current plan.
2883
+ * Automatically fetches when workspaceId changes.
2884
+ *
2885
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
2886
+ * @returns An object containing:
2887
+ * - `quotas`: Record of quota usage statuses keyed by slug (null if not loaded)
2888
+ * - `loading`: Boolean indicating if statuses are being fetched
2889
+ * - `error`: Error message string (null if no error)
2890
+ * - `refetch()`: Function to manually refetch all statuses
2891
+ *
2892
+ * @example
2893
+ * ```tsx
2894
+ * function AllQuotasDisplay() {
2895
+ * const { currentWorkspace } = useSaaSWorkspaces();
2896
+ * const { quotas, loading } = useAllQuotaUsage(currentWorkspace?._id);
2897
+ *
2898
+ * if (loading) return <Loading />;
2899
+ * if (!quotas) return null;
2900
+ *
2901
+ * return (
2902
+ * <div>
2903
+ * {Object.entries(quotas).map(([slug, usage]) => (
2904
+ * <div key={slug}>
2905
+ * <p>{slug}: {usage.consumed}/{usage.included}</p>
2906
+ * {usage.hasOverage && <p>Overage: {usage.overage}</p>}
2907
+ * </div>
2908
+ * ))}
2909
+ * </div>
2910
+ * );
2911
+ * }
2912
+ * ```
2913
+ */
2914
+ declare const useAllQuotaUsage: (workspaceId: string | null | undefined) => {
2915
+ quotas: Record<string, IQuotaUsageStatus> | null;
2916
+ loading: boolean;
2917
+ error: string | null;
2918
+ refetch: () => Promise<void>;
2919
+ };
2920
+ /**
2921
+ * Hook to get paginated usage logs for a workspace.
2922
+ * Automatically fetches when workspaceId or filter params change.
2923
+ *
2924
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
2925
+ * @param quotaSlug - Optional quota slug to filter logs by.
2926
+ * @param options - Optional filters: from, to, source, page, limit
2927
+ * @returns An object containing:
2928
+ * - `logs`: Array of usage log entries
2929
+ * - `totalDocs`: Total number of log entries matching the query
2930
+ * - `totalPages`: Total number of pages
2931
+ * - `page`: Current page number
2932
+ * - `hasNextPage`: Whether there are more pages after the current one
2933
+ * - `hasPrevPage`: Whether there are pages before the current one
2934
+ * - `loading`: Boolean indicating if logs are being fetched
2935
+ * - `error`: Error message string (null if no error)
2936
+ * - `refetch()`: Function to manually refetch logs
2937
+ *
2938
+ * @example
2939
+ * ```tsx
2940
+ * function UsageLogsTable() {
2941
+ * const { currentWorkspace } = useSaaSWorkspaces();
2942
+ * const { logs, totalPages, page, hasNextPage, loading } = useUsageLogs(
2943
+ * currentWorkspace?._id,
2944
+ * 'api_calls',
2945
+ * { limit: 20 }
2946
+ * );
2947
+ *
2948
+ * if (loading) return <Loading />;
2949
+ *
2950
+ * return (
2951
+ * <div>
2952
+ * {logs.map(log => (
2953
+ * <div key={log._id}>
2954
+ * {log.quotaSlug}: {log.quantity} ({log.createdAt})
2955
+ * </div>
2956
+ * ))}
2957
+ * <p>Page {page} of {totalPages}</p>
2958
+ * </div>
2959
+ * );
2960
+ * }
2961
+ * ```
2962
+ */
2963
+ declare const useUsageLogs: (workspaceId: string | null | undefined, quotaSlug?: string, options?: {
2964
+ from?: string;
2965
+ to?: string;
2966
+ source?: string;
2967
+ page?: number;
2968
+ limit?: number;
2969
+ }) => {
2970
+ logs: IUsageLogEntry[];
2971
+ totalDocs: number;
2972
+ totalPages: number;
2973
+ page: number;
2974
+ hasNextPage: boolean;
2975
+ hasPrevPage: boolean;
2976
+ loading: boolean;
2977
+ error: string | null;
2978
+ refetch: () => Promise<void>;
2979
+ };
2980
+
2981
+ interface TrialStatus {
2982
+ /** Whether the current subscription is in trial. */
2983
+ isTrialing: boolean;
2984
+ /** Number of days remaining in the trial. 0 if not trialing or expired. */
2985
+ daysRemaining: number;
2986
+ /** Trial end date as a Date object. null if not trialing. */
2987
+ trialEndsAt: Date | null;
2988
+ /** Trial start date as a Date object. null if not trialing. */
2989
+ trialStartedAt: Date | null;
2990
+ /** Whether the trial is ending soon (<= 3 days remaining). */
2991
+ isTrialEnding: boolean;
2992
+ }
2993
+ /**
2994
+ * Hook that computes trial status from the current subscription context.
2995
+ * Must be used within SubscriptionContextProvider.
2996
+ *
2997
+ * @returns TrialStatus — computed trial information
2998
+ *
2999
+ * @example
3000
+ * ```tsx
3001
+ * const { isTrialing, daysRemaining, isTrialEnding } = useTrialStatus();
3002
+ *
3003
+ * if (isTrialEnding) {
3004
+ * return <UpgradeBanner daysLeft={daysRemaining} />;
3005
+ * }
3006
+ * ```
3007
+ */
3008
+ declare function useTrialStatus(): TrialStatus;
3009
+
3010
+ interface SeatStatus {
3011
+ /** Whether the current plan uses seat-based pricing. */
3012
+ hasSeatPricing: boolean;
3013
+ /** Total workspace members. */
3014
+ memberCount: number;
3015
+ /** Seats included in the base price (free). */
3016
+ includedSeats: number;
3017
+ /** Maximum users allowed (resolved from seat pricing, plan limits, or settings). 0 = unlimited. */
3018
+ maxUsers: number;
3019
+ /**
3020
+ * Maximum seats allowed from seat pricing config. 0 = unlimited.
3021
+ * @deprecated Use `maxUsers` for the unified limit.
3022
+ */
3023
+ maxSeats: number;
3024
+ /** Where the max user limit comes from. */
3025
+ limitSource: MaxUsersConfig['source'];
3026
+ /** Seats beyond included that are being billed. */
3027
+ billableSeats: number;
3028
+ /** Remaining seats before hitting max. Infinity if unlimited. */
3029
+ availableSeats: number;
3030
+ /** Whether workspace is at max seat/user capacity. */
3031
+ isAtMax: boolean;
3032
+ /** Whether workspace is near max (>= 80% used). */
3033
+ isNearMax: boolean;
3034
+ /** Per-seat price in cents for the current billing interval. Null if not applicable. */
3035
+ perSeatPriceCents: number | null;
3036
+ /** Billing currency. */
3037
+ currency: string;
3038
+ /** Whether a new member can be invited. */
3039
+ canInvite: boolean;
3040
+ /** Reason the invite is blocked, or null if allowed. */
3041
+ inviteBlockReason: InviteBlockReason;
3042
+ /** Human-readable message for why invite is blocked. */
3043
+ inviteBlockMessage: string | null;
3044
+ }
3045
+ /**
3046
+ * Hook that computes seat status from subscription context and workspace data.
3047
+ * Resolves max user limits from seat pricing, plan limits, and settings in priority order.
3048
+ * Must be used within SubscriptionContextProvider.
3049
+ *
3050
+ * @param workspace - The current workspace (needs users array, limits, billingCurrency)
3051
+ * @param options - Optional overrides (e.g. settingsMaxUsers fallback)
3052
+ * @returns SeatStatus — computed seat and invite information
3053
+ *
3054
+ * @example
3055
+ * ```tsx
3056
+ * const { isAtMax, canInvite, inviteBlockMessage, availableSeats } = useSeatStatus(workspace);
3057
+ *
3058
+ * if (!canInvite) {
3059
+ * return <div>{inviteBlockMessage}</div>;
3060
+ * }
3061
+ * ```
3062
+ */
3063
+ declare function useSeatStatus(workspace: {
3064
+ users?: any[];
3065
+ billingCurrency?: string | null;
3066
+ } | null, options?: {
3067
+ settingsMaxUsers?: number | null;
3068
+ }): SeatStatus;
3069
+
3070
+ declare function WorkspaceSwitcher(props: {
3071
+ trigger: (isLoading: boolean, currentWorkspace: IWorkspace | null) => ReactNode;
3072
+ }): react_jsx_runtime.JSX.Element;
3073
+
3074
+ type Language = 'en' | 'es' | 'fr' | 'de' | 'zh' | 'ja' | 'ko';
3075
+ interface FormText {
3076
+ nameLabel: string;
3077
+ emailLabel: string;
3078
+ submitText: string;
3079
+ submittingText: string;
3080
+ errorMessage: string;
3081
+ }
3082
+ interface BetaFormProps {
3083
+ onSuccess?: () => void;
3084
+ onError?: (error: string) => void;
3085
+ className?: string;
3086
+ fieldClassName?: string;
3087
+ language?: Language;
3088
+ customTexts?: Partial<FormText>;
3089
+ autoFocus?: boolean;
3090
+ showSuccessMessage?: boolean;
3091
+ successMessageDuration?: number;
3092
+ hideLogo?: boolean;
3093
+ hideTitles?: boolean;
3094
+ }
3095
+ declare const BetaForm: react__default.FC<BetaFormProps>;
3096
+
3097
+ interface PricingPageDetails {
3098
+ /** Whether plan data is being fetched */
3099
+ loading: boolean;
3100
+ /** Error message if fetch failed */
3101
+ error: string | null;
3102
+ /** Subscription items (features, limits, quotas) */
3103
+ items: IPublicPlanItem[];
3104
+ /** Plan versions with pricing, features, limits, quotas */
3105
+ plans: IPublicPlanVersion[];
3106
+ /** Optional note from API (e.g. "Pricing is in cents. Please convert to dollars for display.") */
3107
+ notes?: string;
3108
+ /** Refetch plan data */
3109
+ refetch: () => Promise<void>;
3110
+ }
3111
+ interface PricingPageProps {
3112
+ /** Plan group slug (e.g. 'main-pricing', 'enterprise') */
3113
+ slug: string;
3114
+ /** Render prop receiving plan details - construct layout from items and plans */
3115
+ children: (details: PricingPageDetails) => ReactNode;
3116
+ /** Custom loading UI. Defaults to skeleton. */
3117
+ loadingFallback?: ReactNode;
3118
+ /** Custom error UI. Receives error message. */
3119
+ errorFallback?: (error: string) => ReactNode;
3120
+ }
3121
+ /**
3122
+ * Fetches and provides plan/pricing details for public pricing pages (no login required).
3123
+ * Returns items (features, limits, quotas) and plans (with pricing) - user constructs layout.
3124
+ *
3125
+ * @example
3126
+ * ```tsx
3127
+ * <PricingPage slug="main-pricing">
3128
+ * {({ loading, error, items, plans, refetch }) => {
3129
+ * if (loading) return <Loading />;
3130
+ * if (error) return <Error message={error} />;
3131
+ *
3132
+ * return (
3133
+ * <div>
3134
+ * {plans.map(plan => (
3135
+ * <PlanCard key={plan._id} plan={plan} items={items} />
3136
+ * ))}
3137
+ * </div>
3138
+ * );
3139
+ * }}
3140
+ * </PricingPage>
3141
+ * ```
3142
+ */
3143
+ declare function PricingPage({ slug, children, loadingFallback, errorFallback }: PricingPageProps): react_jsx_runtime.JSX.Element;
3144
+
3145
+ interface PushNotificationState {
3146
+ /** Browser's Notification.permission: 'default' | 'granted' | 'denied' */
3147
+ permission: NotificationPermission;
3148
+ /** Whether this device is subscribed to push notifications */
3149
+ isSubscribed: boolean;
3150
+ /** Whether the browser supports push notifications */
3151
+ isSupported: boolean;
3152
+ /** Loading state for subscribe/unsubscribe operations */
3153
+ loading: boolean;
3154
+ /** Error message from the last operation */
3155
+ error: string | null;
3156
+ }
3157
+ interface PushNotificationContextValue extends PushNotificationState {
3158
+ /** Request notification permission from the browser. Returns true if granted. */
3159
+ requestPermission: () => Promise<boolean>;
3160
+ /** Subscribe this device to push notifications (requests permission if needed). */
3161
+ subscribe: () => Promise<void>;
3162
+ /** Unsubscribe this device from push notifications. */
3163
+ unsubscribe: () => Promise<void>;
3164
+ }
3165
+ interface PushNotificationProviderProps {
3166
+ children: react__default.ReactNode;
3167
+ /** Path to the service worker file (default: '/push-sw.js') */
3168
+ serviceWorkerPath?: string;
3169
+ /** Automatically subscribe after permission is granted on login (default: false) */
3170
+ autoSubscribe?: boolean;
3171
+ }
3172
+ declare const PushNotificationProvider: react__default.FC<PushNotificationProviderProps>;
3173
+ /**
3174
+ * Hook to access push notification state and actions.
3175
+ * Must be used within PushNotificationProvider (included in SaaSOSProvider when push config is provided).
3176
+ */
3177
+ declare function usePushNotifications(): PushNotificationContextValue;
3178
+
3179
+ export { ApiVersion, AuthApi, AuthStatus, BaseApi, BetaForm, CURRENCY_DISPLAY, CURRENCY_FLAG, EventEmitter, PLAN_CURRENCY_CODES, PLAN_CURRENCY_OPTIONS, PUSH_SERVICE_WORKER_SCRIPT, PricingPage, PushApi, PushNotificationProvider, QuotaUsageContextProvider, SaaSOSProvider, SettingsApi, SubscriptionContextProvider, UserApi, WhenAuthenticated, WhenNoSubscription, WhenNotTrialing, WhenQuotaAvailable, WhenQuotaExhausted, WhenQuotaOverage, WhenQuotaThreshold, WhenRoles, WhenSubscription, WhenSubscriptionToPlans, WhenTrialEnding, WhenTrialing, WhenUnauthenticated, WhenUserFeatureDisabled, WhenUserFeatureEnabled, WhenWorkspaceFeatureDisabled, WhenWorkspaceFeatureEnabled, WhenWorkspaceRoles, WorkspaceApi, WorkspaceSwitcher, formSchema as betaFormSchema, calculateBillableSeats, calculateSeatOverageCents, calculateTotalSubscriptionCents, countries, uniqueCurrencies as currencies, eventEmitter, formatCents, formatOverageRate, formatOverageRateWithLabel, formatQuotaIncludedOverage, formatQuotaWithPrice, getAvailableCurrenciesFromPlans, getBasePriceCents, getBillingIntervalAndCurrencyFromPriceId, getCurrencyFlag, getCurrencySymbol, getDisplayCurrency, getPerSeatPriceCents, getPricingVariant, getQuotaDisplayValue, getQuotaDisplayWithVariant, getQuotaOverageCents, getQuotaUnitLabelFromName, getSeatPricing, getStripePriceIdForInterval, invalidateQuotaUsage, invalidateSubscription, languages, resolveMaxUsers, timezones, useAllQuotaUsage, useBillingPortal, useCancelSubscription, useCreateCheckoutSession, useInvoice, useInvoices, usePlanGroup, usePlanGroupVersions, usePublicPlanGroupVersion, usePublicPlans, usePushNotifications, useQuotaUsageContext, useQuotaUsageStatus, useRecordUsage, useResumeSubscription, useSaaSAuth, useSaaSOs, useSaaSSettings, useSaaSWorkspaces, useSeatStatus, useSubscription, useSubscriptionContext, useSubscriptionManagement, useTrialStatus, useUpdateSubscription, useUsageLogs, useUserAttributes, useUserFeatures, validateInvite };
3180
+ export type { BetaFormData, BetaFormResponse, formValuesType as BetaFormValues, BillingInterval, CheckoutResult, EventData, EventType, FormatQuotaWithPriceOptions, IAllQuotaUsageResponse, IBaseApiConfig, IBasePricing, IBetaConfig, ICheckoutSessionRequest, ICheckoutSessionResponse, IEventCallbacks, IInvoice, IInvoiceListResponse, IInvoiceResponse, IOsConfig, IOsState, IPlan, IPlanGroup, IPlanGroupInfo, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionSummary, IPlanVersionWithPlan, IPricingVariant, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanVersion, IPublicPlansResponse, IQuotaByInterval, IQuotaIntervalValue, IQuotaOveragePriceIdsByInterval, IQuotaOveragesByInterval, IQuotaUsageStatus, IQuotaUsageStatusResponse, IRecordUsageRequest, IRecordUsageResponse, IStripePricesByInterval, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, IUsageLogEntry, IUsageLogsQuery, IUsageLogsResponse, InviteBlockReason, InviteValidation, InvoiceStatus, MaxUsersConfig, OnWorkspaceChangeParams, PlanVersionWithPricingVariants, PricingPageDetails, PricingPageProps, QuotaDisplayValue, QuotaDisplayWithOverage, QuotaUsageContextValue, SaaSOSProviderProps, SeatStatus, SubscriptionContextValue, TrialStatus, UserCreatedEventData, UserUpdatedEventData, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };