@buildbase/sdk 0.0.50 → 0.0.53

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 (52) hide show
  1. package/AGENTS.md +41 -13
  2. package/CHANGELOG.md +109 -0
  3. package/README.md +343 -44
  4. package/dist/css/styles.css +1 -1
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.d.ts +874 -53
  7. package/dist/index.mjs +1 -1
  8. package/dist/mcp/index.cjs +1 -0
  9. package/dist/mcp/index.d.ts +1402 -0
  10. package/dist/mcp/index.mjs +1 -0
  11. package/dist/react/chunks/SettingsDialog-BxDYsie6.mjs +2 -0
  12. package/dist/react/chunks/SettingsDialog-Dy8W3NA6.cjs +2 -0
  13. package/dist/react/chunks/SubscriptionDialog-6c5dHoQd.mjs +2 -0
  14. package/dist/react/chunks/SubscriptionDialog-CpVnnXJg.cjs +2 -0
  15. package/dist/react/chunks/ar-1Z1MOGAP.mjs +2 -0
  16. package/dist/react/chunks/ar-VGzBv3AZ.cjs +2 -0
  17. package/dist/react/chunks/de-BjdDg60Y.cjs +2 -0
  18. package/dist/react/chunks/de-CXUItplO.mjs +2 -0
  19. package/dist/react/chunks/es-BBPsSZUp.cjs +2 -0
  20. package/dist/react/chunks/es-BTbzVutz.mjs +2 -0
  21. package/dist/react/chunks/fr-Cax48X_S.cjs +2 -0
  22. package/dist/react/chunks/fr-DPMeOQu3.mjs +2 -0
  23. package/dist/react/chunks/hi-BJqvpG6d.cjs +2 -0
  24. package/dist/react/chunks/hi-JfJx-LV7.mjs +2 -0
  25. package/dist/react/chunks/ja-CDGtLzTk.mjs +2 -0
  26. package/dist/react/chunks/ja-DvVyj5xX.cjs +2 -0
  27. package/dist/react/chunks/react-4SlWxHdh.cjs +2 -0
  28. package/dist/react/chunks/react-OL1uSkpr.mjs +2 -0
  29. package/dist/react/chunks/zh-BAcqxkxk.cjs +2 -0
  30. package/dist/react/chunks/zh-BNZ2Ooe8.mjs +2 -0
  31. package/dist/react/index.cjs +1 -1
  32. package/dist/react/index.d.ts +484 -93
  33. package/dist/react/index.mjs +1 -1
  34. package/package.json +22 -5
  35. package/dist/react/chunks/SubscriptionDialog-A6oETKbb.cjs +0 -2
  36. package/dist/react/chunks/SubscriptionDialog-nuMunBn4.mjs +0 -2
  37. package/dist/react/chunks/ar-BRvKHRYS.cjs +0 -2
  38. package/dist/react/chunks/ar-IhPhJAZA.mjs +0 -2
  39. package/dist/react/chunks/de-D3q0vQBG.cjs +0 -2
  40. package/dist/react/chunks/de-bvh5IFSx.mjs +0 -2
  41. package/dist/react/chunks/es-B9kiwJmF.cjs +0 -2
  42. package/dist/react/chunks/es-TyUz4_E1.mjs +0 -2
  43. package/dist/react/chunks/fr-C500Ytao.cjs +0 -2
  44. package/dist/react/chunks/fr-CKm-bSvG.mjs +0 -2
  45. package/dist/react/chunks/hi-CfFhH2uQ.cjs +0 -2
  46. package/dist/react/chunks/hi-Ck9cPpd-.mjs +0 -2
  47. package/dist/react/chunks/ja-AM4H1tXw.mjs +0 -2
  48. package/dist/react/chunks/ja-DfROrx_j.cjs +0 -2
  49. package/dist/react/chunks/react-CTX0_nOV.cjs +0 -2
  50. package/dist/react/chunks/react-DzQupoqH.mjs +0 -2
  51. package/dist/react/chunks/zh-CLmBh-it.cjs +0 -2
  52. package/dist/react/chunks/zh-DCVPxie-.mjs +0 -2
@@ -0,0 +1,1402 @@
1
+ import { z } from 'zod';
2
+
3
+ /** MCP Server Card (SEP-1649 / SEP-2127), advertising a live MCP server. */
4
+ interface McpServerCard {
5
+ /** Server name. */
6
+ name: string;
7
+ /** Server version. */
8
+ version: string;
9
+ /** MCP transport endpoint URL the agent connects to. */
10
+ endpoint: string;
11
+ /** Transport type. Defaults to `"streamable-http"`. */
12
+ transport?: string;
13
+ /** Capabilities object, e.g. `{ tools: {}, resources: {} }`. */
14
+ capabilities?: Record<string, unknown>;
15
+ /** Optional human description. */
16
+ description?: string;
17
+ /** Documentation URL. */
18
+ documentationUrl?: string;
19
+ }
20
+
21
+ /**
22
+ * Built-in MCP tools mapping BuildBase capabilities to agent-callable tools.
23
+ *
24
+ * Authorization model: the agent acts as an authenticated app user — it knows
25
+ * your app, not BuildBase. Built-in tools therefore carry NO BuildBase-specific
26
+ * scope requirement; they're available whenever your `auth.verify` accepts the
27
+ * token and your app chose to expose them. Every call runs under the acting
28
+ * user's own BuildBase session, so the server enforces that user's permissions
29
+ * — an agent can never exceed what its user could do. Want per-scope gating on
30
+ * top? Set `requiredScopes` on your own custom tools — the handler enforces it.
31
+ *
32
+ * The read-vs-write boundary is YOUR choice via `builtinTools`: the default is
33
+ * `'readonly'` (reads only — least privilege). Opt in to `'all'` to also expose
34
+ * writes AND destructive/billing ops (workspace delete, subscription cancel,
35
+ * credit purchase — still gated by the user's own permissions), `false` to
36
+ * expose no built-ins, or `{ include, exclude }` to hand-pick specific tools.
37
+ *
38
+ * Every workspace-scoped tool accepts an optional `workspaceId` and falls back
39
+ * to the workspace pinned on the verified token (`McpAuthInfo.workspaceId`).
40
+ */
41
+
42
+ /** Every built-in tool, keyed by name. */
43
+ declare const builtinMcpTools: ReadonlyMap<string, McpToolDefinition<any>>;
44
+ /** The name of a built-in BuildBase MCP tool. */
45
+ type BuiltinMcpToolName = 'list_workspaces' | 'get_workspace' | 'get_user_profile' | 'list_workspace_users' | 'get_subscription' | 'get_plans' | 'get_plan_versions' | 'get_public_plans' | 'get_plan_version' | 'list_invoices' | 'get_invoice' | 'get_quota_usage' | 'get_all_quota_usage' | 'get_usage_logs' | 'get_credit_balance' | 'list_credit_transactions' | 'get_credit_packages' | 'get_credit_buckets' | 'get_expiring_credits' | 'get_public_credit_packages' | 'check_feature_flag' | 'check_permission' | 'resolve_permissions' | 'get_settings' | 'record_usage' | 'record_usage_batch' | 'consume_credits' | 'send_notification' | 'create_workspace' | 'update_workspace' | 'delete_workspace' | 'invite_workspace_user' | 'remove_workspace_user' | 'update_workspace_user_role' | 'update_user_profile' | 'update_feature_flag' | 'create_subscription_checkout' | 'update_subscription' | 'cancel_subscription' | 'resume_subscription' | 'get_billing_portal_url' | 'purchase_credits';
46
+ /** Resolve a `builtinTools` config value to the tools it selects. */
47
+ declare function selectBuiltinTools(selection: 'all' | 'readonly' | false | {
48
+ include?: BuiltinMcpToolName[];
49
+ exclude?: BuiltinMcpToolName[];
50
+ }): McpToolDefinition<any>[];
51
+
52
+ interface IDocument {
53
+ _id: string;
54
+ /** Optional; some APIs only return _id. Prefer _id for identity. */
55
+ id?: string;
56
+ createdAt: string;
57
+ updatedAt: string;
58
+ deleted: boolean;
59
+ }
60
+ interface IUser extends IDocument {
61
+ _id: string;
62
+ name: string;
63
+ email: string;
64
+ /** Profile image URL. Often omitted or empty from API. */
65
+ image?: string;
66
+ role: string;
67
+ /** ISO country code. May be omitted. */
68
+ country?: string;
69
+ /** IANA timezone. May be omitted. */
70
+ timezone?: string;
71
+ /** Language code. May be omitted. */
72
+ language?: string;
73
+ /** Currency code. May be omitted. */
74
+ currency?: string;
75
+ attributes?: Record<string, string | number | boolean>;
76
+ }
77
+ type BillingInterval = 'monthly' | 'yearly' | 'quarterly';
78
+ /** Subscription status constants */
79
+ declare const SubscriptionStatus: {
80
+ readonly Active: "active";
81
+ readonly Trialing: "trialing";
82
+ readonly Canceled: "canceled";
83
+ readonly PastDue: "past_due";
84
+ readonly Paused: "paused";
85
+ readonly Incomplete: "incomplete";
86
+ readonly Unpaid: "unpaid";
87
+ };
88
+ type SubscriptionStatusType = (typeof SubscriptionStatus)[keyof typeof SubscriptionStatus];
89
+ interface ISubscription {
90
+ _id: string;
91
+ subscriptionStatus: SubscriptionStatusType;
92
+ /** Stripe Subscription ID (e.g. 'sub_...'). Present when linked to Stripe. */
93
+ subscriptionId?: string;
94
+ stripePriceId?: string;
95
+ stripeCurrentPeriodEnd?: string;
96
+ /** When the current monthly usage period ends (quotas reset on this date). */
97
+ usageCurrentPeriodEnd?: string;
98
+ cancelAtPeriodEnd: boolean;
99
+ billingInterval?: BillingInterval;
100
+ /** Trial start date (ISO string). Set when subscription is in trial. */
101
+ trialStart?: string;
102
+ /** Trial end date (ISO string). Set when subscription is in trial. */
103
+ trialEnd?: string;
104
+ /** When the subscription was canceled (ISO string). Soft-delete marker. */
105
+ canceledAt?: string;
106
+ /** Dunning state: 'none', 'notified', 'warning', 'final', 'suspended'. */
107
+ dunningState?: string;
108
+ /** Whether this subscription uses per-seat pricing. */
109
+ seatPricingEnabled?: boolean;
110
+ /** Current billable seat count. */
111
+ currentSeatCount?: number;
112
+ createdAt: string;
113
+ updatedAt: string;
114
+ plan?: {
115
+ _id: string;
116
+ name: string;
117
+ slug: string;
118
+ description?: string;
119
+ /** Stripe currency code (e.g. 'usd', 'inr', 'eur'). */
120
+ currency?: string;
121
+ };
122
+ }
123
+ interface ISubscriptionItem {
124
+ _id: string;
125
+ type: 'feature' | 'limit' | 'quota';
126
+ name: string;
127
+ slug: string;
128
+ description?: string;
129
+ category: string;
130
+ }
131
+ /** Per-interval quota value (plan-group/versions and public plans schema). */
132
+ interface IQuotaIntervalValue {
133
+ included: number;
134
+ /** Overage price in cents. Omitted in public plans; use pricingVariant.quotaOverages for display. */
135
+ overage?: number;
136
+ /** Stripe price ID for overage. Omitted in public plans; use pricingVariant.quotaOveragePriceIds. */
137
+ priceId?: string;
138
+ /** Unit size for overage pricing (e.g. 1000 = price per 1000 units). */
139
+ unitSize?: number;
140
+ }
141
+ /** Quota defined per billing interval (new plan-group/versions schema) */
142
+ interface IQuotaByInterval {
143
+ /** Whether over-usage beyond included is allowed (billed as overage). When false, usage is hard-capped at included amount. Default true. */
144
+ allowOverage?: boolean;
145
+ monthly?: IQuotaIntervalValue;
146
+ yearly?: IQuotaIntervalValue;
147
+ quarterly?: IQuotaIntervalValue;
148
+ }
149
+ /** Base pricing per interval. Values are often in cents (Stripe); convert for display. */
150
+ interface IBasePricing {
151
+ monthly: number;
152
+ yearly: number;
153
+ quarterly: number;
154
+ }
155
+ /** Stripe price IDs per billing interval (for a single currency variant). */
156
+ interface IStripePricesByInterval {
157
+ monthlyPriceId?: string;
158
+ yearlyPriceId?: string;
159
+ quarterlyPriceId?: string;
160
+ monthly?: string;
161
+ yearly?: string;
162
+ }
163
+ /** Overage amounts in cents per interval, keyed by quota slug. Used in pricing variants. */
164
+ type IQuotaOveragesByInterval = Record<string, {
165
+ monthly?: number;
166
+ yearly?: number;
167
+ quarterly?: number;
168
+ }>;
169
+ /** Overage Stripe price IDs per interval, keyed by quota slug. Used in pricing variants. */
170
+ type IQuotaOveragePriceIdsByInterval = Record<string, {
171
+ monthly?: string;
172
+ yearly?: string;
173
+ quarterly?: string;
174
+ }>;
175
+ /**
176
+ * Multi-currency pricing variant at plan version level.
177
+ * Each plan version can have multiple variants (e.g. usd, eur, inr, sgd).
178
+ */
179
+ interface IPricingVariant {
180
+ _id: string;
181
+ currency: string;
182
+ basePricing: IBasePricing;
183
+ stripePrices: IStripePricesByInterval;
184
+ /** Per-seat pricing config. When enabled, a second recurring item is on the subscription. */
185
+ seatPricing?: {
186
+ enabled: boolean;
187
+ includedSeats: number;
188
+ /** Maximum seats allowed. 0 or undefined = unlimited. */
189
+ maxSeats?: number;
190
+ perSeat: IBasePricing;
191
+ };
192
+ /** Stripe Price IDs for the per-seat recurring price. */
193
+ seatStripePrices?: IStripePricesByInterval;
194
+ /** Overage cents per quota slug per interval. */
195
+ quotaOverages?: IQuotaOveragesByInterval;
196
+ /** Stripe price IDs for overage per quota slug per interval. */
197
+ quotaOveragePriceIds?: IQuotaOveragePriceIdsByInterval;
198
+ }
199
+ interface IPlanVersion {
200
+ _id: string;
201
+ version: number;
202
+ name: string;
203
+ status: 'draft' | 'published';
204
+ features?: Record<string, boolean>;
205
+ limits?: Record<string, number>;
206
+ /** Per-interval quotas (included, unitSize; overage from pricingVariant.quotaOverages). */
207
+ quotas?: Record<string, IQuotaByInterval>;
208
+ /** Multi-currency pricing. Each variant has currency, basePricing, stripePrices, quotaOverages. */
209
+ pricingVariants?: IPricingVariant[];
210
+ subscriptionItems?: ISubscriptionItem[];
211
+ /** Trial configuration. When enabled, users can start a free trial of this plan. */
212
+ trial?: {
213
+ enabled: boolean;
214
+ durationDays: number;
215
+ requireCard: boolean;
216
+ };
217
+ /** Credit grant configuration. When enabled, credits are granted to workspaces on this plan. */
218
+ creditGrant?: {
219
+ enabled: boolean;
220
+ /** Linked credit package (populated with name, slug, creditAmount). */
221
+ creditPackage?: {
222
+ _id: string;
223
+ name: string;
224
+ slug: string;
225
+ creditAmount: number;
226
+ } | string;
227
+ /** How unused plan credits are handled on renewal: 'reset' = expire old, 'topup' = add to existing. */
228
+ mode: 'reset' | 'topup';
229
+ /** true = credits given fresh every month, false = one-time lifetime grant (default). */
230
+ renewOnPeriod?: boolean;
231
+ };
232
+ isCurrent?: boolean;
233
+ isLegacy?: boolean;
234
+ archived?: boolean;
235
+ deleted?: boolean;
236
+ createdAt?: string;
237
+ updatedAt?: string;
238
+ id?: string;
239
+ stripeProductId?: string;
240
+ }
241
+ /** Plan version summary (e.g. plan.latestVersion from subscription API) with subscriptionItems as IDs. */
242
+ interface IPlanVersionSummary extends Omit<IPlanVersion, 'subscriptionItems'> {
243
+ subscriptionItems?: string[];
244
+ }
245
+ interface IPlan {
246
+ _id: string;
247
+ name: string;
248
+ slug: string;
249
+ description?: string;
250
+ /** Stripe currency code (e.g. 'usd', 'inr', 'eur'). Used for pricing display. */
251
+ currency?: string;
252
+ /** Freemium plan: $0 base pricing, no seat billing, no trial. */
253
+ isFreemium?: boolean;
254
+ latestVersion?: IPlanVersionSummary;
255
+ archived?: boolean;
256
+ deleted?: boolean;
257
+ createdAt?: string;
258
+ updatedAt?: string;
259
+ id?: string;
260
+ }
261
+ interface IPlanGroupLatestVersion {
262
+ _id: string;
263
+ version: number;
264
+ planVersionIds: string[];
265
+ requiredItems: string[];
266
+ status: 'draft' | 'published';
267
+ isCurrent?: boolean;
268
+ isLegacy?: boolean;
269
+ archived?: boolean;
270
+ deleted?: boolean;
271
+ createdAt?: string;
272
+ updatedAt?: string;
273
+ description?: string;
274
+ }
275
+ interface IPlanGroup {
276
+ _id: string;
277
+ name: string;
278
+ slug: string;
279
+ description?: string;
280
+ latestVersion?: IPlanGroupLatestVersion;
281
+ archived?: boolean;
282
+ deleted?: boolean;
283
+ createdAt?: string;
284
+ updatedAt?: string;
285
+ id?: string;
286
+ }
287
+ interface IPlanGroupVersion {
288
+ _id: string;
289
+ version: number;
290
+ description?: string;
291
+ group?: {
292
+ _id: string;
293
+ name: string;
294
+ description?: string;
295
+ };
296
+ planVersionIds: IPlanVersionWithPlan[] | string[];
297
+ requiredItems?: string[];
298
+ status?: 'draft' | 'published';
299
+ isCurrent?: boolean;
300
+ isLegacy?: boolean;
301
+ archived?: boolean;
302
+ deleted?: boolean;
303
+ createdAt?: string;
304
+ updatedAt?: string;
305
+ id?: string;
306
+ }
307
+ interface ISubscriptionResponse {
308
+ subscription: ISubscription | null;
309
+ planVersion: IPlanVersion | null;
310
+ plan: IPlan | null;
311
+ group: IPlanGroup | null;
312
+ groupVersion: IPlanGroupVersion | null;
313
+ }
314
+ /** Plan version with nested plan info (name, slug, currency for display). */
315
+ interface IPlanVersionWithPlan extends IPlanVersion {
316
+ plan: IPlan;
317
+ }
318
+ /**
319
+ * Plan group version with full plan versions (for GET .../plan-group/versions).
320
+ * Each plan has plan, subscriptionItems, quotas (per-interval), pricingVariants.
321
+ */
322
+ interface IPlanGroupVersionWithPlans {
323
+ _id: string;
324
+ version: number;
325
+ description?: string;
326
+ /** Full plan versions with nested plan (name, slug, currency). */
327
+ plans: IPlanVersionWithPlan[];
328
+ isCurrent?: boolean;
329
+ whatsNew?: {
330
+ newPlans: IPlanVersionWithPlan[];
331
+ updatedPlans: IPlanVersionWithPlan[];
332
+ removedPlans: IPlanVersionWithPlan[];
333
+ };
334
+ }
335
+ interface IPlanGroupInfo {
336
+ _id: string;
337
+ name: string;
338
+ slug: string;
339
+ description?: string;
340
+ }
341
+ /** Response from GET workspaces/:id/subscription/plan-group (and by version). */
342
+ interface IPlanGroupResponse {
343
+ /** Plan group with latestVersion, archived, deleted, timestamps. May be null in some API responses. */
344
+ group: IPlanGroup | null;
345
+ /** Current group version with populated planVersionIds (or IDs). */
346
+ groupVersion: IPlanGroupVersion;
347
+ /** Full plan versions for display (subscriptionItems, pricingVariants, quotas). */
348
+ plans: IPlanVersionWithPlan[];
349
+ }
350
+ /**
351
+ * Response from GET workspaces/:workspaceId/subscription/plan-group/versions.
352
+ * Group summary plus current and available group versions; each version has plans with
353
+ * per-interval quotas and pricingVariants.
354
+ */
355
+ interface IPlanGroupVersionsResponse {
356
+ /** Plan group summary (_id, name, slug). */
357
+ group: IPlanGroupInfo;
358
+ /** Current group version (user's version when subscribed, or latest published when not). */
359
+ currentVersion: IPlanGroupVersionWithPlans;
360
+ /** Newer versions when user has subscription; empty when no subscription. */
361
+ availableVersions: IPlanGroupVersionWithPlans[];
362
+ }
363
+ /**
364
+ * Optional Stripe-level overrides forwarded to the checkout session.
365
+ * Use this to pass affiliate/referral tracking data or other Stripe parameters
366
+ * that should be set on the checkout session or resulting subscription.
367
+ */
368
+ interface ICheckoutStripeOptions {
369
+ /** Custom metadata merged into the Stripe checkout session metadata. */
370
+ metadata?: Record<string, string>;
371
+ /**
372
+ * Stripe `client_reference_id` — most affiliate platforms (Rewardful,
373
+ * FirstPromoter, PartnerStack, etc.) read this field to attribute conversions.
374
+ */
375
+ clientReferenceId?: string;
376
+ /** Custom metadata merged into `subscription_data.metadata` on the Stripe session. */
377
+ subscriptionMetadata?: Record<string, string>;
378
+ }
379
+ /** Request body for POST .../workspaces/:id/subscription/checkout. */
380
+ interface ICheckoutSessionRequest {
381
+ planVersionId: string;
382
+ billingInterval?: BillingInterval;
383
+ currency?: string;
384
+ successUrl?: string;
385
+ cancelUrl?: string;
386
+ /** Stripe-level overrides for affiliate tracking, referral IDs, etc. */
387
+ stripeOptions?: ICheckoutStripeOptions;
388
+ }
389
+ interface ICheckoutSessionResponse {
390
+ /** Response type discriminator. Added for centralized checkout flow. */
391
+ type?: 'checkout' | 'trial_started' | 'existing';
392
+ success: boolean;
393
+ checkoutUrl: string;
394
+ sessionId: string;
395
+ message: string;
396
+ planVersion?: {
397
+ _id: string;
398
+ version: number;
399
+ name: string;
400
+ };
401
+ }
402
+ /** No-card trial started server-side; no redirect needed. */
403
+ interface ICheckoutTrialResult {
404
+ type: 'trial_started';
405
+ success: boolean;
406
+ checkoutUrl: null;
407
+ sessionId: null;
408
+ subscription: ISubscription;
409
+ message: string;
410
+ }
411
+ /** Workspace already has a matching active subscription. */
412
+ interface ICheckoutExistingResult {
413
+ type: 'existing';
414
+ success: boolean;
415
+ checkoutUrl: null;
416
+ sessionId: null;
417
+ message: string;
418
+ existingSubscription?: {
419
+ _id: string;
420
+ subscriptionStatus: string;
421
+ stripePriceId?: string;
422
+ };
423
+ }
424
+ /**
425
+ * Discriminated union for POST /subscription/checkout responses.
426
+ * - `checkout`: Stripe checkout session created, redirect user to checkoutUrl
427
+ * - `trial_started`: No-card trial started server-side, no redirect needed
428
+ * - `existing`: Workspace already has a matching subscription
429
+ */
430
+ type CheckoutResult = (ICheckoutSessionResponse & {
431
+ type: 'checkout';
432
+ }) | ICheckoutTrialResult | ICheckoutExistingResult;
433
+ /** Request body for PATCH .../workspaces/:id/subscription. Only these fields are allowed. */
434
+ interface ISubscriptionUpdateRequest {
435
+ planVersionId: string;
436
+ billingInterval?: BillingInterval;
437
+ successUrl?: string;
438
+ cancelUrl?: string;
439
+ }
440
+ interface ISubscriptionUpdateResponse {
441
+ _id: string;
442
+ subscriptionStatus: string;
443
+ workspace: string;
444
+ planVersion: string;
445
+ plan: string;
446
+ planGroup?: string;
447
+ planGroupVersion?: string;
448
+ cancelAtPeriodEnd: boolean;
449
+ createdAt: string;
450
+ updatedAt: string;
451
+ }
452
+ interface IPublicPlanItemCategory {
453
+ name: string;
454
+ slug: string;
455
+ }
456
+ interface IPublicPlanItem {
457
+ _id: string;
458
+ name: string;
459
+ slug: string;
460
+ description?: string;
461
+ type: 'feature' | 'limit' | 'quota';
462
+ category: IPublicPlanItemCategory;
463
+ }
464
+ /**
465
+ * Public plan version (e.g. from GET /api/v1/public/:orgId/plans/:slug).
466
+ * Each plan has _id, name (plan display name), version, status, pricingVariants, quotas, features, limits.
467
+ * Pricing is in cents (see response.notes).
468
+ */
469
+ interface IPublicPlanVersion {
470
+ _id: string;
471
+ /** Plan display name (e.g. "Pro", "Base Plan"). */
472
+ name: string;
473
+ /** Whether this is a free ($0) plan with no seat billing or trial. */
474
+ isFreemium: boolean;
475
+ version: number;
476
+ status: 'draft' | 'published';
477
+ /** Multi-currency pricing. Use getBasePriceCents(plan, currency, interval) and getQuotaDisplayWithVariant for display. */
478
+ pricingVariants?: IPricingVariant[];
479
+ /** Keyed by item slug. Per-interval: included, unitSize; overage from pricingVariant.quotaOverages. */
480
+ quotas: Record<string, IQuotaByInterval>;
481
+ features: Record<string, boolean>;
482
+ limits: Record<string, number>;
483
+ /** Trial config. Only present when the plan has trials enabled. */
484
+ trial?: {
485
+ enabled: boolean;
486
+ durationDays: number;
487
+ requireCard: boolean;
488
+ };
489
+ /** Credit grant config. Only present when the plan grants credits. */
490
+ creditGrant?: {
491
+ enabled: boolean;
492
+ creditAmount: number | null;
493
+ packageName: string | null;
494
+ mode: 'reset' | 'topup';
495
+ /** true = credits given fresh every month, false = one-time lifetime grant. */
496
+ renewOnPeriod: boolean;
497
+ };
498
+ }
499
+ interface IPublicPlansResponse {
500
+ items: IPublicPlanItem[];
501
+ plans: IPublicPlanVersion[];
502
+ /** Optional note from API (e.g. "Pricing is in cents. Please convert to dollars for display."). */
503
+ notes?: string;
504
+ }
505
+ type InvoiceStatus = 'draft' | 'open' | 'paid' | 'uncollectible' | 'void';
506
+ interface IInvoice {
507
+ id: string;
508
+ amount_due: number;
509
+ number: string | null;
510
+ amount_paid: number;
511
+ currency: string;
512
+ status: InvoiceStatus;
513
+ created: number;
514
+ due_date: number | null;
515
+ hosted_invoice_url: string;
516
+ invoice_pdf: string | null;
517
+ description: string | null;
518
+ subscription: string;
519
+ }
520
+ interface IInvoiceListResponse {
521
+ invoices: IInvoice[];
522
+ has_more: boolean;
523
+ }
524
+ interface IInvoiceResponse {
525
+ invoice: IInvoice;
526
+ }
527
+ /** Request body for POST .../workspaces/:id/subscription/usage */
528
+ interface IRecordUsageRequest {
529
+ quotaSlug: string;
530
+ quantity: number;
531
+ metadata?: Record<string, unknown>;
532
+ source?: string;
533
+ idempotencyKey?: string;
534
+ }
535
+ /** Response from POST .../workspaces/:id/subscription/usage */
536
+ interface IRecordUsageResponse {
537
+ used: number;
538
+ consumed: number;
539
+ included: number;
540
+ available: number;
541
+ overage: number;
542
+ billedAsync: boolean;
543
+ }
544
+ /** Single quota usage status (shared between status and all endpoints). */
545
+ interface IQuotaUsageStatus {
546
+ consumed: number;
547
+ included: number;
548
+ available: number;
549
+ overage: number;
550
+ hasOverage: boolean;
551
+ /** Whether over-usage is allowed (billed as overage). When false, usage is hard-capped. Default true. */
552
+ allowOverage?: boolean;
553
+ }
554
+ /** Response from GET .../workspaces/:id/subscription/usage/status?quotaSlug=X */
555
+ interface IQuotaUsageStatusResponse extends IQuotaUsageStatus {
556
+ quotaSlug: string;
557
+ }
558
+ /** Response from GET .../workspaces/:id/subscription/usage/all */
559
+ interface IAllQuotaUsageResponse {
560
+ quotas: Record<string, IQuotaUsageStatus>;
561
+ }
562
+ /** Single usage log entry from GET .../usage/logs */
563
+ interface IUsageLogEntry {
564
+ _id: string;
565
+ quotaSlug: string;
566
+ quantity: number;
567
+ source?: string;
568
+ workspace: string;
569
+ createdAt: string;
570
+ updatedAt: string;
571
+ }
572
+ /** Query parameters for GET .../workspaces/:id/subscription/usage/logs */
573
+ interface IUsageLogsQuery {
574
+ quotaSlug?: string;
575
+ from?: string;
576
+ to?: string;
577
+ source?: string;
578
+ page?: number;
579
+ limit?: number;
580
+ }
581
+ /** Paginated response from GET .../workspaces/:id/subscription/usage/logs */
582
+ interface IUsageLogsResponse {
583
+ docs: IUsageLogEntry[];
584
+ totalDocs: number;
585
+ limit: number;
586
+ page: number;
587
+ totalPages: number;
588
+ hasNextPage: boolean;
589
+ hasPrevPage: boolean;
590
+ }
591
+ /** Credit bucket source (how credits entered the workspace) */
592
+ declare const CreditBucketSource: {
593
+ readonly PlanGrant: "plan_grant";
594
+ readonly CreditPackPurchase: "credit_pack_purchase";
595
+ readonly AdminGrant: "admin_grant";
596
+ readonly Refund: "refund";
597
+ };
598
+ type CreditBucketSourceType = (typeof CreditBucketSource)[keyof typeof CreditBucketSource];
599
+ /** Credit bucket status */
600
+ declare const CreditBucketStatus: {
601
+ readonly Pending: "pending";
602
+ readonly Active: "active";
603
+ readonly Expired: "expired";
604
+ readonly Consumed: "consumed";
605
+ };
606
+ type CreditBucketStatusType = (typeof CreditBucketStatus)[keyof typeof CreditBucketStatus];
607
+ /** Credit transaction type */
608
+ declare const CreditTransactionType: {
609
+ readonly PlanGrant: "plan_grant";
610
+ readonly PackPurchased: "pack_purchased";
611
+ readonly Consumed: "consumed";
612
+ readonly Expired: "expired";
613
+ readonly AdminGrant: "admin_grant";
614
+ readonly AdminRevoke: "admin_revoke";
615
+ readonly Refund: "refund";
616
+ };
617
+ type CreditTransactionTypeValue = (typeof CreditTransactionType)[keyof typeof CreditTransactionType];
618
+ /** Credit balance for a workspace */
619
+ interface ICreditBalance {
620
+ available: number;
621
+ totalGranted: number;
622
+ totalConsumed: number;
623
+ totalExpired: number;
624
+ totalRefunded: number;
625
+ }
626
+ /** Pricing variant for a credit package */
627
+ interface ICreditPackagePricingVariant {
628
+ currency: string;
629
+ /** Price in smallest currency unit (cents) */
630
+ amount: number;
631
+ stripePriceId?: string;
632
+ }
633
+ /** Admin-defined purchasable credit package */
634
+ interface ICreditPackage extends IDocument {
635
+ name: string;
636
+ slug: string;
637
+ description?: string;
638
+ creditAmount: number;
639
+ pricingVariants: ICreditPackagePricingVariant[];
640
+ validityDays?: number;
641
+ isActive: boolean;
642
+ sortOrder: number;
643
+ archived: boolean;
644
+ }
645
+ /** A single credit transaction (user-facing event history) */
646
+ interface ICreditTransaction extends IDocument {
647
+ workspace: string;
648
+ type: CreditTransactionTypeValue;
649
+ /** Positive for grants, negative for consume/expire/revoke */
650
+ amount: number;
651
+ balanceAfter: number;
652
+ description?: string;
653
+ bucket?: string;
654
+ creditPackage?: string;
655
+ actor?: string;
656
+ metadata?: Record<string, any>;
657
+ }
658
+ /** A credit bucket (per-grant allocation with expiry) */
659
+ interface ICreditBucket extends IDocument {
660
+ workspace: string;
661
+ source: CreditBucketSourceType;
662
+ status: CreditBucketStatusType;
663
+ creditAmount: number;
664
+ remaining: number;
665
+ expiresAt?: string;
666
+ activatedAt?: string;
667
+ creditPackage?: string | ICreditPackage;
668
+ grantedBy?: string;
669
+ metadata?: Record<string, any>;
670
+ }
671
+ /** Request body for POST .../credits/consume */
672
+ interface IConsumeCreditsRequest {
673
+ amount: number;
674
+ description?: string;
675
+ idempotencyKey?: string;
676
+ metadata?: Record<string, any>;
677
+ }
678
+ /** Response from POST .../credits/consume */
679
+ interface IConsumeCreditsResponse {
680
+ success: boolean;
681
+ consumed: number;
682
+ balanceAfter: number;
683
+ }
684
+ /** Request body for POST .../credits/purchase */
685
+ interface ICreditPurchaseRequest {
686
+ creditPackageId: string;
687
+ currency?: string;
688
+ successUrl: string;
689
+ cancelUrl: string;
690
+ }
691
+ /** Response from POST .../credits/purchase */
692
+ interface ICreditPurchaseResponse {
693
+ sessionId: string;
694
+ url: string;
695
+ }
696
+ /** Query params for GET .../credits/transactions */
697
+ interface ICreditTransactionsQuery {
698
+ type?: CreditTransactionTypeValue;
699
+ page?: number;
700
+ limit?: number;
701
+ }
702
+ /** Paginated response from GET .../credits/transactions */
703
+ interface ICreditTransactionsResponse {
704
+ docs: ICreditTransaction[];
705
+ totalDocs: number;
706
+ limit: number;
707
+ page: number;
708
+ totalPages: number;
709
+ hasNextPage: boolean;
710
+ hasPrevPage: boolean;
711
+ }
712
+ /** Query params for GET .../credits/buckets */
713
+ interface ICreditBucketsQuery {
714
+ status?: CreditBucketStatusType;
715
+ source?: CreditBucketSourceType;
716
+ page?: number;
717
+ limit?: number;
718
+ }
719
+ /** Paginated response from GET .../credits/buckets */
720
+ interface ICreditBucketsResponse {
721
+ docs: ICreditBucket[];
722
+ totalDocs: number;
723
+ limit: number;
724
+ page: number;
725
+ totalPages: number;
726
+ hasNextPage: boolean;
727
+ hasPrevPage: boolean;
728
+ }
729
+ /** Response from GET .../credits/expiring */
730
+ interface IExpiringCreditsResponse {
731
+ days: number;
732
+ expiringCredits: number;
733
+ buckets: ICreditBucket[];
734
+ }
735
+ /** Public credit package (from public endpoint, no auth) */
736
+ interface IPublicCreditPackage {
737
+ _id: string;
738
+ name: string;
739
+ slug: string;
740
+ description: string;
741
+ creditAmount: number;
742
+ pricingVariants: ICreditPackagePricingVariant[];
743
+ validityDays: number | null;
744
+ sortOrder: number;
745
+ }
746
+ /** Response from GET /:orgId/credit-packages (public, no auth) */
747
+ interface IPublicCreditPackagesResponse {
748
+ packages: IPublicCreditPackage[];
749
+ notes?: string;
750
+ }
751
+
752
+ interface IWorkspace {
753
+ _id: string;
754
+ name: string;
755
+ image?: string;
756
+ workspaceId: string;
757
+ users: IUser[];
758
+ roles: string[];
759
+ createdBy: string | IUser;
760
+ features: Record<string, boolean>;
761
+ /**
762
+ * Quota usage tracking: { [quotaSlug]: number } – how much of each quota has been used.
763
+ */
764
+ quotas?: Record<string, number>;
765
+ /**
766
+ * Subscription limits snapshot: { [limitSlug]: number | null } – synced from subscription plan.
767
+ * Limits are maximum values (e.g. max-users, max-workspaces). Updated when subscription is assigned/updated.
768
+ */
769
+ limits?: Record<string, number | null>;
770
+ subscription?: ISubscription | string | null;
771
+ /** Stripe Customer ID for this workspace. */
772
+ stripeCustomerId?: string;
773
+ /**
774
+ * Billing currency locked for this workspace (set on first subscription).
775
+ * Stripe allows one currency per customer; all future subscriptions must use this currency.
776
+ * When set, subscription UI only shows/uses this currency.
777
+ */
778
+ billingCurrency?: string | null;
779
+ /** Per-workspace permission overrides. Takes priority over org-level settings.permissions. */
780
+ permissions?: Record<string, string[]>;
781
+ /** Set when workspace first uses a trial. Blocks trial from being used again on the same workspace. */
782
+ trialUsedAt?: string | null;
783
+ }
784
+ interface IWorkspaceFeature {
785
+ _id: string;
786
+ name: string;
787
+ description: string;
788
+ userManaged: boolean;
789
+ defaultValue: boolean;
790
+ slug: string;
791
+ category: string;
792
+ createdAt: Date;
793
+ updatedAt: Date;
794
+ }
795
+ interface IWorkspaceUser {
796
+ _id: string;
797
+ workspace: string | IWorkspace;
798
+ user: string | IUser;
799
+ role: string;
800
+ }
801
+
802
+ type WorkspaceMode = 'personal' | 'platform';
803
+ interface ISettings {
804
+ workspace: {
805
+ roles: string[];
806
+ defaultRole: string;
807
+ maxWorkspaces: number;
808
+ maxWorkspaceUsers: number;
809
+ /** Workspace mode: 'personal' (solo) or 'platform' (multi-user, default) */
810
+ mode: WorkspaceMode;
811
+ /** Whether users can create workspaces. false = disabled, 'owner-only' = restricted */
812
+ canCreateWorkspace: boolean | 'owner-only';
813
+ /** Whether members can invite others. false = disabled, 'admin-only' = restricted */
814
+ canInviteMembers: boolean | 'admin-only';
815
+ /** Custom role→permission mapping. Overrides SDK defaults when provided by backend. */
816
+ permissions?: Record<string, string[]>;
817
+ /** Show workspace switcher in the UI */
818
+ showSwitcher: boolean;
819
+ /** Max workspaces a user can own. 0 = unlimited */
820
+ maxWorkspacesPerUser: number;
821
+ /** Auto-create workspace on first login */
822
+ autoCreateFirst: boolean;
823
+ };
824
+ [key: string]: any;
825
+ }
826
+
827
+ /** Data passed to a notification template for merge tag replacement. */
828
+ interface NotificationData {
829
+ /** Push notification title. Falls back to the event name if not provided. */
830
+ title?: string;
831
+ /** Primary message — used in email body and as push notification body. */
832
+ message?: string;
833
+ /** Custom icon URL for the push notification. Falls back to the org icon. */
834
+ icon?: string;
835
+ /** Large image URL displayed in the push notification body. */
836
+ image?: string;
837
+ /** Small monochrome icon for the status bar (Android/ChromeOS). */
838
+ badge?: string;
839
+ /** URL to open when the user clicks the push notification. Also available as {{url}} in email template. */
840
+ url?: string;
841
+ /** Tag to group/replace notifications. New notification with same tag replaces the previous one instead of stacking. */
842
+ tag?: string;
843
+ /** Action buttons displayed on the notification (max 2). */
844
+ actions?: Array<{
845
+ action: string;
846
+ title: string;
847
+ icon?: string;
848
+ }>;
849
+ /** Show notification without sound or vibration. */
850
+ silent?: boolean;
851
+ /** Keep notification visible until user interacts (no auto-dismiss). Useful for critical alerts. */
852
+ requireInteraction?: boolean;
853
+ /** Vibrate/sound again when replacing a notification with the same tag. Only works with `tag`. */
854
+ renotify?: boolean;
855
+ /** Custom timestamp (ms since epoch) displayed on the notification. */
856
+ timestamp?: number;
857
+ /** Text direction for title/body. */
858
+ dir?: 'ltr' | 'rtl' | 'auto';
859
+ /** Time-to-live in seconds. Push service discards the message if not delivered within this time. Default: 86400 (24h). */
860
+ ttl?: number;
861
+ /** Delivery urgency hint. Affects battery/delivery priority on mobile. */
862
+ urgency?: 'very-low' | 'low' | 'normal' | 'high';
863
+ /** ISO 8601 date string. Delays delivery until the specified time. */
864
+ scheduledAt?: string;
865
+ /**
866
+ * Which channels to send on. Overrides the event's default channel config.
867
+ * Omit to use the event's configured channels.
868
+ *
869
+ * @example
870
+ * ```ts
871
+ * // Only push, no email
872
+ * { channels: { push: true } }
873
+ *
874
+ * // Only email, no push
875
+ * { channels: { email: true } }
876
+ * ```
877
+ */
878
+ channels?: {
879
+ email?: boolean;
880
+ push?: boolean;
881
+ };
882
+ /** Any additional merge tags available as {{key}} in the email template. */
883
+ [key: string]: any;
884
+ }
885
+ /** Result of sending a notification. */
886
+ interface NotificationResult {
887
+ sent: boolean;
888
+ /** Which channels were actually used. false = blocked by settings or missing template. */
889
+ channels: {
890
+ email: boolean;
891
+ push: boolean;
892
+ };
893
+ /** Number of users notified. 1 for single user, N for whole workspace. */
894
+ notifiedCount?: number;
895
+ /** Reason if not sent (e.g., 'event_disabled'). Only present when sent=false. */
896
+ reason?: string;
897
+ }
898
+
899
+ interface WorkspaceActions {
900
+ list(): Promise<IWorkspace[]>;
901
+ get(workspaceId: string): Promise<IWorkspace>;
902
+ create(data: {
903
+ name: string;
904
+ image?: string;
905
+ }): Promise<IWorkspace>;
906
+ update(workspaceId: string, data: Partial<IWorkspace>): Promise<IWorkspace>;
907
+ delete(workspaceId: string): Promise<{
908
+ success: boolean;
909
+ }>;
910
+ }
911
+ interface UserActions {
912
+ list(workspaceId: string): Promise<IWorkspaceUser[]>;
913
+ invite(workspaceId: string, email: string, role: string): Promise<{
914
+ userId: string;
915
+ workspace: IWorkspace;
916
+ message: string;
917
+ }>;
918
+ remove(workspaceId: string, userId: string): Promise<{
919
+ userId: string;
920
+ workspace: IWorkspace;
921
+ message: string;
922
+ }>;
923
+ updateRole(workspaceId: string, userId: string, role: string): Promise<{
924
+ userId: string;
925
+ workspace: IWorkspace;
926
+ message: string;
927
+ }>;
928
+ getProfile(): Promise<IUser>;
929
+ updateProfile(data: Partial<IUser>): Promise<IUser>;
930
+ }
931
+ interface SubscriptionActions {
932
+ get(workspaceId: string): Promise<ISubscriptionResponse>;
933
+ checkout(workspaceId: string, request: ICheckoutSessionRequest): Promise<CheckoutResult | ICheckoutSessionResponse>;
934
+ update(workspaceId: string, request: ISubscriptionUpdateRequest): Promise<ISubscriptionUpdateResponse | ICheckoutSessionResponse>;
935
+ cancel(workspaceId: string): Promise<ISubscriptionResponse>;
936
+ resume(workspaceId: string): Promise<ISubscriptionResponse>;
937
+ getBillingPortalUrl(workspaceId: string, returnUrl?: string): Promise<{
938
+ url: string;
939
+ }>;
940
+ }
941
+ interface PlanActions {
942
+ getGroup(workspaceId: string): Promise<IPlanGroupResponse>;
943
+ getVersions(workspaceId: string): Promise<IPlanGroupVersionsResponse>;
944
+ /** No auth required */
945
+ getPublic(slug: string): Promise<IPublicPlansResponse>;
946
+ /** No auth required */
947
+ getVersion(groupVersionId: string): Promise<IPlanGroupVersion>;
948
+ }
949
+ interface InvoiceActions {
950
+ list(workspaceId: string, limit?: number, startingAfter?: string): Promise<IInvoiceListResponse>;
951
+ get(workspaceId: string, invoiceId: string): Promise<IInvoiceResponse>;
952
+ }
953
+ interface UsageBatchRequest {
954
+ items: Array<{
955
+ quotaSlug: string;
956
+ quantity: number;
957
+ metadata?: Record<string, any>;
958
+ source?: string;
959
+ idempotencyKey?: string;
960
+ }>;
961
+ }
962
+ interface UsageBatchResponse {
963
+ success: boolean;
964
+ total: number;
965
+ succeeded: number;
966
+ failed: number;
967
+ results: Array<{
968
+ success: boolean;
969
+ quotaSlug: string;
970
+ quantity: number;
971
+ error?: string;
972
+ }>;
973
+ }
974
+ interface UsageActions {
975
+ record(workspaceId: string, request: IRecordUsageRequest): Promise<IRecordUsageResponse>;
976
+ /** Record multiple usage entries in one request. Max 100 items. For bulk/batch operations. */
977
+ recordBatch(workspaceId: string, request: UsageBatchRequest): Promise<UsageBatchResponse>;
978
+ getQuota(workspaceId: string, quotaSlug: string): Promise<IQuotaUsageStatusResponse>;
979
+ getAll(workspaceId: string): Promise<IAllQuotaUsageResponse>;
980
+ getLogs(workspaceId: string, query?: IUsageLogsQuery): Promise<IUsageLogsResponse>;
981
+ }
982
+ interface SettingsActions {
983
+ get(): Promise<ISettings>;
984
+ }
985
+ interface FeatureActions {
986
+ list(): Promise<IWorkspaceFeature[]>;
987
+ update(workspaceId: string, key: string, value: boolean): Promise<IWorkspace>;
988
+ }
989
+ interface PermissionActions {
990
+ /** Check if a user has a permission (or all of an array) in a workspace. Works with both platform permissions (Permission.*) and app permissions (custom strings). */
991
+ check(workspaceId: string, userId: string, permission: string | string[]): Promise<boolean>;
992
+ /** Resolve all permissions for a user in a workspace. Returns both platform and app permissions. */
993
+ resolve(workspaceId: string, userId: string): Promise<Set<string>>;
994
+ }
995
+ interface NotificationActions {
996
+ /**
997
+ * Send a notification to a user or all workspace members.
998
+ * Respects all notification gates (org settings, event config, workspace preferences).
999
+ *
1000
+ * @param workspaceId - The workspace context
1001
+ * @param event - The event slug (e.g., 'comment_added')
1002
+ * @param userId - The user to notify. Omit to notify all workspace members.
1003
+ * @param data - Template merge data. `message` is used as push body.
1004
+ *
1005
+ * @example
1006
+ * ```ts
1007
+ * // Notify one user
1008
+ * await notification.send(workspaceId, 'comment_added', userId, {
1009
+ * message: 'Alice commented on your project',
1010
+ * })
1011
+ *
1012
+ * // Notify all workspace members
1013
+ * await notification.send(workspaceId, 'new_release', undefined, {
1014
+ * message: 'Version 2.0 is now available!',
1015
+ * })
1016
+ * ```
1017
+ */
1018
+ send(workspaceId: string, event: string, userId?: string, data?: NotificationData): Promise<NotificationResult>;
1019
+ }
1020
+ interface CreditActions {
1021
+ /** Get workspace credit balance */
1022
+ getBalance(workspaceId: string): Promise<ICreditBalance>;
1023
+ /** Consume credits from workspace. Throws with code 'INSUFFICIENT_CREDITS' on 402. */
1024
+ consume(workspaceId: string, request: IConsumeCreditsRequest): Promise<IConsumeCreditsResponse>;
1025
+ /** Create Stripe checkout session for purchasing a credit package */
1026
+ purchase(workspaceId: string, request: ICreditPurchaseRequest): Promise<ICreditPurchaseResponse>;
1027
+ /** List available credit packages for purchase */
1028
+ getPackages(workspaceId: string): Promise<ICreditPackage[]>;
1029
+ /** Get paginated credit transaction history */
1030
+ getTransactions(workspaceId: string, query?: ICreditTransactionsQuery): Promise<ICreditTransactionsResponse>;
1031
+ /** Get paginated credit buckets */
1032
+ getBuckets(workspaceId: string, query?: ICreditBucketsQuery): Promise<ICreditBucketsResponse>;
1033
+ /** Get credits expiring within N days (default 7) */
1034
+ getExpiring(workspaceId: string, days?: number): Promise<IExpiringCreditsResponse>;
1035
+ /** Get credit packages publicly (no auth required) */
1036
+ getPublicPackages(): Promise<IPublicCreditPackagesResponse>;
1037
+ }
1038
+ /** All action modules bound to a specific session. Returned by `withSession()`. */
1039
+ interface ScopedActions {
1040
+ workspace: WorkspaceActions;
1041
+ users: UserActions;
1042
+ subscription: SubscriptionActions;
1043
+ plans: PlanActions;
1044
+ invoices: InvoiceActions;
1045
+ usage: UsageActions;
1046
+ settings: SettingsActions;
1047
+ features: FeatureActions;
1048
+ permissions: PermissionActions;
1049
+ notification: NotificationActions;
1050
+ credits: CreditActions;
1051
+ }
1052
+
1053
+ /**
1054
+ * MCP server toolkit (server-side, framework-agnostic).
1055
+ *
1056
+ * Turns a consuming app into a live MCP (Model Context Protocol) server so AI
1057
+ * agents can operate its BuildBase capabilities — workspaces, subscriptions,
1058
+ * quotas, credits, feature flags, permissions — plus any custom tools the app
1059
+ * defines. The transport is stateless Streamable HTTP: a single JSON-RPC
1060
+ * message per POST, no sessions and no SSE, which keeps the handler pure and
1061
+ * identical on Node 18+, edge, Deno, and Bun.
1062
+ *
1063
+ * Zero framework types: the core `handle()` takes a plain
1064
+ * `{ method, headers, body }` and returns `{ status, headers, body }` (wire it
1065
+ * into Express/Fastify/Hono yourself), while `fetch()` adapts Web-standard
1066
+ * `Request` → `Response` for Next.js App Router and edge runtimes.
1067
+ *
1068
+ * Agents authenticate with the Bearer tokens the app mints via the OAuth2
1069
+ * app-bridge (`handleAppTokenRequest` + `signClientJwt`); the `auth.verify`
1070
+ * callback maps a verified token to the BuildBase session the tools run under.
1071
+ *
1072
+ * @example Next.js App Router — the entire integration:
1073
+ * ```ts
1074
+ * // lib/mcp.ts
1075
+ * import BuildBase from '@buildbase/sdk';
1076
+ * import { createMcpHandler, verifyClientJwt } from '@buildbase/sdk/mcp';
1077
+ *
1078
+ * const buildbase = BuildBase({
1079
+ * serverUrl: process.env.BUILDBASE_URL!,
1080
+ * orgId: process.env.BUILDBASE_ORG_ID!,
1081
+ * });
1082
+ *
1083
+ * export const mcp = createMcpHandler({
1084
+ * buildbase,
1085
+ * serverInfo: { name: 'imejis', version: '1.0.0' },
1086
+ * auth: {
1087
+ * verify: (token) => {
1088
+ * const c = verifyClientJwt(token, process.env.BUILDBASE_CLIENT_SECRET!);
1089
+ * return { sessionId: String(c.sid), userId: String(c.sub), scopes: c.scope };
1090
+ * },
1091
+ * resourceMetadataUrl: 'https://imejis.io/.well-known/oauth-protected-resource',
1092
+ * },
1093
+ * });
1094
+ *
1095
+ * // app/api/mcp/route.ts
1096
+ * import { mcp } from '@/lib/mcp';
1097
+ * export const POST = (req: Request) => mcp.fetch(req);
1098
+ * export const GET = (req: Request) => mcp.fetch(req); // 405 per spec (no SSE)
1099
+ * export const DELETE = (req: Request) => mcp.fetch(req); // 405 (stateless)
1100
+ * ```
1101
+ */
1102
+
1103
+ /**
1104
+ * The slice of the `BuildBase()` client the MCP handler needs. Structural on
1105
+ * purpose (instead of the full `BuildBaseResult`) so the type stays assignable
1106
+ * across the SDK's separately-bundled entry points.
1107
+ */
1108
+ interface McpBuildBaseClient {
1109
+ withSession(sessionId: string): ScopedActions;
1110
+ }
1111
+ /** A transport-agnostic HTTP request (mirror of the DiscoveryDocument idea). */
1112
+ interface McpHttpRequest {
1113
+ /** HTTP method, e.g. `'POST'`. */
1114
+ method: string;
1115
+ /** Header map. Keys are matched case-insensitively. */
1116
+ headers: Record<string, string | undefined>;
1117
+ /** Raw JSON body string, or an already-parsed value (e.g. Express req.body). */
1118
+ body?: string | unknown;
1119
+ }
1120
+ /** A rendered HTTP response ready to hand to any framework. */
1121
+ interface McpHttpResponse {
1122
+ status: number;
1123
+ headers: Record<string, string>;
1124
+ body: string;
1125
+ }
1126
+ /** The identity a verified Bearer token resolves to. */
1127
+ interface McpAuthInfo {
1128
+ /** BuildBase session all tool calls run under (`buildbase.withSession(...)`). */
1129
+ sessionId: string;
1130
+ /** The acting BuildBase user id — default subject for permission checks. */
1131
+ userId?: string;
1132
+ /** Pin tools to one workspace; used when the agent omits `workspaceId`. */
1133
+ workspaceId?: string;
1134
+ /** OAuth scopes granted to the agent; filters tools with `requiredScopes`. */
1135
+ scopes?: string[];
1136
+ /** Raw verified claims, passed through to tool context. */
1137
+ claims?: Record<string, unknown>;
1138
+ }
1139
+ /** Context passed to every tool execution. */
1140
+ interface McpToolContext<TCustom = unknown> {
1141
+ /**
1142
+ * Session-scoped BuildBase actions (`workspace`, `usage`, `credits`, …).
1143
+ * Only usable when a `buildbase` client was configured — otherwise any
1144
+ * access throws a clear error (tools that don't touch BuildBase never
1145
+ * notice).
1146
+ */
1147
+ bb: ScopedActions;
1148
+ auth: McpAuthInfo;
1149
+ /** Default workspace (from `auth.workspaceId`), if any. */
1150
+ workspaceId?: string;
1151
+ /**
1152
+ * Whatever your `context` factory returned for this request — your own
1153
+ * database handles, services, request info. `undefined` when no factory is
1154
+ * configured.
1155
+ */
1156
+ custom: TCustom;
1157
+ }
1158
+ /** MCP tool annotations (behavior hints for agents). */
1159
+ interface McpToolAnnotations {
1160
+ title?: string;
1161
+ readOnlyHint?: boolean;
1162
+ destructiveHint?: boolean;
1163
+ idempotentHint?: boolean;
1164
+ openWorldHint?: boolean;
1165
+ }
1166
+ /** A tool exposed over MCP. Use {@link defineMcpTool} for inferred input types. */
1167
+ interface McpToolDefinition<S extends z.ZodType = z.ZodType, TCustom = any> {
1168
+ /** Tool name: `[a-zA-Z0-9_-]`, 1–128 chars. */
1169
+ name: string;
1170
+ description: string;
1171
+ /**
1172
+ * Input schema: a zod schema (validated, converted to JSON Schema for
1173
+ * `tools/list`) or a raw JSON Schema object (served as-is, not validated).
1174
+ */
1175
+ inputSchema: S | Record<string, unknown>;
1176
+ annotations?: McpToolAnnotations;
1177
+ /**
1178
+ * Scopes required to see/call this tool. The token must carry ALL of them
1179
+ * (`McpAuthInfo.scopes`) for the tool to be visible or callable; a token
1180
+ * with no scopes sees only tools that declare none. Built-in tools declare
1181
+ * no scopes and are governed by `builtinTools` + the user's own permissions.
1182
+ */
1183
+ requiredScopes?: string[];
1184
+ execute: (input: z.output<S>, ctx: McpToolContext<TCustom>) => unknown | Promise<unknown>;
1185
+ }
1186
+ /** Configuration for {@link createMcpHandler}. */
1187
+ interface CreateMcpHandlerConfig {
1188
+ /**
1189
+ * The `BuildBase()` instance the built-in tools run against (via
1190
+ * `withSession`). Optional — omit it to run a standalone MCP server with
1191
+ * only your own tools (built-ins are then disabled and `ctx.bb` throws a
1192
+ * clear error if a tool touches it).
1193
+ */
1194
+ buildbase?: McpBuildBaseClient;
1195
+ /** Advertised in `initialize`. Defaults to `buildbase-mcp`. */
1196
+ serverInfo?: {
1197
+ name: string;
1198
+ version: string;
1199
+ };
1200
+ /** Optional usage instructions surfaced to agents on `initialize`. */
1201
+ instructions?: string;
1202
+ /**
1203
+ * Per-request context factory for YOUR tools: whatever it returns (your
1204
+ * database, services, request info) is available as `ctx.custom` in every
1205
+ * `execute`. Runs once per `tools/call`, after auth.
1206
+ */
1207
+ context?: (auth: McpAuthInfo | null, req: McpHttpRequest) => unknown | Promise<unknown>;
1208
+ /**
1209
+ * Bearer-token verification. Return null to reject (401). Set `false` to
1210
+ * disable auth entirely — local development only.
1211
+ */
1212
+ auth: {
1213
+ verify: (token: string, req: McpHttpRequest) => McpAuthInfo | null | Promise<McpAuthInfo | null>;
1214
+ /** When set, 401s carry the RFC 9728 `WWW-Authenticate` challenge. */
1215
+ resourceMetadataUrl?: string;
1216
+ } | false;
1217
+ /**
1218
+ * App-defined tools. A custom tool with a built-in's name REPLACES the
1219
+ * built-in (your definition wins); duplicate custom names or invalid names
1220
+ * throw at create time.
1221
+ */
1222
+ tools?: McpToolDefinition<any, any>[];
1223
+ /**
1224
+ * Which built-in BuildBase tools to expose. **Defaults to `'readonly'`**
1225
+ * when a `buildbase` client is configured (`false` otherwise) — reads only,
1226
+ * so no agent can mutate, bill, or delete anything unless you opt in. Set
1227
+ * `'all'` to expose the full surface (reads + writes + destructive/billing
1228
+ * ops like workspace delete, subscription cancel, credit purchase); `false`
1229
+ * for none; or an `{ include, exclude }` selection to hand-pick. Every tool
1230
+ * still runs under the user's session, so the platform enforces the user's
1231
+ * real permissions on top — but least privilege starts here.
1232
+ */
1233
+ builtinTools?: 'all' | 'readonly' | false | {
1234
+ include?: BuiltinMcpToolName[];
1235
+ exclude?: BuiltinMcpToolName[];
1236
+ };
1237
+ /**
1238
+ * Allowed `Origin` header values (DNS-rebinding protection). When set, a
1239
+ * request with a non-matching Origin is rejected with 403. Requests without
1240
+ * an Origin header (curl, server-to-server) always pass.
1241
+ */
1242
+ allowedOrigins?: string[];
1243
+ /**
1244
+ * Hard cap on the raw request-body size in bytes (DoS protection). Bodies
1245
+ * larger than this are rejected with 413 before parsing. Defaults to
1246
+ * 1 MiB (`1_048_576`); set `0` to disable the check.
1247
+ */
1248
+ maxRequestBytes?: number;
1249
+ /**
1250
+ * Optional rate-limit gate, called after authentication and before the
1251
+ * JSON-RPC message is dispatched. Return `false` (or a `{ retryAfter }`
1252
+ * object) to reject the request with 429. The SDK is stateless and holds no
1253
+ * counters itself — back this with your own store (KV, Redis, edge limiter),
1254
+ * keyed by `auth.userId`/`auth.sessionId`. Recommended in production; also
1255
+ * apply platform/edge rate limiting in front of the endpoint.
1256
+ */
1257
+ rateLimit?: (auth: McpAuthInfo | null, req: McpHttpRequest) => boolean | {
1258
+ ok: boolean;
1259
+ retryAfter?: number;
1260
+ } | Promise<boolean | {
1261
+ ok: boolean;
1262
+ retryAfter?: number;
1263
+ }>;
1264
+ /** Called on tool-execution and auth-callback errors (for logging). */
1265
+ onError?: (error: Error, ctx: {
1266
+ method: string;
1267
+ tool?: string;
1268
+ }) => void;
1269
+ /**
1270
+ * Map a thrown tool error to the message returned to the agent. Use it to
1271
+ * redact internal details in production (the full error still reaches
1272
+ * `onError`). Defaults to the raw `error.message`. Return a generic string
1273
+ * — e.g. `() => 'Tool execution failed'` — to leak nothing.
1274
+ */
1275
+ formatToolError?: (error: Error, ctx: {
1276
+ tool: string;
1277
+ }) => string;
1278
+ }
1279
+ /** The handler returned by {@link createMcpHandler}. */
1280
+ interface McpHandler {
1281
+ /** Pure, framework-agnostic core (Express, Fastify, Hono, tests). */
1282
+ handle(req: McpHttpRequest): Promise<McpHttpResponse>;
1283
+ /** Web-standard adapter (Next.js App Router route handlers, edge). */
1284
+ fetch(request: Request): Promise<Response>;
1285
+ /** Metadata for the exposed tools (before per-request scope filtering). */
1286
+ listTools(): Array<{
1287
+ name: string;
1288
+ description: string;
1289
+ annotations?: McpToolAnnotations;
1290
+ }>;
1291
+ /** A ready-to-assign `AgentReadyConfig.mcpServerCard` for this server. */
1292
+ serverCard(options: {
1293
+ endpoint: string;
1294
+ description?: string;
1295
+ documentationUrl?: string;
1296
+ }): McpServerCard;
1297
+ }
1298
+ /**
1299
+ * Create a stateless MCP server handler exposing BuildBase capabilities (and
1300
+ * any custom tools) over Streamable HTTP. See the module docs for wiring.
1301
+ */
1302
+ declare function createMcpHandler(config: CreateMcpHandlerConfig): McpHandler;
1303
+ /**
1304
+ * Identity helper that infers the tool's input type from its zod schema.
1305
+ * Pass a second type argument to type `ctx.custom` from your `context`
1306
+ * factory: `defineMcpTool<typeof schema, MyContext>({ ... })`.
1307
+ */
1308
+ declare function defineMcpTool<S extends z.ZodType, TCustom = any>(tool: McpToolDefinition<S, TCustom>): McpToolDefinition<S, TCustom>;
1309
+
1310
+ /**
1311
+ * OAuth2 app-bridge toolkit (server-side).
1312
+ *
1313
+ * BuildBase runs the OAuth2 authorization flow (login, consent, code, PKCE,
1314
+ * refresh rotation) but it never mints the access token itself — on the token
1315
+ * grant it calls the org's own backend to mint the token the agent will carry.
1316
+ * Concretely, the platform makes signed webhook-style calls to two endpoints an
1317
+ * OAuth2 client registers:
1318
+ *
1319
+ * • applicationTokenUrl — mint an access token for a user (required)
1320
+ * • applicationRevokeUrl — invalidate a user's token on revocation (optional)
1321
+ *
1322
+ * Both requests carry an `Authorization: Bearer <JWT>` where the JWT is HS256,
1323
+ * signed with the client's secret (so possession of the secret authenticates
1324
+ * the platform). This module verifies those requests and shapes the responses,
1325
+ * so an implementor writes only the part that is theirs: minting/invalidating a
1326
+ * token in their own format.
1327
+ *
1328
+ * HMAC verification uses the SDK's dependency-free pure-JS HMAC-SHA256 (no Web
1329
+ * Crypto, no Node `crypto`, no `require`), so it behaves identically whether the
1330
+ * bundle is loaded as ESM or CJS, under a bundler or on bare Node.
1331
+ *
1332
+ * @example applicationTokenUrl handler (Next.js Pages Router):
1333
+ * ```ts
1334
+ * import { handleAppTokenRequest } from "@buildbase/sdk";
1335
+ * export default async function handler(req, res) {
1336
+ * const { status, body } = await handleAppTokenRequest({
1337
+ * authorization: req.headers.authorization,
1338
+ * clientSecret: process.env.BUILDBASE_CLIENT_SECRET!,
1339
+ * mintToken: (user) => ({
1340
+ * token: signMyAccessToken(user, { aud: user.resource }), // your token, your format
1341
+ * expiresIn: 3600,
1342
+ * }),
1343
+ * });
1344
+ * res.status(status).json(body);
1345
+ * }
1346
+ * ```
1347
+ */
1348
+ /** Thrown when an incoming platform request fails verification. */
1349
+ declare class AppBridgeError extends Error {
1350
+ /** Machine-readable reason, e.g. `invalid_signature`, `token_expired`. */
1351
+ readonly code: string;
1352
+ constructor(code: string, message: string);
1353
+ }
1354
+ /** Options for {@link verifyClientJwt} (all optional; secure defaults). */
1355
+ interface VerifyClientJwtOptions {
1356
+ /** Allowed clock skew in seconds for `exp`/`nbf`. Default 60. */
1357
+ clockToleranceSec?: number;
1358
+ /**
1359
+ * Require a numeric `exp` claim. Default **true** — a JWT with no expiry
1360
+ * would never expire, so a leaked token stays valid forever. Set `false`
1361
+ * only for a token type you know is intentionally non-expiring.
1362
+ */
1363
+ requireExp?: boolean;
1364
+ /** If set, `iss` must equal this value (RFC 7519 issuer check). */
1365
+ issuer?: string;
1366
+ /** If set, `aud` must equal (or, for an array `aud`, include) this value. */
1367
+ audience?: string;
1368
+ }
1369
+ /**
1370
+ * Verify a BuildBase-issued HS256 JWT (signed with the client secret) and return
1371
+ * its payload. Checks the signature (timing-safe), the algorithm, `exp`/`nbf`,
1372
+ * and — by default — that an `exp` is present at all. Optionally pins `iss`/`aud`.
1373
+ * Throws {@link AppBridgeError} on any failure.
1374
+ *
1375
+ * The third argument accepts either the legacy `clockToleranceSec` number or a
1376
+ * {@link VerifyClientJwtOptions} object.
1377
+ */
1378
+ declare function verifyClientJwt(token: string, clientSecret: string, optionsOrTolerance?: number | VerifyClientJwtOptions): Record<string, any>;
1379
+ /** Extract the token from an `Authorization: Bearer <token>` header. */
1380
+ declare function extractBearerToken(authorization: string | null | undefined): string | null;
1381
+ /**
1382
+ * Sign an HS256 JWT — the symmetric counterpart of {@link verifyClientJwt}.
1383
+ * Sets `iat` and `exp` (from `expiresInSec`, default 3600) unless the payload
1384
+ * already carries them. The intended use is minting the app's own agent access
1385
+ * tokens in an `applicationTokenUrl` handler, embedding whatever claims the
1386
+ * MCP/API layer needs to verify later (e.g. `sub`, `scope`, a session id).
1387
+ */
1388
+ declare function signClientJwt(payload: Record<string, unknown>, secret: string, options?: {
1389
+ expiresInSec?: number;
1390
+ }): string;
1391
+ declare function bearerChallenge(options: {
1392
+ resourceMetadataUrl: string;
1393
+ error?: 'invalid_token' | 'insufficient_scope' | string;
1394
+ errorDescription?: string;
1395
+ }): {
1396
+ status: number;
1397
+ headers: Record<string, string>;
1398
+ body: string;
1399
+ };
1400
+
1401
+ export { AppBridgeError, bearerChallenge, builtinMcpTools, createMcpHandler, defineMcpTool, extractBearerToken, selectBuiltinTools, signClientJwt, verifyClientJwt };
1402
+ export type { BuiltinMcpToolName, CreateMcpHandlerConfig, McpAuthInfo, McpBuildBaseClient, McpHandler, McpHttpRequest, McpHttpResponse, McpServerCard, McpToolAnnotations, McpToolContext, McpToolDefinition, ScopedActions };