@buildbase/sdk 0.0.15 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +208 -98
  2. package/dist/index.d.ts +395 -168
  3. package/dist/index.esm.js +5 -5
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +5 -5
  6. package/dist/index.js.map +1 -1
  7. package/dist/saas-os.css +1 -1
  8. package/dist/types/api/index.d.ts +6 -0
  9. package/dist/types/api/quota-utils.d.ts +24 -0
  10. package/dist/types/api/types.d.ts +40 -15
  11. package/dist/types/components/beta/api.d.ts +1 -2
  12. package/dist/types/components/pricing/PricingPage.d.ts +1 -1
  13. package/dist/types/components/subscription/index.d.ts +108 -0
  14. package/dist/types/contexts/SubscriptionContext/SubscriptionContext.d.ts +22 -0
  15. package/dist/types/contexts/SubscriptionContext/index.d.ts +2 -0
  16. package/dist/types/contexts/SubscriptionContext/subscriptionInvalidation.d.ts +19 -0
  17. package/dist/types/contexts/SubscriptionContext/types.d.ts +12 -0
  18. package/dist/types/contexts/index.d.ts +2 -0
  19. package/dist/types/contexts/shared/types.d.ts +21 -0
  20. package/dist/types/contexts/shared/useAppDispatch.d.ts +2 -12
  21. package/dist/types/contexts/shared/useAppSelector.d.ts +2 -12
  22. package/dist/types/contexts/shared/utils/reducerHelpers.d.ts +2 -2
  23. package/dist/types/index.d.ts +9 -2
  24. package/dist/types/lib/api-base.d.ts +49 -0
  25. package/dist/types/providers/ContextConfigProvider.d.ts +1 -1
  26. package/dist/types/providers/auth/api.d.ts +12 -0
  27. package/dist/types/providers/auth/hooks.d.ts +2 -0
  28. package/dist/types/providers/os/api.d.ts +11 -0
  29. package/dist/types/providers/os/hooks.d.ts +6 -0
  30. package/dist/types/providers/os/types.d.ts +2 -0
  31. package/dist/types/providers/user/api.d.ts +16 -0
  32. package/dist/types/providers/user/hooks.d.ts +1 -0
  33. package/dist/types/providers/workspace/api.d.ts +16 -5
  34. package/dist/types/providers/workspace/hooks.d.ts +10 -0
  35. package/dist/types/providers/workspace/subscription-hooks.d.ts +81 -1
  36. package/dist/types/providers/workspace/ui/SubscriptionDialog.d.ts +3 -2
  37. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -21,10 +21,14 @@ interface IUser extends IDocument {
21
21
  currency: string;
22
22
  attributes?: Record<string, string | number | boolean>;
23
23
  }
24
+ type BillingInterval = 'monthly' | 'yearly' | 'quarterly';
24
25
  interface ISubscription {
25
26
  _id: string;
26
27
  subscriptionStatus: 'active' | 'trialing' | 'canceled' | 'past_due';
28
+ stripePriceId?: string;
29
+ stripeCurrentPeriodEnd?: string;
27
30
  cancelAtPeriodEnd: boolean;
31
+ billingInterval?: BillingInterval;
28
32
  createdAt: string;
29
33
  updatedAt: string;
30
34
  plan?: {
@@ -47,6 +51,20 @@ interface IQuotaValue {
47
51
  overage?: number;
48
52
  stripePriceId?: string;
49
53
  }
54
+ /** Per-interval quota value (new plan-group/versions schema) */
55
+ interface IQuotaIntervalValue {
56
+ included: number;
57
+ overage: number;
58
+ priceId: string;
59
+ /** Optional unit size for overage pricing (e.g. 1000 = price per 1000 units). */
60
+ unitSize?: number;
61
+ }
62
+ /** Quota defined per billing interval (new plan-group/versions schema) */
63
+ interface IQuotaByInterval {
64
+ monthly?: IQuotaIntervalValue;
65
+ yearly?: IQuotaIntervalValue;
66
+ quarterly?: IQuotaIntervalValue;
67
+ }
50
68
  interface IBasePricing {
51
69
  monthly: number;
52
70
  yearly: number;
@@ -59,7 +77,8 @@ interface IPlanVersion {
59
77
  status: 'draft' | 'published';
60
78
  features?: Record<string, boolean>;
61
79
  limits?: Record<string, number>;
62
- quotas?: Record<string, number | IQuotaValue>;
80
+ /** Legacy: number | IQuotaValue. New schema: IQuotaByInterval (per-interval included/overage/priceId) */
81
+ quotas?: Record<string, number | IQuotaValue | IQuotaByInterval>;
63
82
  basePricing?: IBasePricing;
64
83
  stripePrices?: {
65
84
  monthlyPriceId?: string;
@@ -76,13 +95,18 @@ interface IPlanVersion {
76
95
  createdAt?: string;
77
96
  updatedAt?: string;
78
97
  id?: string;
98
+ stripeProductId?: string;
99
+ }
100
+ /** Plan version summary (e.g. plan.latestVersion from subscription API) with subscriptionItems as IDs. */
101
+ interface IPlanVersionSummary extends Omit<IPlanVersion, 'subscriptionItems'> {
102
+ subscriptionItems?: string[];
79
103
  }
80
104
  interface IPlan {
81
105
  _id: string;
82
106
  name: string;
83
107
  slug: string;
84
108
  description?: string;
85
- latestVersion?: IPlanVersion;
109
+ latestVersion?: IPlanVersionSummary;
86
110
  archived?: boolean;
87
111
  deleted?: boolean;
88
112
  createdAt?: string;
@@ -157,25 +181,26 @@ interface IPlanGroupVersionWithPlans {
157
181
  removedPlans: IPlanVersionWithPlan[];
158
182
  };
159
183
  }
184
+ interface IPlanGroupInfo {
185
+ _id: string;
186
+ name: string;
187
+ slug: string;
188
+ description?: string;
189
+ }
190
+ /** Response from GET workspaces/:id/subscription/plan-group (and by version). */
160
191
  interface IPlanGroupResponse {
161
- group: {
162
- _id: string;
163
- name: string;
164
- slug: string;
165
- };
166
- currentVersion: IPlanGroupVersionWithPlans;
167
- availableVersions: IPlanGroupVersionWithPlans[];
192
+ /** Plan group with latestVersion, archived, deleted, timestamps. */
193
+ group: IPlanGroup;
194
+ /** Current group version with populated planVersionIds (or IDs). */
195
+ groupVersion: IPlanGroupVersion;
196
+ /** Full plan versions for display (subscriptionItems, basePricing, quotas, etc.). */
197
+ plans: IPlanVersionWithPlan[];
168
198
  }
169
199
  interface IPlanGroupVersionsResponse {
170
- group: {
171
- _id: string;
172
- name: string;
173
- slug: string;
174
- };
200
+ group: IPlanGroupInfo;
175
201
  currentVersion: IPlanGroupVersionWithPlans;
176
202
  availableVersions: IPlanGroupVersionWithPlans[];
177
203
  }
178
- type BillingInterval = 'monthly' | 'yearly' | 'quarterly';
179
204
  interface ICheckoutSessionRequest {
180
205
  planVersionId: string;
181
206
  billingInterval?: BillingInterval;
@@ -510,7 +535,7 @@ interface PricingPageProps {
510
535
  * </PricingPage>
511
536
  * ```
512
537
  */
513
- declare function PricingPage({ slug, children, loadingFallback, errorFallback, }: PricingPageProps): react_jsx_runtime.JSX.Element;
538
+ declare function PricingPage({ slug, children, loadingFallback, errorFallback }: PricingPageProps): react_jsx_runtime.JSX.Element;
514
539
 
515
540
  interface IProps$2 {
516
541
  children: React.ReactNode;
@@ -778,69 +803,149 @@ declare const WhenUserFeatureEnabled: (props: IProps) => react.ReactNode;
778
803
  */
779
804
  declare const WhenUserFeatureDisabled: (props: IProps) => react.ReactNode;
780
805
 
781
- type WorkspaceSettingsSection = 'profile' | 'general' | 'users' | 'subscription' | 'features' | 'danger';
782
-
806
+ interface IWhenSubscriptionProps {
807
+ /** Content to render when the condition is met (workspace has an active subscription). */
808
+ children: React.ReactNode;
809
+ /** Optional component/element to show while subscription is loading (e.g. <Skeleton />). */
810
+ loadingComponent?: React.ReactNode;
811
+ /** Optional component/element to show when condition is not met (e.g. <UpgradePrompt />). */
812
+ fallbackComponent?: React.ReactNode;
813
+ }
783
814
  /**
784
- * Main authentication hook for the SDK.
785
- * Provides authentication state, user session, and auth actions.
815
+ * Renders children only when the current workspace has an active subscription (any plan).
816
+ * Optionally pass loadingComponent (while loading) or fallbackComponent (when not subscribed).
817
+ * Must be used within SubscriptionContextProvider.
786
818
  *
787
- * @returns An object containing:
788
- * - `user`: Current authenticated user object (null if not authenticated)
789
- * - `session`: Full session object with user and token (null if not authenticated)
790
- * - `status`: Current authentication status (loading, redirecting, authenticating, authenticated, unauthenticated)
791
- * - `isLoading`: Boolean indicating if auth state is being determined
792
- * - `isAuthenticated`: Boolean indicating if user is authenticated
793
- * - `isRedirecting`: Boolean indicating if redirecting to OAuth provider
794
- * - `signIn()`: Function to initiate OAuth sign-in flow
795
- * - `signOut()`: Function to sign out the current user
796
- * - `openWorkspaceSettings(section?)`: Function to open workspace settings dialog
819
+ * @param props - Component props
820
+ * @param props.children - Content to render when subscribed
821
+ * @param props.loadingComponent - Optional component/element to show while loading
822
+ * @param props.fallbackComponent - Optional component/element to show when not subscribed
823
+ * @returns ReactNode - children when subscribed, loadingComponent when loading, fallbackComponent when not subscribed, or null
797
824
  *
798
825
  * @example
799
826
  * ```tsx
800
- * function MyComponent() {
801
- * const { user, isAuthenticated, signIn, signOut } = useSaaSAuth();
827
+ * <WhenSubscription>
828
+ * <BillingSettings />
829
+ * </WhenSubscription>
830
+ * ```
802
831
  *
803
- * if (!isAuthenticated) {
804
- * return <button onClick={signIn}>Sign In</button>;
805
- * }
832
+ * @example
833
+ * ```tsx
834
+ * <WhenSubscription
835
+ * loadingComponent={<Skeleton />}
836
+ * fallbackComponent={<UpgradePrompt />}
837
+ * >
838
+ * <BillingSettings />
839
+ * </WhenSubscription>
840
+ * ```
841
+ */
842
+ declare const WhenSubscription: (props: IWhenSubscriptionProps) => react.ReactNode;
843
+ /**
844
+ * Renders children only when the current workspace has no subscription (or no current workspace).
845
+ * Optionally pass loadingComponent (while loading) or fallbackComponent (when already subscribed).
846
+ * Must be used within SubscriptionContextProvider.
806
847
  *
807
- * return (
808
- * <div>
809
- * <p>Welcome, {user?.name}</p>
810
- * <button onClick={signOut}>Sign Out</button>
811
- * </div>
812
- * );
813
- * }
848
+ * @param props - Component props
849
+ * @param props.children - Content to render when not subscribed
850
+ * @param props.loadingComponent - Optional component/element to show while loading
851
+ * @param props.fallbackComponent - Optional component/element to show when already subscribed
852
+ * @returns ReactNode - children when not subscribed, loadingComponent when loading, fallbackComponent when subscribed, or null
853
+ *
854
+ * @example
855
+ * ```tsx
856
+ * <WhenNoSubscription>
857
+ * <UpgradePrompt />
858
+ * </WhenNoSubscription>
814
859
  * ```
815
860
  *
816
861
  * @example
817
862
  * ```tsx
818
- * // Handle loading state
819
- * function App() {
820
- * const { status, isLoading } = useSaaSAuth();
863
+ * <WhenNoSubscription
864
+ * loadingComponent={<Spinner />}
865
+ * fallbackComponent={null}
866
+ * >
867
+ * <UpgradePrompt />
868
+ * </WhenNoSubscription>
869
+ * ```
870
+ */
871
+ declare const WhenNoSubscription: (props: IWhenSubscriptionProps) => react.ReactNode;
872
+ interface IWhenSubscriptionToPlansProps {
873
+ /** Plan slugs to match (e.g. ['pro', 'enterprise']). Matching is case-insensitive. */
874
+ plans: string[];
875
+ /** Content to render when the workspace is on one of the given plans. */
876
+ children: React.ReactNode;
877
+ /** Optional component/element to show while subscription is loading (e.g. <Skeleton />). */
878
+ loadingComponent?: React.ReactNode;
879
+ /** Optional component/element to show when not on a matching plan (e.g. <UpgradeToPro />). */
880
+ fallbackComponent?: React.ReactNode;
881
+ }
882
+ /**
883
+ * Renders children only when the current workspace is subscribed to one of the given plans.
884
+ * Matches by plan slug only. Optionally pass loadingComponent (while loading) or fallbackComponent (when not on a matching plan).
885
+ * Must be used within SubscriptionContextProvider.
821
886
  *
822
- * if (isLoading) {
823
- * return <LoadingSpinner />;
824
- * }
887
+ * @param props - Component props
888
+ * @param props.plans - Plan slugs to match (e.g. ['pro', 'enterprise'])
889
+ * @param props.children - Content to render when on a matching plan
890
+ * @param props.loadingComponent - Optional component/element to show while loading
891
+ * @param props.fallbackComponent - Optional component/element to show when not on a matching plan
892
+ * @returns ReactNode - children when on a matching plan, loadingComponent when loading, fallbackComponent when not matching, or null
825
893
  *
826
- * return <MainContent />;
827
- * }
894
+ * @example
895
+ * ```tsx
896
+ * <WhenSubscriptionToPlans plans={['pro', 'enterprise']}>
897
+ * <AdvancedAnalytics />
898
+ * </WhenSubscriptionToPlans>
828
899
  * ```
829
900
  *
830
901
  * @example
831
902
  * ```tsx
832
- * // Open workspace settings
833
- * function SettingsButton() {
834
- * const { openWorkspaceSettings } = useSaaSAuth();
835
- *
836
- * return (
837
- * <button onClick={() => openWorkspaceSettings('general')}>
838
- * Open Settings
839
- * </button>
840
- * );
841
- * }
903
+ * <WhenSubscriptionToPlans
904
+ * plans={['pro', 'enterprise']}
905
+ * loadingComponent={<Skeleton />}
906
+ * fallbackComponent={<UpgradeToPro />}
907
+ * >
908
+ * <AdvancedAnalytics />
909
+ * </WhenSubscriptionToPlans>
842
910
  * ```
843
911
  */
912
+ declare const WhenSubscriptionToPlans: (props: IWhenSubscriptionToPlansProps) => react.ReactNode;
913
+
914
+ /**
915
+ * Value provided by SubscriptionContext and returned by useSubscriptionContext.
916
+ */
917
+ interface SubscriptionContextValue {
918
+ /** Current subscription response for the current workspace, or null if none or not loaded. */
919
+ response: ISubscriptionResponse | null;
920
+ /** True while subscription is being fetched. */
921
+ loading: boolean;
922
+ /** Refetch subscription for the current workspace. Call after plan change (e.g. upgrade) or when subscription was updated elsewhere. */
923
+ refetch: () => Promise<void>;
924
+ }
925
+
926
+ /**
927
+ * Provides subscription data for the current workspace to subscription gate components.
928
+ * Fetches when workspace changes; refetches when subscription is invalidated (e.g. after plan change).
929
+ * Must wrap (or be ancestor of) any component that uses WhenSubscription, WhenNoSubscription,
930
+ * WhenSubscriptionToPlans, or useSubscriptionContext. Included in SaaSOSProvider by default.
931
+ *
932
+ * @param props - Component props
933
+ * @param props.children - React tree that may use subscription gates or useSubscriptionContext
934
+ * @returns Provider element that supplies subscription context to descendants
935
+ */
936
+ declare const SubscriptionContextProvider: react__default.FC<{
937
+ children: ReactNode;
938
+ }>;
939
+ /**
940
+ * Returns subscription data for the current workspace. Must be used within SubscriptionContextProvider.
941
+ *
942
+ * @returns SubscriptionContextValue - { response, loading, refetch }
943
+ * @throws Error if used outside SubscriptionContextProvider
944
+ */
945
+ declare function useSubscriptionContext(): SubscriptionContextValue;
946
+
947
+ type WorkspaceSettingsSection = 'profile' | 'general' | 'users' | 'subscription' | 'features' | 'danger';
948
+
844
949
  declare function useSaaSAuth(): {
845
950
  signIn: () => Promise<void>;
846
951
  signOut: () => Promise<void>;
@@ -853,6 +958,11 @@ declare function useSaaSAuth(): {
853
958
  status: AuthStatus;
854
959
  };
855
960
 
961
+ /**
962
+ * Hook to access OS (organization) state (serverUrl, version, orgId, auth, settings).
963
+ * Prefer useSaaSSettings() when you only need settings.
964
+ */
965
+ declare function useSaaSOs(): IOsState;
856
966
  /**
857
967
  * Hook to access organization settings from the OS context.
858
968
  * Automatically fetches settings when OS config is ready.
@@ -908,6 +1018,68 @@ interface UserContextValue {
908
1018
  refreshFeatures: () => Promise<void>;
909
1019
  }
910
1020
 
1021
+ /**
1022
+ * Base API client for SDK endpoints.
1023
+ * All domain API classes (WorkspaceApi, UserApi, etc.) extend this to share
1024
+ * URL building, auth headers, and request/response handling.
1025
+ */
1026
+
1027
+ interface IBaseApiConfig {
1028
+ serverUrl: string;
1029
+ version: ApiVersion;
1030
+ orgId?: string;
1031
+ /** When true, ensureReady() also requires orgId. Used by WorkspaceApi and SettingsApi. */
1032
+ requireOrgId?: boolean;
1033
+ /** API path segment after version (default 'public'). e.g. 'public' => .../v1/public, 'beta' => .../v1/beta */
1034
+ basePath?: string;
1035
+ }
1036
+ /**
1037
+ * Base class for SDK API clients.
1038
+ * Provides:
1039
+ * - baseUrl: `${serverUrl}/api/${version}/public`
1040
+ * - getAuthHeaders()
1041
+ * - fetchJson<T>(path, init, errorMessage): GET/POST/etc. with handleApiResponse
1042
+ * - fetchResponse(path, init): raw Response for custom parsing (e.g. non-JSON or custom error handling)
1043
+ */
1044
+ declare abstract class BaseApi {
1045
+ protected readonly serverUrl: string;
1046
+ protected readonly version: ApiVersion;
1047
+ protected readonly orgId: string | undefined;
1048
+ private readonly requireOrgId;
1049
+ private readonly basePath;
1050
+ constructor(config: IBaseApiConfig);
1051
+ /** Throws if config is not ready for API calls. Called automatically by fetchJson/fetchResponse. */
1052
+ protected ensureReady(): void;
1053
+ /** Base URL: ${serverUrl}/api/${version}/${basePath} */
1054
+ protected get baseUrl(): string;
1055
+ /** Auth headers (x-session-id). Subclasses can override to add more. */
1056
+ protected getAuthHeaders(): Record<string, string>;
1057
+ /** Build full URL from path (path can be "workspaces" or "/workspaces"). */
1058
+ protected url(path: string): string;
1059
+ /**
1060
+ * Execute request and parse JSON with handleApiResponse (throws on !response.ok).
1061
+ * Use for standard JSON APIs.
1062
+ */
1063
+ protected fetchJson<T>(path: string, init?: RequestInit, errorMessage?: string): Promise<T>;
1064
+ /**
1065
+ * Execute request and return raw Response (for custom parsing or error handling).
1066
+ * Caller is responsible for checking response.ok and parsing body.
1067
+ */
1068
+ protected fetchResponse(path: string, init?: RequestInit): Promise<Response>;
1069
+ }
1070
+
1071
+ /**
1072
+ * Centralized API client for user attributes and features.
1073
+ * Extends BaseApi for shared URL/auth/request handling.
1074
+ */
1075
+ declare class UserApi extends BaseApi {
1076
+ constructor(config: Pick<IOsConfig, 'serverUrl' | 'version'>);
1077
+ getAttributes(signal?: AbortSignal): Promise<Record<string, string | number | boolean>>;
1078
+ updateAttributes(updates: Record<string, string | number | boolean>): Promise<IUser>;
1079
+ updateAttribute(attributeKey: string, value: string | number | boolean): Promise<IUser>;
1080
+ getFeatures(signal?: AbortSignal): Promise<Record<string, boolean>>;
1081
+ }
1082
+
911
1083
  /**
912
1084
  * Hook to access user attributes from the UserProvider.
913
1085
  * Must be used within a UserProvider component.
@@ -988,111 +1160,131 @@ declare function useUserFeatures(): {
988
1160
  isFeatureEnabled: (featureId: string) => boolean;
989
1161
  };
990
1162
 
991
- /**
992
- * Main workspace management hook for the SDK.
993
- * Provides workspace state, CRUD operations, and user management.
994
- *
995
- * @returns An object containing:
996
- * - `workspaces`: Array of all workspaces the user has access to
997
- * - `currentWorkspace`: Currently selected workspace (null if none selected)
998
- * - `loading`: Boolean indicating if workspaces are being fetched
999
- * - `error`: Error message string (null if no error)
1000
- * - `refreshing`: Boolean indicating if workspaces are being refreshed in background
1001
- * - `switching`: Boolean - true when a workspace switch is in progress
1002
- * - `fetchWorkspaces()`: Function to fetch all workspaces
1003
- * - `refreshWorkspaces()`: Function to refresh workspaces in background (non-blocking)
1004
- * - `setCurrentWorkspace(workspace)`: Function to set the current workspace (direct, no callback)
1005
- * - `switchToWorkspace(workspace)`: Centralized switch - calls onWorkspaceChange first, then sets workspace
1006
- * - `resetCurrentWorkspace()`: Function to clear the current workspace
1007
- * - `createWorkspace(name, image?)`: Function to create a new workspace
1008
- * - `updateWorkspace(workspace, data)`: Function to update a workspace
1009
- * - `deleteWorkspace(workspaceId)`: Function to delete a workspace (owner only)
1010
- * - `getWorkspace(workspaceId)`: Function to fetch a specific workspace
1011
- * - `getUsers(workspaceId)`: Function to fetch users in a workspace
1012
- * - `addUser(workspaceId, email, role)`: Function to add a user to a workspace
1013
- * - `removeUser(workspaceId, userId)`: Function to remove a user from a workspace
1014
- * - `updateUser(workspaceId, userId, config)`: Function to update a user in a workspace
1015
- * - `getProfile()`: Function to fetch current user profile
1016
- * - `updateUserProfile(config)`: Function to update current user profile
1017
- * - `allFeatures`: Array of all available feature flags
1018
- * - `getFeatures()`: Function to fetch all available features
1019
- * - `updateFeature(workspaceId, key, value)`: Function to update a feature flag
1020
- *
1021
- * @example
1022
- * ```tsx
1023
- * function WorkspaceList() {
1024
- * const { workspaces, loading, fetchWorkspaces } = useSaaSWorkspaces();
1025
- *
1026
- * useEffect(() => {
1027
- * fetchWorkspaces();
1028
- * }, [fetchWorkspaces]);
1029
- *
1030
- * if (loading) return <Loading />;
1031
- *
1032
- * return (
1033
- * <ul>
1034
- * {workspaces.map(ws => (
1035
- * <li key={ws._id}>{ws.name}</li>
1036
- * ))}
1037
- * </ul>
1038
- * );
1039
- * }
1040
- * ```
1041
- *
1042
- * @example
1043
- * ```tsx
1044
- * // Create a new workspace
1045
- * function CreateWorkspace() {
1046
- * const { createWorkspace } = useSaaSWorkspaces();
1047
- *
1048
- * const handleCreate = async () => {
1049
- * try {
1050
- * await createWorkspace('My Workspace', 'https://example.com/logo.png');
1051
- * } catch (error) {
1052
- * console.error('Failed to create workspace:', error);
1053
- * }
1054
- * };
1055
- *
1056
- * return <button onClick={handleCreate}>Create Workspace</button>;
1057
- * }
1058
- * ```
1059
- *
1060
- * @example
1061
- * ```tsx
1062
- * // Delete workspace (owner only)
1063
- * function DeleteWorkspaceButton({ workspaceId }) {
1064
- * const { deleteWorkspace } = useSaaSWorkspaces();
1065
- *
1066
- * const handleDelete = async () => {
1067
- * if (!confirm('Are you sure?')) return;
1068
- * try {
1069
- * await deleteWorkspace(workspaceId);
1070
- * } catch (error) {
1071
- * // Error: "Only the workspace creator can delete the workspace"
1072
- * alert(error.message);
1073
- * }
1074
- * };
1075
- *
1076
- * return <button onClick={handleDelete}>Delete</button>;
1077
- * }
1078
- * ```
1079
- *
1080
- * @example
1081
- * ```tsx
1082
- * // Edge case: Workspace removed from user's access
1083
- * function WorkspaceContent() {
1084
- * const { currentWorkspace, workspaces } = useSaaSWorkspaces();
1085
- *
1086
- * // If current workspace is not in the list, it was removed
1087
- * // The hook automatically switches to first available workspace
1088
- * if (!currentWorkspace) {
1089
- * return <p>No workspace selected</p>;
1090
- * }
1091
- *
1092
- * return <div>{currentWorkspace.name}</div>;
1093
- * }
1094
- * ```
1095
- */
1163
+ declare class WorkspaceApi extends BaseApi {
1164
+ constructor(config: IOsConfig);
1165
+ getWorkspaces(): Promise<IWorkspace[]>;
1166
+ createWorkspace(data: {
1167
+ name: string;
1168
+ image?: string;
1169
+ }): Promise<IWorkspace>;
1170
+ updateWorkspace(id: string, data: Partial<IWorkspace>): Promise<IWorkspace>;
1171
+ deleteWorkspace(id: string): Promise<{
1172
+ success: boolean;
1173
+ }>;
1174
+ getWorkspaceUsers(workspaceId: string): Promise<IWorkspaceUser[]>;
1175
+ addUser(workspaceId: string, config: {
1176
+ email: string;
1177
+ role: string;
1178
+ }): Promise<{
1179
+ userId: string;
1180
+ workspace: IWorkspace;
1181
+ message: string;
1182
+ }>;
1183
+ removeUser(workspaceId: string, userId: string): Promise<{
1184
+ userId: string;
1185
+ workspace: IWorkspace;
1186
+ message: string;
1187
+ }>;
1188
+ updateUser(workspaceId: string, userId: string, data: Partial<IWorkspaceUser>): Promise<{
1189
+ userId: string;
1190
+ workspace: IWorkspace;
1191
+ message: string;
1192
+ }>;
1193
+ getFeatures(): Promise<IWorkspaceFeature[]>;
1194
+ updateFeature(workspaceId: string, key: string, value: boolean): Promise<IWorkspace>;
1195
+ getWorkspace(workspaceId: string): Promise<IWorkspace>;
1196
+ getProfile(): Promise<IUser>;
1197
+ updateUserProfile(config: Partial<IUser>): Promise<IUser>;
1198
+ /**
1199
+ * Get current subscription for a workspace
1200
+ * Returns subscription details including plan, plan version, and group information
1201
+ */
1202
+ getCurrentSubscription(workspaceId: string): Promise<ISubscriptionResponse>;
1203
+ /**
1204
+ * Get plan group for a workspace
1205
+ * Returns the plan group containing the current plan if subscription exists,
1206
+ * otherwise returns the latest published group
1207
+ */
1208
+ getPlanGroup(workspaceId: string): Promise<IPlanGroupResponse>;
1209
+ /**
1210
+ * Get plan group for a workspace with a specific version
1211
+ * @param workspaceId - The workspace ID
1212
+ * @param groupVersionId - The plan group version ID to fetch
1213
+ * @returns Plan group response with the specified version
1214
+ */
1215
+ getPlanGroupByVersion(workspaceId: string, groupVersionId: string): Promise<IPlanGroupResponse>;
1216
+ /**
1217
+ * Get current group version and available newer versions of the same group
1218
+ * - If user has active subscription: returns their current group version + newer versions
1219
+ * - If no subscription: returns the latest published group version
1220
+ * Shows what's new in newer versions to help users upgrade
1221
+ * Example: User on Group v1 (Basic Plan) can see Group v2 (Basic + Pro Plan)
1222
+ * @param workspaceId - The workspace ID
1223
+ * @returns Plan group versions response with currentVersion and availableVersions
1224
+ */
1225
+ getPlanGroupVersions(workspaceId: string): Promise<IPlanGroupVersionsResponse>;
1226
+ /**
1227
+ * Get plan group versions by slug (public, no auth required).
1228
+ * Returns the latest published plan group versions for the given plan group slug.
1229
+ * Use this for public pricing pages when you want to show a specific plan group.
1230
+ *
1231
+ * @param slug - Plan group slug (e.g. 'default', 'enterprise')
1232
+ * @returns Plan group versions response with currentVersion and availableVersions
1233
+ */
1234
+ getPublicPlans(slug: string): Promise<IPublicPlansResponse>;
1235
+ /**
1236
+ * Get plan group version details by ID (public, no auth required).
1237
+ * Returns the full plan group version with populated plan versions.
1238
+ * Use this for public pricing pages when you have the groupVersionId (e.g. from config or URL).
1239
+ *
1240
+ * @param groupVersionId - The plan group version ID to fetch
1241
+ * @returns Plan group version with populated plan versions
1242
+ */
1243
+ getPlanGroupVersion(groupVersionId: string): Promise<IPlanGroupVersion>;
1244
+ /**
1245
+ * Create checkout session for new subscription
1246
+ * @param workspaceId - The workspace ID
1247
+ * @param request - Checkout session request with planVersionId and optional billing interval/URLs
1248
+ * @returns Checkout session response with checkoutUrl to redirect user
1249
+ */
1250
+ createCheckoutSession(workspaceId: string, request: ICheckoutSessionRequest): Promise<ICheckoutSessionResponse>;
1251
+ /**
1252
+ * Update subscription (upgrade/downgrade)
1253
+ * Only allows plan changes within the same plan group
1254
+ * Returns checkout session if payment is required, otherwise returns subscription update response
1255
+ */
1256
+ updateSubscription(workspaceId: string, request: ISubscriptionUpdateRequest): Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
1257
+ /**
1258
+ * List invoices for a workspace subscription
1259
+ * @param workspaceId - The workspace ID
1260
+ * @param limit - Number of invoices to return (default: 10)
1261
+ * @param startingAfter - Invoice ID to start after (for pagination)
1262
+ * @returns List of invoices with pagination info
1263
+ */
1264
+ listInvoices(workspaceId: string, limit?: number, startingAfter?: string): Promise<IInvoiceListResponse>;
1265
+ /**
1266
+ * Get a single invoice by ID
1267
+ * @param workspaceId - The workspace ID
1268
+ * @param invoiceId - The invoice ID
1269
+ * @returns Invoice details
1270
+ */
1271
+ getInvoice(workspaceId: string, invoiceId: string): Promise<IInvoiceResponse>;
1272
+ /**
1273
+ * Cancel subscription at the end of the current billing period
1274
+ * Sets cancelAtPeriodEnd: true - subscription remains active until period ends
1275
+ * @param workspaceId - The workspace ID
1276
+ * @returns Updated subscription with cancelAtPeriodEnd and stripeCurrentPeriodEnd
1277
+ */
1278
+ cancelSubscriptionAtPeriodEnd(workspaceId: string): Promise<ISubscriptionResponse>;
1279
+ /**
1280
+ * Resume a subscription that was scheduled for cancellation
1281
+ * Sets cancelAtPeriodEnd: false - subscription will continue after period ends
1282
+ * @param workspaceId - The workspace ID
1283
+ * @returns Updated subscription with cancelAtPeriodEnd set to false
1284
+ */
1285
+ resumeSubscription(workspaceId: string): Promise<ISubscriptionResponse>;
1286
+ }
1287
+
1096
1288
  declare const useSaaSWorkspaces: () => {
1097
1289
  workspaces: IWorkspace[];
1098
1290
  loading: boolean;
@@ -1136,6 +1328,7 @@ declare const useSaaSWorkspaces: () => {
1136
1328
  success: boolean;
1137
1329
  }>;
1138
1330
  switching: boolean;
1331
+ switchingToId: string | null;
1139
1332
  };
1140
1333
 
1141
1334
  declare function WorkspaceSwitcher(props: {
@@ -1263,7 +1456,7 @@ declare const useSubscription: (workspaceId: string | null | undefined) => {
1263
1456
  *
1264
1457
  * return (
1265
1458
  * <div>
1266
- * <h3>{planGroup.name}</h3>
1459
+ * <h3>{planGroup.group.name}</h3>
1267
1460
  * {planGroup.plans.map(plan => (
1268
1461
  * <PlanCard key={plan._id} plan={plan} />
1269
1462
  * ))}
@@ -1703,5 +1896,39 @@ declare class EventEmitter {
1703
1896
  }
1704
1897
  declare const eventEmitter: EventEmitter;
1705
1898
 
1706
- export { ApiVersion, AuthStatus, BetaForm, PricingPage, SaaSOSProvider, WhenAuthenticated, WhenRoles, WhenUnauthenticated, WhenUserFeatureDisabled, WhenUserFeatureEnabled, WhenWorkspaceFeatureDisabled, WhenWorkspaceFeatureEnabled, WhenWorkspaceRoles, WorkspaceSwitcher, eventEmitter, useCreateCheckoutSession, useInvoice, useInvoices, usePlanGroup, usePlanGroupVersions, usePublicPlanGroupVersion, usePublicPlans, useSaaSAuth, useSaaSSettings, useSaaSWorkspaces, useSubscription, useSubscriptionManagement, useUpdateSubscription, useUserAttributes, useUserFeatures };
1707
- export type { BillingInterval, EventData, EventType, IBasePricing, ICheckoutSessionRequest, ICheckoutSessionResponse, IEventCallbacks, IInvoice, IInvoiceListResponse, IInvoiceResponse, IPlan, IPlanGroup, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionWithPlan, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanPricing, IPublicPlanQuotaValue, IPublicPlanVersion, IPublicPlansResponse, IQuotaValue, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, InvoiceStatus, OnWorkspaceChangeParams, PricingPageDetails, PricingPageProps, UserCreatedEventData, UserUpdatedEventData, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };
1899
+ /**
1900
+ * Centralized API client for organization (OS) settings.
1901
+ * Extends BaseApi for shared URL/auth/request handling.
1902
+ */
1903
+
1904
+ declare class SettingsApi extends BaseApi {
1905
+ constructor(config: IOsConfig);
1906
+ getSettings(signal?: AbortSignal): Promise<ISettings>;
1907
+ }
1908
+
1909
+ type QuotaDisplayValue = {
1910
+ included: number;
1911
+ overage?: number;
1912
+ unitSize?: number;
1913
+ } | number | null;
1914
+ /**
1915
+ * Normalize a quota value (legacy or per-interval) to a display shape for a given billing interval.
1916
+ * - Legacy: number or IQuotaValue → use as-is (interval ignored).
1917
+ * - New schema: IQuotaByInterval → pick the interval slice (e.g. monthly, yearly, quarterly).
1918
+ */
1919
+ declare function getQuotaDisplayValue(value: number | IQuotaValue | IQuotaByInterval | null | undefined, interval?: BillingInterval): QuotaDisplayValue;
1920
+ /** Options for formatting quota with price. */
1921
+ interface FormatQuotaWithPriceOptions {
1922
+ /** If true, overage is in cents (Stripe); format as dollars. Default true. */
1923
+ overageInCents?: boolean;
1924
+ /** Currency symbol. Default '$'. */
1925
+ currencySymbol?: string;
1926
+ }
1927
+ /**
1928
+ * Format a quota display value as "X included, then $Y.YY / unit" (e.g. "10 included, then $10.00 / video").
1929
+ * Assumes overage is the per-unit price (in cents when overageInCents is true).
1930
+ */
1931
+ declare function formatQuotaWithPrice(value: QuotaDisplayValue, unitName: string, options?: FormatQuotaWithPriceOptions): string;
1932
+
1933
+ export { ApiVersion, AuthStatus, BaseApi, BetaForm, PricingPage, SaaSOSProvider, SettingsApi, SubscriptionContextProvider, UserApi, WhenAuthenticated, WhenNoSubscription, WhenRoles, WhenSubscription, WhenSubscriptionToPlans, WhenUnauthenticated, WhenUserFeatureDisabled, WhenUserFeatureEnabled, WhenWorkspaceFeatureDisabled, WhenWorkspaceFeatureEnabled, WhenWorkspaceRoles, WorkspaceApi, WorkspaceSwitcher, eventEmitter, formatQuotaWithPrice, getQuotaDisplayValue, useCreateCheckoutSession, useInvoice, useInvoices, usePlanGroup, usePlanGroupVersions, usePublicPlanGroupVersion, usePublicPlans, useSaaSAuth, useSaaSOs, useSaaSSettings, useSaaSWorkspaces, useSubscription, useSubscriptionContext, useSubscriptionManagement, useUpdateSubscription, useUserAttributes, useUserFeatures };
1934
+ export type { BillingInterval, EventData, EventType, FormatQuotaWithPriceOptions, IBaseApiConfig, IBasePricing, ICheckoutSessionRequest, ICheckoutSessionResponse, IEventCallbacks, IInvoice, IInvoiceListResponse, IInvoiceResponse, IPlan, IPlanGroup, IPlanGroupInfo, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionSummary, IPlanVersionWithPlan, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanPricing, IPublicPlanQuotaValue, IPublicPlanVersion, IPublicPlansResponse, IQuotaByInterval, IQuotaIntervalValue, IQuotaValue, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, InvoiceStatus, OnWorkspaceChangeParams, PricingPageDetails, PricingPageProps, QuotaDisplayValue, SubscriptionContextValue, UserCreatedEventData, UserUpdatedEventData, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };