@buildbase/sdk 0.0.10 → 0.0.12

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.
@@ -1,8 +1,40 @@
1
- import { IPlanGroupResponse, ISubscriptionResponse, ISubscriptionUpdateResponse } from '../../api/types';
1
+ import { BillingInterval, ICheckoutSessionRequest, ICheckoutSessionResponse, IInvoice, IPlanGroupResponse, IPlanGroupVersionsResponse, ISubscriptionResponse, ISubscriptionUpdateResponse } from '../../api/types';
2
2
  /**
3
- * Hook to get and manage the current subscription for a workspace
4
- * @param workspaceId - The workspace ID to get subscription for
5
- * @returns Subscription data and loading/error states
3
+ * Hook to get and manage the current subscription for a workspace.
4
+ * Automatically fetches subscription when workspaceId changes.
5
+ *
6
+ * @param workspaceId - The workspace ID to get subscription for. Can be null/undefined to disable fetching.
7
+ * @returns An object containing:
8
+ * - `subscription`: Current subscription data (null if no subscription or not loaded)
9
+ * - `loading`: Boolean indicating if subscription is being fetched
10
+ * - `error`: Error message string (null if no error)
11
+ * - `refetch()`: Function to manually refetch the subscription
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * function SubscriptionStatus() {
16
+ * const { currentWorkspace } = useSaaSWorkspaces();
17
+ * const { subscription, loading, error } = useSubscription(currentWorkspace?._id);
18
+ *
19
+ * if (loading) return <Loading />;
20
+ * if (error) return <Error message={error} />;
21
+ * if (!subscription) return <p>No active subscription</p>;
22
+ *
23
+ * return <p>Plan: {subscription.plan.name}</p>;
24
+ * }
25
+ * ```
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * // Edge case: Workspace ID changes
30
+ * function SubscriptionComponent({ workspaceId }) {
31
+ * const { subscription, refetch } = useSubscription(workspaceId);
32
+ *
33
+ * // Subscription automatically refetches when workspaceId changes
34
+ * // Use refetch() to manually refresh after mutations
35
+ * return <SubscriptionDetails subscription={subscription} />;
36
+ * }
37
+ * ```
6
38
  */
7
39
  export declare const useSubscription: (workspaceId: string | null | undefined) => {
8
40
  subscription: ISubscriptionResponse | null;
@@ -11,39 +43,387 @@ export declare const useSubscription: (workspaceId: string | null | undefined) =
11
43
  refetch: () => Promise<void>;
12
44
  };
13
45
  /**
14
- * Hook to get the plan group for a workspace
46
+ * Hook to get the plan group for a workspace.
15
47
  * Returns the plan group containing the current plan if subscription exists,
16
- * otherwise returns the latest published group
17
- * @param workspaceId - The workspace ID to get plan group for
18
- * @returns Plan group data and loading/error states
48
+ * otherwise returns the latest published group.
49
+ * Automatically fetches when workspaceId or groupVersionId changes.
50
+ *
51
+ * @param workspaceId - The workspace ID to get plan group for. Can be null/undefined to disable fetching.
52
+ * @param groupVersionId - Optional: specific group version ID to fetch (for viewing historical versions)
53
+ * @returns An object containing:
54
+ * - `planGroup`: Plan group data (null if not loaded)
55
+ * - `loading`: Boolean indicating if plan group is being fetched
56
+ * - `error`: Error message string (null if no error)
57
+ * - `refetch()`: Function to manually refetch the plan group
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * function PlanGroupDisplay() {
62
+ * const { currentWorkspace } = useSaaSWorkspaces();
63
+ * const { planGroup, loading } = usePlanGroup(currentWorkspace?._id);
64
+ *
65
+ * if (loading) return <Loading />;
66
+ * if (!planGroup) return <p>No plan group available</p>;
67
+ *
68
+ * return (
69
+ * <div>
70
+ * <h3>{planGroup.name}</h3>
71
+ * {planGroup.plans.map(plan => (
72
+ * <PlanCard key={plan._id} plan={plan} />
73
+ * ))}
74
+ * </div>
75
+ * );
76
+ * }
77
+ * ```
78
+ *
79
+ * @example
80
+ * ```tsx
81
+ * // Fetch specific version for comparison
82
+ * function PlanVersionComparison() {
83
+ * const { currentWorkspace } = useSaaSWorkspaces();
84
+ * const current = usePlanGroup(currentWorkspace?._id);
85
+ * const previous = usePlanGroup(currentWorkspace?._id, 'previous-version-id');
86
+ *
87
+ * return <ComparePlans current={current.planGroup} previous={previous.planGroup} />;
88
+ * }
89
+ * ```
19
90
  */
20
- export declare const usePlanGroup: (workspaceId: string | null | undefined) => {
91
+ export declare const usePlanGroup: (workspaceId: string | null | undefined, groupVersionId?: string | null) => {
21
92
  planGroup: IPlanGroupResponse | null;
22
93
  loading: boolean;
23
94
  error: string | null;
24
95
  refetch: () => Promise<void>;
25
96
  };
26
97
  /**
27
- * Hook to update subscription (upgrade/downgrade)
28
- * @param workspaceId - The workspace ID to update subscription for
29
- * @returns Update function and loading/error states
98
+ * Hook to get all available versions of a plan group for a workspace.
99
+ * Shows current version and available newer versions for upgrade paths.
100
+ * Automatically fetches when workspaceId changes.
101
+ *
102
+ * @param workspaceId - The workspace ID to get plan group versions for. Can be null/undefined to disable fetching.
103
+ * @returns An object containing:
104
+ * - `versions`: Plan group versions response with currentVersion and availableVersions
105
+ * - `loading`: Boolean indicating if versions are being fetched
106
+ * - `error`: Error message string (null if no error)
107
+ * - `refetch()`: Function to manually refetch the versions
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * function UpgradeOptions() {
112
+ * const { currentWorkspace } = useSaaSWorkspaces();
113
+ * const { versions, loading } = usePlanGroupVersions(currentWorkspace?._id);
114
+ *
115
+ * if (loading) return <Loading />;
116
+ *
117
+ * return (
118
+ * <div>
119
+ * <p>Current: {versions?.currentVersion.name}</p>
120
+ * <h4>Available Upgrades:</h4>
121
+ * {versions?.availableVersions.map(version => (
122
+ * <UpgradeCard key={version._id} version={version} />
123
+ * ))}
124
+ * </div>
125
+ * );
126
+ * }
127
+ * ```
128
+ */
129
+ export declare const usePlanGroupVersions: (workspaceId: string | null | undefined) => {
130
+ versions: IPlanGroupVersionsResponse | null;
131
+ loading: boolean;
132
+ error: string | null;
133
+ refetch: () => Promise<void>;
134
+ };
135
+ /**
136
+ * Hook to create a checkout session for a new subscription.
137
+ * Returns a function to initiate the checkout process.
138
+ *
139
+ * @param workspaceId - The workspace ID to create checkout session for. Can be null/undefined.
140
+ * @returns An object containing:
141
+ * - `createCheckoutSession(request)`: Function to create checkout session (throws if workspaceId is null)
142
+ * - `loading`: Boolean indicating if checkout session is being created
143
+ * - `error`: Error message string (null if no error)
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * function SubscribeButton({ planVersionId }) {
148
+ * const { currentWorkspace } = useSaaSWorkspaces();
149
+ * const { createCheckoutSession, loading } = useCreateCheckoutSession(currentWorkspace?._id);
150
+ *
151
+ * const handleSubscribe = async () => {
152
+ * try {
153
+ * const result = await createCheckoutSession({
154
+ * planVersionId,
155
+ * successUrl: window.location.href,
156
+ * cancelUrl: window.location.href,
157
+ * });
158
+ * // Redirect to checkout
159
+ * window.location.href = result.checkoutUrl;
160
+ * } catch (error) {
161
+ * console.error('Failed to create checkout:', error);
162
+ * }
163
+ * };
164
+ *
165
+ * return (
166
+ * <button onClick={handleSubscribe} disabled={loading}>
167
+ * {loading ? 'Loading...' : 'Subscribe'}
168
+ * </button>
169
+ * );
170
+ * }
171
+ * ```
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * // Edge case: Workspace ID not available
176
+ * function SubscribeButton() {
177
+ * const { currentWorkspace } = useSaaSWorkspaces();
178
+ * const { createCheckoutSession } = useCreateCheckoutSession(currentWorkspace?._id);
179
+ *
180
+ * const handleSubscribe = async () => {
181
+ * try {
182
+ * await createCheckoutSession({ planVersionId: 'plan-123' });
183
+ * } catch (error) {
184
+ * // Error: "Workspace ID is required"
185
+ * alert('Please select a workspace first');
186
+ * }
187
+ * };
188
+ *
189
+ * return <button onClick={handleSubscribe}>Subscribe</button>;
190
+ * }
191
+ * ```
192
+ */
193
+ export declare const useCreateCheckoutSession: (workspaceId: string | null | undefined) => {
194
+ createCheckoutSession: (request: ICheckoutSessionRequest) => Promise<ICheckoutSessionResponse>;
195
+ loading: boolean;
196
+ error: string | null;
197
+ };
198
+ /**
199
+ * Hook to update subscription (upgrade/downgrade).
200
+ * Returns checkout session if payment is required, otherwise returns subscription update response.
201
+ *
202
+ * @param workspaceId - The workspace ID to update subscription for. Can be null/undefined.
203
+ * @returns An object containing:
204
+ * - `updateSubscription(planVersionId, options?)`: Function to update subscription (throws if workspaceId is null)
205
+ * - `loading`: Boolean indicating if subscription is being updated
206
+ * - `error`: Error message string (null if no error)
207
+ *
208
+ * @example
209
+ * ```tsx
210
+ * function UpgradeButton({ planVersionId }) {
211
+ * const { currentWorkspace } = useSaaSWorkspaces();
212
+ * const { updateSubscription, loading } = useUpdateSubscription(currentWorkspace?._id);
213
+ *
214
+ * const handleUpgrade = async () => {
215
+ * try {
216
+ * const result = await updateSubscription(planVersionId, {
217
+ * billingInterval: 'monthly',
218
+ * successUrl: window.location.href,
219
+ * cancelUrl: window.location.href,
220
+ * });
221
+ *
222
+ * // Check if payment is required
223
+ * if ('checkoutUrl' in result) {
224
+ * window.location.href = result.checkoutUrl;
225
+ * } else {
226
+ * // Subscription updated without payment
227
+ * alert('Subscription updated successfully!');
228
+ * }
229
+ * } catch (error) {
230
+ * console.error('Failed to update subscription:', error);
231
+ * }
232
+ * };
233
+ *
234
+ * return (
235
+ * <button onClick={handleUpgrade} disabled={loading}>
236
+ * {loading ? 'Upgrading...' : 'Upgrade'}
237
+ * </button>
238
+ * );
239
+ * }
240
+ * ```
241
+ *
242
+ * @example
243
+ * ```tsx
244
+ * // Handle both checkout and direct update responses
245
+ * function SubscriptionUpdater({ planVersionId }) {
246
+ * const { updateSubscription } = useUpdateSubscription(workspaceId);
247
+ *
248
+ * const handleUpdate = async () => {
249
+ * const result = await updateSubscription(planVersionId);
250
+ *
251
+ * // Type guard to check response type
252
+ * if ('checkoutUrl' in result) {
253
+ * // Redirect to payment
254
+ * window.location.href = result.checkoutUrl;
255
+ * } else {
256
+ * // Direct update successful
257
+ * console.log('Updated subscription:', result.subscription);
258
+ * }
259
+ * };
260
+ *
261
+ * return <button onClick={handleUpdate}>Update</button>;
262
+ * }
263
+ * ```
30
264
  */
31
265
  export declare const useUpdateSubscription: (workspaceId: string | null | undefined) => {
32
- updateSubscription: (planVersionId: string) => Promise<ISubscriptionUpdateResponse>;
266
+ updateSubscription: (planVersionId: string, options?: {
267
+ billingInterval?: BillingInterval;
268
+ successUrl?: string;
269
+ cancelUrl?: string;
270
+ }) => Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
33
271
  loading: boolean;
34
272
  error: string | null;
35
273
  };
36
274
  /**
37
- * Combined hook that provides both subscription and plan group data
38
- * Useful for subscription management pages
39
- * @param workspaceId - The workspace ID
40
- * @returns Combined subscription and plan group data with loading/error states
275
+ * Combined hook that provides both subscription and plan group data.
276
+ * Useful for subscription management pages that need both pieces of data.
277
+ * Combines useSubscription, usePlanGroup, and useUpdateSubscription.
278
+ *
279
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
280
+ * @param groupVersionId - Optional: specific group version ID to fetch
281
+ * @returns An object containing:
282
+ * - `subscription`: Current subscription data (from useSubscription)
283
+ * - `planGroup`: Plan group data (from usePlanGroup)
284
+ * - `loading`: Boolean indicating if any operation is in progress
285
+ * - `error`: Error message string (null if no error)
286
+ * - `updateSubscription(planVersionId, options?)`: Function to update subscription
287
+ * - `refetch()`: Function to refetch both subscription and plan group
288
+ *
289
+ * @example
290
+ * ```tsx
291
+ * function SubscriptionManagementPage() {
292
+ * const { currentWorkspace } = useSaaSWorkspaces();
293
+ * const {
294
+ * subscription,
295
+ * planGroup,
296
+ * loading,
297
+ * updateSubscription,
298
+ * refetch,
299
+ * } = useSubscriptionManagement(currentWorkspace?._id);
300
+ *
301
+ * if (loading) return <Loading />;
302
+ *
303
+ * return (
304
+ * <div>
305
+ * <CurrentPlan subscription={subscription} />
306
+ * <AvailablePlans planGroup={planGroup} onSelect={updateSubscription} />
307
+ * <button onClick={refetch}>Refresh</button>
308
+ * </div>
309
+ * );
310
+ * }
311
+ * ```
41
312
  */
42
- export declare const useSubscriptionManagement: (workspaceId: string | null | undefined) => {
313
+ export declare const useSubscriptionManagement: (workspaceId: string | null | undefined, groupVersionId?: string | null) => {
43
314
  subscription: ISubscriptionResponse | null;
44
315
  planGroup: IPlanGroupResponse | null;
45
316
  loading: boolean;
46
317
  error: string | null;
47
- updateSubscription: (planVersionId: string) => Promise<ISubscriptionUpdateResponse>;
318
+ updateSubscription: (planVersionId: string, options?: {
319
+ billingInterval?: BillingInterval;
320
+ successUrl?: string;
321
+ cancelUrl?: string;
322
+ }) => Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
323
+ refetch: () => Promise<void>;
324
+ };
325
+ /**
326
+ * Hook to list invoices for a workspace subscription with pagination support.
327
+ * Automatically fetches when workspaceId, limit, or startingAfter changes.
328
+ *
329
+ * @param workspaceId - The workspace ID to get invoices for. Can be null/undefined to disable fetching.
330
+ * @param limit - Number of invoices to return (default: 10)
331
+ * @param startingAfter - Invoice ID to start after (for pagination)
332
+ * @returns An object containing:
333
+ * - `invoices`: Array of invoice objects
334
+ * - `hasMore`: Boolean indicating if there are more invoices to load
335
+ * - `loading`: Boolean indicating if invoices are being fetched
336
+ * - `error`: Error message string (null if no error)
337
+ * - `refetch()`: Function to manually refetch invoices
338
+ *
339
+ * @example
340
+ * ```tsx
341
+ * function InvoiceList() {
342
+ * const { currentWorkspace } = useSaaSWorkspaces();
343
+ * const { invoices, hasMore, loading, refetch } = useInvoices(currentWorkspace?._id, 10);
344
+ *
345
+ * if (loading) return <Loading />;
346
+ *
347
+ * return (
348
+ * <div>
349
+ * {invoices.map(invoice => (
350
+ * <InvoiceCard key={invoice._id} invoice={invoice} />
351
+ * ))}
352
+ * {hasMore && <button onClick={() => refetch()}>Load More</button>}
353
+ * </div>
354
+ * );
355
+ * }
356
+ * ```
357
+ *
358
+ * @example
359
+ * ```tsx
360
+ * // Pagination example
361
+ * function PaginatedInvoices() {
362
+ * const [lastInvoiceId, setLastInvoiceId] = useState<string | undefined>();
363
+ * const { currentWorkspace } = useSaaSWorkspaces();
364
+ * const { invoices, hasMore, refetch } = useInvoices(
365
+ * currentWorkspace?._id,
366
+ * 10,
367
+ * lastInvoiceId
368
+ * );
369
+ *
370
+ * const loadMore = () => {
371
+ * if (invoices.length > 0) {
372
+ * setLastInvoiceId(invoices[invoices.length - 1]._id);
373
+ * }
374
+ * };
375
+ *
376
+ * return (
377
+ * <div>
378
+ * {invoices.map(invoice => <InvoiceCard key={invoice._id} invoice={invoice} />)}
379
+ * {hasMore && <button onClick={loadMore}>Load More</button>}
380
+ * </div>
381
+ * );
382
+ * }
383
+ * ```
384
+ */
385
+ export declare const useInvoices: (workspaceId: string | null | undefined, limit?: number, startingAfter?: string) => {
386
+ invoices: IInvoice[];
387
+ hasMore: boolean;
388
+ loading: boolean;
389
+ error: string | null;
390
+ refetch: () => Promise<void>;
391
+ };
392
+ /**
393
+ * Hook to get a single invoice by ID.
394
+ * Automatically fetches when workspaceId or invoiceId changes.
395
+ *
396
+ * @param workspaceId - The workspace ID. Can be null/undefined to disable fetching.
397
+ * @param invoiceId - The invoice ID to fetch. Can be null/undefined to disable fetching.
398
+ * @returns An object containing:
399
+ * - `invoice`: Invoice data object (null if not loaded)
400
+ * - `loading`: Boolean indicating if invoice is being fetched
401
+ * - `error`: Error message string (null if no error)
402
+ * - `refetch()`: Function to manually refetch the invoice
403
+ *
404
+ * @example
405
+ * ```tsx
406
+ * function InvoiceDetails({ invoiceId }) {
407
+ * const { currentWorkspace } = useSaaSWorkspaces();
408
+ * const { invoice, loading, error } = useInvoice(currentWorkspace?._id, invoiceId);
409
+ *
410
+ * if (loading) return <Loading />;
411
+ * if (error) return <Error message={error} />;
412
+ * if (!invoice) return <p>Invoice not found</p>;
413
+ *
414
+ * return (
415
+ * <div>
416
+ * <h2>Invoice #{invoice.invoiceNumber}</h2>
417
+ * <p>Amount: ${invoice.amount}</p>
418
+ * <p>Status: {invoice.status}</p>
419
+ * </div>
420
+ * );
421
+ * }
422
+ * ```
423
+ */
424
+ export declare const useInvoice: (workspaceId: string | null | undefined, invoiceId: string | null | undefined) => {
425
+ invoice: IInvoice | null;
426
+ loading: boolean;
427
+ error: string | null;
48
428
  refetch: () => Promise<void>;
49
429
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildbase/sdk",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "description": "A SDK for Buildbase",
6
6
  "main": "dist/index.js",
@@ -24,6 +24,7 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "rollup -c",
27
+ "build:analyze": "rollup --config rollup.config.analyze.js",
27
28
  "dev": "rollup -c -w",
28
29
  "clean": "rimraf dist",
29
30
  "prebuild": "npm run clean",
@@ -44,7 +45,18 @@
44
45
  "react-dom": "^19.0.0"
45
46
  },
46
47
  "dependencies": {
48
+ "@radix-ui/react-alert-dialog": "^1.1.13",
49
+ "@radix-ui/react-avatar": "^1.1.9",
50
+ "@radix-ui/react-dialog": "^1.1.13",
47
51
  "@radix-ui/react-icons": "^1.3.2",
52
+ "@radix-ui/react-label": "^2.1.6",
53
+ "@radix-ui/react-popover": "^1.1.13",
54
+ "@radix-ui/react-radio-group": "^1.3.6",
55
+ "@radix-ui/react-scroll-area": "^1.2.8",
56
+ "@radix-ui/react-select": "^2.2.4",
57
+ "@radix-ui/react-separator": "^1.1.6",
58
+ "@radix-ui/react-slot": "^1.2.2",
59
+ "@radix-ui/react-switch": "^1.2.4",
48
60
  "axios": "^1.6.0",
49
61
  "class-variance-authority": "^0.7.0",
50
62
  "clsx": "^2.0.0",
@@ -57,17 +69,6 @@
57
69
  },
58
70
  "devDependencies": {
59
71
  "@hookform/resolvers": "^5.0.1",
60
- "@radix-ui/react-alert-dialog": "^1.1.13",
61
- "@radix-ui/react-avatar": "^1.1.9",
62
- "@radix-ui/react-dialog": "^1.1.13",
63
- "@radix-ui/react-label": "^2.1.6",
64
- "@radix-ui/react-popover": "^1.1.13",
65
- "@radix-ui/react-radio-group": "^1.3.6",
66
- "@radix-ui/react-scroll-area": "^1.2.8",
67
- "@radix-ui/react-select": "^2.2.4",
68
- "@radix-ui/react-separator": "^1.1.6",
69
- "@radix-ui/react-slot": "^1.2.2",
70
- "@radix-ui/react-switch": "^1.2.4",
71
72
  "@rollup/plugin-commonjs": "^28.0.6",
72
73
  "@rollup/plugin-json": "^6.1.0",
73
74
  "@rollup/plugin-node-resolve": "^16.0.1",
@@ -88,6 +89,7 @@
88
89
  "rollup": "^4.0.0",
89
90
  "rollup-plugin-dts": "^6.0.0",
90
91
  "rollup-plugin-postcss": "^4.0.0",
92
+ "rollup-plugin-visualizer": "^6.0.5",
91
93
  "tailwindcss": "^3.4.17",
92
94
  "tslib": "^2.8.1",
93
95
  "typescript": "^5.2.0"