@buildbase/sdk 0.0.33 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/styles.css +1 -1
- package/dist/index.d.ts +101 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react/index.d.ts +204 -2
- package/dist/react/index.js +4 -4
- package/dist/react/index.mjs +4 -4
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
let e=!0;function t(t,...s){e&&function(){try{const e="undefined"!=typeof globalThis?globalThis:null;return"development"===e?.process?.env?.NODE_ENV}catch{return!1}}()&&console.error(t,...s)}async function s(e,t){try{const s=await e.json();return s?.message||s?.error||t}catch{return t}}async function r(e){const t=await e.text();if(!t)throw new Error("Empty response body");try{return JSON.parse(t)}catch(e){throw new Error(`Invalid JSON response: ${t.substring(0,100)}${t.length>100?"...":""}`)}}async function n(e,t="Request failed"){if(!e.ok){let s=t;try{const t=await r(e);s=t.message||t.error||s}catch{s=function(e,t){const s={400:"Bad Request",401:"Unauthorized - Please check your session",403:"Forbidden - You do not have permission",404:"Resource not found",500:"Internal server error",502:"Bad Gateway",503:"Service unavailable"}[e.status]||e.statusText||t;return new Error(`${t} (${e.status}: ${s})`)}(e,t).message}throw new Error(s)}try{return await r(e)}catch(e){if(e instanceof Error&&e.message.includes("Invalid JSON"))throw e;throw new Error("Failed to parse response as JSON")}}class o extends Error{constructor(e,t,s,r){super(e),this.code=t,this.context=s,this.originalError=r,this.name="SDKError","undefined"!=typeof Error&&"captureStackTrace"in Error&&Error.captureStackTrace(this,o)}}const a=new class{constructor(){this.config={enableConsoleLogging:!0,showUserNotifications:!1}}configure(t){this.config={...this.config,...t},void 0!==t.enableConsoleLogging&&function(t){void 0!==t.enableLogging&&(e=t.enableLogging)}({enableLogging:t.enableConsoleLogging})}handleError(e,s={}){if(function(e){return e instanceof Error&&("AbortError"===e.name||"ERR_CANCELED"===e.code)}(e))return;const r=e instanceof Error?e:new o("string"==typeof e?e:"An unknown error occurred","UNKNOWN_ERROR",s),n=r instanceof o?r:new o(r.message,"SDK_ERROR",s,r);if(this.config.enableConsoleLogging&&t(`[SDK Error] ${s.component||"Unknown"}:`,{message:n.message,code:n.code,context:n.context,originalError:n.originalError,stack:n.stack}),this.config.onError)try{this.config.onError(n,s)}catch(e){!function(e,...t){console.error(e,...t)}("[SDK Error Handler] Error in custom error callback:",e)}this.config.showUserNotifications&&this.notifyUser(n,s)}notifyUser(e,t){"undefined"!=typeof window&&window.dispatchEvent&&window.dispatchEvent(new CustomEvent("sdk-error",{detail:{error:e,context:t}}))}wrapAsync(e,t){return(...s)=>e(...s).catch(e=>{throw this.handleError(e,t),e})}wrapSync(e,t){return(...s)=>{try{return e(...s)}catch(e){throw this.handleError(e,t),e}}}};function i(e,t={}){a.handleError(e,t)}const c="saas-session-id";function u(){if("undefined"==typeof window)return null;try{return function(e){if("undefined"==typeof window)return null;try{return localStorage.getItem(e)}catch(t){return i(t,{component:"storage",action:"getStorageItem",metadata:{key:e}}),null}}(c)}catch(e){return i(e,{component:"auth-utils",action:"getSessionId",metadata:{key:c}}),null}}function l(){const e=u(),t={};return e&&(t["x-session-id"]=e),t}const d="SDK is not ready (missing serverUrl, version, or orgId)";class h{constructor(e){this.serverUrl=e.serverUrl,this.version=e.version,this.orgId=e.orgId,this.requireOrgId=e.requireOrgId??!1,this.basePath=e.basePath??"public",this._sessionId=e.sessionId,this._timeout=e.timeout??3e4,this._maxRetries=e.maxRetries??0,this._debug=e.debug??!1,this._customHeaders=e.headers??{},this._onError=e.onError,this._fetch=e.fetch??globalThis.fetch}ensureReady(){if(!this.serverUrl?.trim()||!this.version)throw new Error(d);if(this.requireOrgId&&!this.orgId?.trim())throw new Error(d)}get baseUrl(){return this.ensureReady(),`${this.serverUrl}/api/${this.version}/${this.basePath}`}getAuthHeaders(){return this._sessionId?{"x-session-id":this._sessionId}:l()}url(e){const t=e.startsWith("/")?e.slice(1):e;return`${this.baseUrl.endsWith("/")?this.baseUrl.slice(0,-1):this.baseUrl}/${t}`}buildHeaders(e){const t={...this._customHeaders,...this.getAuthHeaders()};return e.headers&&Object.assign(t,e.headers),null==e.body||t["Content-Type"]||(t["Content-Type"]="application/json"),t}async executeFetch(e,t){const s=this.url(e),r=(t.method??"GET").toUpperCase(),n=this.buildHeaders(t),o={...t,headers:n};let a;if(this._timeout>0){const e=new AbortController;a=setTimeout(()=>e.abort(),this._timeout),o.signal=t.signal?AbortSignal.any([t.signal,e.signal]):e.signal}const i=async t=>{try{const e=this._fetch.bind(globalThis),n=await e(s,o);if(this._debug&&console.log(`[BuildBase] ${r} ${s} → ${n.status}`),n.status>=500&&t<this._maxRetries){const e=Math.min(1e3*Math.pow(2,t),1e4);return this._debug&&console.log(`[BuildBase] Retrying in ${e}ms (attempt ${t+1}/${this._maxRetries})`),await new Promise(t=>setTimeout(t,e)),i(t+1)}return n}catch(s){if(s instanceof Error&&"AbortError"===s.name){if(void 0!==a){const t=new Error(`Request timeout after ${this._timeout}ms: ${r} ${e}`);throw this._onError?.(t,{method:r,path:e}),t}throw s}if(t<this._maxRetries){const e=Math.min(1e3*Math.pow(2,t),1e4);return this._debug&&console.log(`[BuildBase] Network error, retrying in ${e}ms (attempt ${t+1}/${this._maxRetries})`),await new Promise(t=>setTimeout(t,e)),i(t+1)}throw s instanceof Error&&this._onError?.(s,{method:r,path:e}),s}};try{return await i(0)}finally{void 0!==a&&clearTimeout(a)}}async fetchJson(e,t={},s="Request failed"){this.ensureReady();try{const r=await this.executeFetch(e,t);return await n(r,s)}catch(s){throw s instanceof Error&&this._onError?.(s,{method:(t.method??"GET").toUpperCase(),path:e}),s}}async fetchResponse(e,t={}){return this.ensureReady(),this.executeFetch(e,t)}}class p extends h{constructor(e){super(e)}async requestAuth(e){const t=`${this.serverUrl}/api/${this.version}/auth/request`,s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!s.ok){let e="Failed to initiate authentication";try{e=(await s.json()).message||e}catch{e=`Failed to initiate authentication (${s.status}: ${s.statusText})`}throw new Error(e)}return s.json()}async getProfile(e,t){return this.fetchJson("profile",{headers:{"x-session-id":e},signal:t},"Failed to fetch user profile")}}class f extends h{constructor(e){super({...e,basePath:"beta",requireOrgId:!0})}getAuthHeaders(){return{}}async fetchConfig(){return this.fetchJson(`config?orgId=${encodeURIComponent(this.orgId)}`,{},"Failed to fetch beta form configuration")}async submitBetaUser(e){return this.fetchJson("submit",{method:"POST",body:JSON.stringify(e)},"Failed to submit beta user request")}}class g{constructor(e){this.api=new f(e),this.orgId=e.orgId}async fetchConfig(){return this.api.fetchConfig()}async submitBetaUser(e){const t=e?.context??{},s=t?.country??("undefined"!=typeof navigator&&navigator.language?navigator.language.split("-")[1]:void 0),r=t?.language??("undefined"!=typeof navigator&&navigator.language?navigator.language.split("-")[0]:void 0),n=t?.timezone??("undefined"!=typeof Intl&&Intl.DateTimeFormat?Intl.DateTimeFormat().resolvedOptions().timeZone:void 0),o=t?.currency??("undefined"!=typeof Intl&&Intl.NumberFormat&&Intl.NumberFormat().resolvedOptions().currency?Intl.NumberFormat().resolvedOptions().currency:void 0);return this.api.submitBetaUser({orgId:this.orgId,formData:{...e,country:s,language:r,timezone:n,currency:o}})}}class w extends h{constructor(e){super({...e,requireOrgId:!0})}async getVapidPublicKey(){return this.fetchJson("push/vapid-public-key")}async subscribe(e,t){await this.fetchJson("push/subscribe",{method:"POST",body:JSON.stringify({endpoint:e.endpoint,keys:e.keys,userAgent:t})})}async unsubscribe(e){await this.fetchJson("push/unsubscribe",{method:"DELETE",body:JSON.stringify({endpoint:e})})}}class y extends h{constructor(e){super({...e,requireOrgId:!0})}async getSettings(e){return this.fetchJson(`${this.orgId}/settings`,{signal:e},"Failed to fetch settings")}}class m extends h{constructor(e){super(e)}async getAttributes(e){const t=await this.fetchResponse("users/attributes",{signal:e});if(!t.ok)throw new Error(await s(t,"Failed to fetch user attributes"));const r=await t.json();return r&&"object"==typeof r&&!Array.isArray(r)?r:{}}async updateAttributes(e){return this.fetchJson("users/attributes",{method:"PATCH",body:JSON.stringify({attributes:e})},"Failed to update user attributes")}async updateAttribute(e,t){return this.fetchJson(`users/attributes/${e}`,{method:"PATCH",body:JSON.stringify({value:t})},"Failed to update user attribute")}async getFeatures(e){const t=await this.fetchResponse("users/features",{signal:e});if(!t.ok)throw new Error(await s(t,"Failed to fetch user features"));const r=await t.json();return"object"==typeof r&&null!==r?r:{}}}class k extends h{constructor(e){super({...e,requireOrgId:!0})}async getWorkspaces(){return this.fetchJson("workspaces",{},"Failed to fetch workspaces")}async createWorkspace(e){return this.fetchJson("workspaces",{method:"POST",body:JSON.stringify(e)},"Failed to create workspace")}async updateWorkspace(e,t){return this.fetchJson(`workspaces/${e}`,{method:"PUT",body:JSON.stringify(t)},"Failed to update workspace")}async deleteWorkspace(e){return this.fetchJson(`workspaces/${e}`,{method:"DELETE"},"Failed to delete workspace")}async getWorkspaceUsers(e){return this.fetchJson(`workspaces/${e}/users`,{},"Failed to fetch workspace users")}async addUser(e,t){return this.fetchJson(`workspaces/${e}/users/add`,{method:"POST",body:JSON.stringify(t)},"Failed to invite member")}async removeUser(e,t){return this.fetchJson(`workspaces/${e}/users/${t}`,{method:"DELETE"},"Failed to remove user")}async updateUser(e,t,s){return this.fetchJson(`workspaces/${e}/users/${t}`,{method:"PATCH",body:JSON.stringify(s)},"Failed to update user")}async getFeatures(){return this.fetchJson("workspaces/features",{},"Failed to fetch features")}async updateFeature(e,t,s){return this.fetchJson(`workspaces/${e}/features`,{method:"PATCH",body:JSON.stringify({features:{[t]:s}})},"Failed to update feature")}async getWorkspace(e){return this.fetchJson(`workspaces/${e}`,{},"Failed to fetch workspace")}async getProfile(){return this.fetchJson("profile",{},"Failed to fetch profile")}async updateUserProfile(e){return this.fetchJson("profile",{method:"PATCH",body:JSON.stringify(e)},"Failed to update user profile")}async getCurrentSubscription(e){const t=await this.fetchResponse(`workspaces/${e}/subscription`);if(!t.ok){let e="Failed to fetch subscription";try{e=(await t.json()).message||e}catch{e=404===t.status?"Workspace not found or no subscription available":401===t.status?"Unauthorized - Please check your session":`Failed to fetch subscription (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch subscription");return s.data||s}return s}async getPlanGroup(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/plan-group`);if(!t.ok){let e="Failed to fetch plan group";try{e=(await t.json()).message||e}catch{e=404===t.status?"No plan group found for this workspace":401===t.status?"Unauthorized - Please check your session":`Failed to fetch plan group (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch plan group");return s.data||s}return s}async getPlanGroupByVersion(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/plan-group?groupVersionId=${encodeURIComponent(t)}`);if(!s.ok){let e="Failed to fetch plan group version";try{e=(await s.json()).message||e}catch{e=404===s.status?"Plan group version not found":401===s.status?"Unauthorized - Please check your session":`Failed to fetch plan group version (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to fetch plan group version");return r.data||r}return r}async getPlanGroupVersions(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/plan-group/versions`);if(!t.ok){let e="Failed to fetch plan group versions";try{e=(await t.json()).message||e}catch{e=404===t.status?"No plan group versions found":401===t.status?"Unauthorized - Please check your session":`Failed to fetch plan group versions (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch plan group versions");return s.data||s}return s}async getPublicPlans(e){if(!this.orgId)throw new Error("orgId is required for getPublicPlans");const t=await this.fetchResponse(`${this.orgId}/plans/${encodeURIComponent(e)}`);if(!t.ok){let s="Failed to fetch plans";try{s=(await t.json()).message||s}catch{s=404===t.status?`Plans "${e}" not found`:`Failed to fetch plans (${t.status}: ${t.statusText})`}throw new Error(s)}const s=await t.json();if(void 0!==s.success&&!s.success)throw new Error(s.message||"Failed to fetch plans");return s.data??s}async getPlanGroupVersion(e){const t=await this.fetchResponse(`plan-group-versions/${e}`);if(!t.ok){let e="Failed to fetch plan group version";try{e=(await t.json()).message||e}catch{e=404===t.status?"Plan group version not found":401===t.status?"Unauthorized - Please check your session":`Failed to fetch plan group version (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch plan group version");return s.data||s}return s}async createCheckoutSession(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/checkout`,{method:"POST",body:JSON.stringify(t)});if(!s.ok){let e="Failed to create checkout session";try{e=(await s.json()).message||e}catch{e=`Failed to create checkout session (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to create checkout session");return r.data||r}return r}async updateSubscription(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription`,{method:"PATCH",body:JSON.stringify(t)});if(!s.ok){let e="Failed to update subscription";try{e=(await s.json()).message||e}catch{e=`Failed to update subscription (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to update subscription");return r.data?.checkoutUrl||r.checkoutUrl,r.data||r}return r.checkoutUrl,r}async createBillingPortalSession(e,t){return this.fetchJson(`workspaces/${e}/subscription/billing-portal`,{method:"POST",body:JSON.stringify(t?{returnUrl:t}:{})})}async listInvoices(e,t=10,s){const r=new URLSearchParams;r.append("limit",t.toString()),s&&r.append("starting_after",s);const n=await this.fetchResponse(`workspaces/${e}/subscription/invoices?${r.toString()}`,{});if(!n.ok){let e="Failed to fetch invoices";try{e=(await n.json()).message||e}catch{e=404===n.status?"Workspace not found or no invoices available":401===n.status?"Unauthorized - Please check your session":`Failed to fetch invoices (${n.status}: ${n.statusText})`}throw new Error(e)}const o=await n.json();if(void 0!==o.success){if(!o.success)throw new Error(o.message||"Failed to fetch invoices");return o}return o}async getInvoice(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/invoices/${t}`,{});if(!s.ok){let e="Failed to fetch invoice";try{e=(await s.json()).message||e}catch{e=404===s.status?"Invoice not found":401===s.status?"Unauthorized - Please check your session":`Failed to fetch invoice (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to fetch invoice");return r}return r}async cancelSubscriptionAtPeriodEnd(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/cancel-at-period-end`,{method:"POST"});if(!t.ok){let e="Failed to cancel subscription";try{e=(await t.json()).message||e}catch{e=404===t.status?"Subscription not found":401===t.status?"Unauthorized - Please check your session":`Failed to cancel subscription (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to cancel subscription");return s.data||s}return s}async resumeSubscription(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/resume`,{method:"POST"});if(!t.ok){let e="Failed to resume subscription";try{e=(await t.json()).message||e}catch{e=404===t.status?"Subscription not found":401===t.status?"Unauthorized - Please check your session":`Failed to resume subscription (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to resume subscription");return s.data||s}return s}async recordUsage(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/usage`,{method:"POST",body:JSON.stringify(t)});if(!s.ok){let e="Failed to record usage";try{e=(await s.json()).message||e}catch{e=`Failed to record usage (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to record usage");return r.data||r}return r}async recordUsageBatch(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/usage/batch`,{method:"POST",body:JSON.stringify(t)});if(!s.ok){let e="Failed to record batch usage";try{e=(await s.json()).message||e}catch{e=`Failed to record batch usage (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();return r.data||r}async getQuotaUsageStatus(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/usage/status?quotaSlug=${encodeURIComponent(t)}`);if(!s.ok){let e="Failed to fetch quota usage status";try{e=(await s.json()).message||e}catch{e=404===s.status?"Workspace not found or no subscription available":401===s.status?"Unauthorized - Please check your session":`Failed to fetch quota usage status (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to fetch quota usage status");return r.data||r}return r}async getAllQuotaUsage(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/usage/all`);if(!t.ok){let e="Failed to fetch all quota usage";try{e=(await t.json()).message||e}catch{e=404===t.status?"Workspace not found or no subscription available":401===t.status?"Unauthorized - Please check your session":`Failed to fetch all quota usage (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch all quota usage");return s.data||s}return s}async getUsageLogs(e,t){const s=new URLSearchParams;t?.quotaSlug&&s.append("quotaSlug",t.quotaSlug),t?.from&&s.append("from",t.from),t?.to&&s.append("to",t.to),t?.source&&s.append("source",t.source),t?.page&&s.append("page",t.page.toString()),t?.limit&&s.append("limit",t.limit.toString());const r=s.toString(),n=`workspaces/${e}/subscription/usage/logs${r?`?${r}`:""}`,o=await this.fetchResponse(n);if(!o.ok){let e="Failed to fetch usage logs";try{e=(await o.json()).message||e}catch{e=404===o.status?"Workspace not found":401===o.status?"Unauthorized - Please check your session":`Failed to fetch usage logs (${o.status}: ${o.statusText})`}throw new Error(e)}const a=await o.json();if(void 0!==a.success){if(!a.success)throw new Error(a.message||"Failed to fetch usage logs");return a.data||a}return a}}var b;!function(e){e.V1="v1"}(b||(b={}));const v={UserCreated:"user:created",UserUpdated:"user:updated",WorkspaceChanged:"workspace:changed",WorkspaceUpdated:"workspace:updated",WorkspaceUserAdded:"workspace:user-added",WorkspaceUserRemoved:"workspace:user-removed",WorkspaceUserRoleChanged:"workspace:user-role-changed",WorkspaceCreated:"workspace:created",WorkspaceDeleted:"workspace:deleted"};class ${constructor(){this.callbacks=null}setCallbacks(e){this.callbacks=e}getCallbacks(){return this.callbacks}async emit(e,t){if(this.callbacks?.handleEvent)try{await this.callbacks.handleEvent(e,t)}catch(t){i(t,{component:"EventEmitter",action:"emit",metadata:{eventType:e}})}}async emitUserCreated(e){await this.emit(v.UserCreated,{user:e})}async emitUserUpdated(e,t){await this.emit(v.UserUpdated,{user:e,previousUser:t})}async emitWorkspaceChanged(e,t){await this.emit(v.WorkspaceChanged,{workspace:e,previousWorkspace:t})}async emitWorkspaceUpdated(e){await this.emit(v.WorkspaceUpdated,{workspace:e})}async emitWorkspaceUserAdded(e,t,s){await this.emit(v.WorkspaceUserAdded,{userId:e,workspace:t,role:s})}async emitWorkspaceUserRemoved(e,t,s){await this.emit(v.WorkspaceUserRemoved,{userId:e,workspace:t,role:s})}async emitWorkspaceUserRoleChanged(e,t,s,r){await this.emit(v.WorkspaceUserRoleChanged,{userId:e,workspace:t,previousRole:s,newRole:r})}async emitWorkspaceCreated(e){await this.emit(v.WorkspaceCreated,{workspace:e})}async emitWorkspaceDeleted(e){await this.emit(v.WorkspaceDeleted,{workspace:e})}}const S=new $,U=new Set;function E(){U.forEach(e=>e())}const F=new Set;function P(){F.forEach(e=>e())}const I="bb";function R(e,t){let s;try{const e=t||("undefined"!=typeof window?window.location.href:"https://localhost");s=new URL(e),s.search=""}catch{s=new URL("https://localhost")}return s.searchParams.set(I,function(e){return Object.entries(e).filter(([,e])=>null!=e&&""!==e).map(([e,t])=>`${encodeURIComponent(e)}:${encodeURIComponent(t)}`).join(",")}(e)),s.toString()}function x(e,t){const s=t||("undefined"!=typeof window?window.location.href:void 0);return{successUrl:R({action:"checkout",status:"success",ws:e,screen:"subscription"},s),cancelUrl:R({action:"checkout",status:"cancel",ws:e,screen:"subscription"},s)}}function C(){if("undefined"==typeof window)return null;try{const e=new URLSearchParams(window.location.search).get(I);if(!e)return null;const t=function(e){const t={};if(!e)return t;const s=e.split(",");for(const e of s){const s=e.indexOf(":");if(-1===s)continue;const r=decodeURIComponent(e.slice(0,s)),n=decodeURIComponent(e.slice(s+1));r&&(t[r]=n)}return t}(e);return Object.keys(t).length>0?t:null}catch{return null}}function T(){if("undefined"!=typeof window)try{const e=new URL(window.location.href);e.searchParams.has(I)&&(e.searchParams.delete(I),window.history.replaceState({},"",e.toString()))}catch{}}function W(e){if(!e||"string"!=typeof e)return null;try{const t=new URL(e);return"https:"===t.protocol?e:"http:"!==t.protocol||"localhost"!==t.hostname&&"127.0.0.1"!==t.hostname&&"::1"!==t.hostname?null:e}catch{return null}}function j(e,t="/"){const s=W(e);window.location.href=s||t}const O={usd:"$",eur:"€",gbp:"£",jpy:"¥",cad:"CA$",aud:"A$",chf:"CHF",cny:"¥",hkd:"HK$",sgd:"S$",inr:"₹",mxn:"MX$",brl:"R$",nzd:"NZ$",sek:"kr",nok:"kr",dkk:"kr",pln:"zł",thb:"฿"},J={usd:"🇺🇸",eur:"🇪🇺",gbp:"🇬🇧",jpy:"🇯🇵",cad:"🇨🇦",aud:"🇦🇺",chf:"🇨🇭",cny:"🇨🇳",hkd:"🇭🇰",sgd:"🇸🇬",inr:"🇮🇳",mxn:"🇲🇽",brl:"🇧🇷",nzd:"🇳🇿",sek:"🇸🇪",nok:"🇳🇴",dkk:"🇩🇰",pln:"🇵🇱",thb:"🇹🇭"};function L(e){return e&&e.trim()?J[e.trim().toLowerCase()]??"":""}function N(e){if(!e||!e.trim())return"";const t=e.trim().toLowerCase();return O[t]??t.toUpperCase()}const _=["usd","eur","gbp","jpy","cad","aud","chf","cny","hkd","sgd","inr","mxn","brl","nzd","sek","nok","dkk","pln","thb"],q=_.map(e=>({value:e,label:`${e.toUpperCase()} (${N(e)})`}));function A(e,t){return N(t)+(e/100).toFixed(2)}const z={unit:"unit",units:"units",included:"Included",afterThat:"after that",afterIncluded:"After included"};function B(e,t,s,r){if(null==e||e<0)return null;const n={...z,...r},o=null!=t&&t>=1?t:1,a=N(s),i=(e/100).toFixed(2);return 1===o?`${a}${i}/${n.unit}`:`${a}${i}/${o.toLocaleString()} ${n.units}`}function M(e,t,s,r,n,o){if(null==e||e<0)return null;const a={...z,...o},i=null!=t&&t>=1?t:1,c=N(r),u=(e/100).toFixed(2);if(s){const e=n??(s.endsWith("s")?s:`${s}s`);return i>=2?`${c}${u}/${i.toLocaleString()} ${e}`:`${c}${u}/${s}`}return 1===i?`${c}${u}/${a.unit}`:`${c}${u}/${i.toLocaleString()} ${a.units}`}function V(e,t="unit"){const s=(e||"").trim().toLowerCase();if(!s)return t;const r=s.split(/\s+/)[0]??s;return new Set(["series","species","status","analysis","basis","bus","campus","corpus","axis"]).has(r)?r:r.endsWith("ies")&&r.length>3?r.slice(0,-3)+"y":r.endsWith("ses")||r.endsWith("xes")||r.endsWith("zes")||r.endsWith("ches")||r.endsWith("shes")?r.slice(0,-2):r.endsWith("s")&&!r.endsWith("ss")&&r.length>1?r.slice(0,-1):r||t}function D(e,t,s,r,n,o,a){const i={...z,...a},c=o??(s.endsWith("s")?s:`${s}s`),u=null!=n&&n>=2?`${n.toLocaleString()} ${c}`:s;return null!=e&&null!=t?`${i.included}: ${e.toLocaleString()}, ${i.afterThat} ${A(t,r)}/${u}`:null!=e?`${i.included}: ${e.toLocaleString()}`:null!=t?`${i.afterIncluded}: ${A(t,r)}/${u}`:"—"}function H(e,t){if(null==e)return null;const s=e[t??"monthly"];return s?{included:s.included,...void 0!==s.overage&&{overage:s.overage},...void 0!==s.unitSize&&{unitSize:s.unitSize}}:null}const K={included:"included",then:"then"};function G(e,t,s={}){const{overageInCents:r=!0,currency:n}=s,o=s.labels??K,a=s.currencySymbol??N(n??"");if(null==e)return"—";const{included:i,overage:c}=e,u=`${i} ${o.included}`;if(null==c)return u;const l=r?c/100:c,d="number"==typeof l&&Number.isFinite(l)?l.toFixed(2):String(c),h=t&&"unitSize"in e&&null!=e.unitSize&&e.unitSize>0?` / ${e.unitSize.toLocaleString()} ${t}`:t?` / ${t}`:"";return`${u}, ${o.then} ${a}${d}${h}`}const Q={Monthly:"monthly",Yearly:"yearly",Quarterly:"quarterly"},Y={Active:"active",Trialing:"trialing",Canceled:"canceled",PastDue:"past_due",Paused:"paused",Incomplete:"incomplete",Unpaid:"unpaid"},Z={Draft:"draft",Open:"open",Paid:"paid",Uncollectible:"uncollectible",Void:"void"},X={Feature:"feature",Limit:"limit",Quota:"quota"},ee={None:"none",Notified:"notified",Warning:"warning",Final:"final",Suspended:"suspended"};function te(e,t){const s=e.pricingVariants;if(!s?.length)return null;const r=t.toLowerCase();return s.find(e=>e.currency?.toLowerCase()===r)??null}function se(e,t,s){const r=te(e,t);if(!r?.basePricing)return null;const n=r.basePricing[s];return null!=n?n:null}function re(e,t,s){const r=te(e,t);if(!r?.stripePrices)return null;const n=s===Q.Monthly?"monthlyPriceId":s===Q.Yearly?"yearlyPriceId":"quarterlyPriceId",o=s===Q.Monthly?"monthly":s===Q.Yearly?"yearly":void 0;return r.stripePrices[n]??(o?r.stripePrices[o]:void 0)??null}function ne(e,t,s,r){const n=te(e,t),o=n?.quotaOverages?.[s];if(o)return o[r]}function oe(e,t){const s=te(e,t);return s?s.currency:e.plan?.currency??""}function ae(e){const t=new Set;for(const s of e)s.pricingVariants?.forEach(e=>{e.currency&&t.add(e.currency.toLowerCase())});return Array.from(t).sort()}function ie(e,t,s,r){const n=e.quotas?.[s];if(null==n)return null;const o=n[r];if(!o)return null;const a=ne(e,t,s,r);return{included:o.included,...void 0!==o.unitSize&&{unitSize:o.unitSize},...void 0!==a&&{overage:a}}}function ce(e,t){if(!e)return null;for(const s of t){const t=s.pricingVariants;if(t?.length)for(const s of t){const t=s.stripePrices;if(t){if(t.monthlyPriceId===e||t.monthly===e)return{interval:"monthly",currency:s.currency};if(t.yearlyPriceId===e||t.yearly===e)return{interval:"yearly",currency:s.currency};if(t.quarterlyPriceId===e)return{interval:"quarterly",currency:s.currency}}}}return null}function ue(e,t){const s=te(e,t);return s?.seatPricing?.enabled?s.seatPricing:null}function le(e,t,s){const r=ue(e,t);return r?.perSeat?r.perSeat[s]??null:null}function de(e,t){return Math.max(0,e-(t||0))}function he(e,t,s,r){const n=ue(e,t);if(!n)return null;return de(r,n.includedSeats)*(le(e,t,s)??0)}function pe(e,t,s,r){const n=se(e,t,s);if(null===n)return null;if(void 0===r)return n;return n+(he(e,t,s,r)??0)}function fe(e){const{planVersion:t,currency:s="usd",settingsMaxUsers:r}=e;if(t){const e=ue(t,s);if(e)return{maxUsers:e.maxSeats??0,source:"seat_pricing",includedSeats:e.includedSeats??0,hasSeatPricing:!0}}return null!=r&&r>0?{maxUsers:r,source:"settings",includedSeats:0,hasSeatPricing:!1}:{maxUsers:0,source:"none",includedSeats:0,hasSeatPricing:!1}}function ge(e){const{memberCount:t,maxUsersConfig:s,hasSubscription:r=!0,requireSubscription:n=!1}=e;if(n&&!r)return{canInvite:!1,blockReason:"no_subscription",blockMessageKey:"users.subscriptionRequired",blockMessageValues:{}};const{maxUsers:o,source:a}=s;if(o<=0)return{canInvite:!0,blockReason:null,blockMessageKey:null,blockMessageValues:null};if(t>=o){return{canInvite:!1,blockReason:{seat_pricing:"seat_limit_reached",settings:"settings_user_limit_reached"}[a]??"seat_limit_reached",blockMessageKey:{seat_pricing:"users.seatLimitMessage",settings:"users.settingsLimitMessage"}[a]??"users.memberLimitMessage",blockMessageValues:{maxUsers:o}}}return{canInvite:!0,blockReason:null,blockMessageKey:null,blockMessageValues:null}}const we="\n// BuildBase Push Notification Service Worker\n// Place this file in your app's public directory (e.g. public/push-sw.js)\n\nself.addEventListener('push', function(event) {\n if (!event.data) return;\n\n try {\n var payload = event.data.json();\n var title = payload.title || 'Notification';\n var options = {\n body: payload.body || '',\n icon: payload.icon || undefined,\n badge: payload.icon || undefined,\n data: { url: payload.url, ...(payload.data || {}) },\n tag: 'buildbase-push-' + Date.now(),\n };\n\n event.waitUntil(\n self.registration.showNotification(title, options)\n );\n } catch (e) {\n console.error('[PushSW] Failed to show notification:', e);\n }\n});\n\nself.addEventListener('notificationclick', function(event) {\n event.notification.close();\n\n var url = event.notification.data && event.notification.data.url;\n if (url) {\n event.waitUntil(\n clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {\n for (var i = 0; i < clientList.length; i++) {\n var client = clientList[i];\n if (client.url === url && 'focus' in client) {\n return client.focus();\n }\n }\n if (clients.openWindow) {\n return clients.openWindow(url);\n }\n })\n );\n }\n});\n";var ye;function me(e){const{serverUrl:t,orgId:s,version:r="v1",getSessionId:n,timeout:o,maxRetries:a,debug:i,headers:c,onError:u,fetch:l}=e;if(!t)throw new Error("BuildBase: serverUrl is required");if(!s)throw new Error("BuildBase: orgId is required");const d={...void 0!==o&&{timeout:o},...void 0!==a&&{maxRetries:a},...void 0!==i&&{debug:i},...c&&{headers:c},...u&&{onError:u},...l&&{fetch:l}},h=e=>{const n={serverUrl:t,version:r,orgId:s,sessionId:e,...d};return{workspace:new k(n),user:new m(n),settings:new y(n),push:new w(n)}},p=new k({serverUrl:t,version:r,orgId:s,...d}),f=e=>({workspace:{list:async()=>(await e()).workspace.getWorkspaces(),get:async t=>(await e()).workspace.getWorkspace(t),create:async t=>(await e()).workspace.createWorkspace(t),update:async(t,s)=>(await e()).workspace.updateWorkspace(t,s),delete:async t=>(await e()).workspace.deleteWorkspace(t)},users:{list:async t=>(await e()).workspace.getWorkspaceUsers(t),invite:async(t,s,r)=>(await e()).workspace.addUser(t,{email:s,role:r}),remove:async(t,s)=>(await e()).workspace.removeUser(t,s),updateRole:async(t,s,r)=>(await e()).workspace.updateUser(t,s,{role:r}),getProfile:async()=>(await e()).workspace.getProfile(),updateProfile:async t=>(await e()).workspace.updateUserProfile(t)},subscription:{get:async t=>(await e()).workspace.getCurrentSubscription(t),checkout:async(t,s)=>(await e()).workspace.createCheckoutSession(t,s),update:async(t,s)=>(await e()).workspace.updateSubscription(t,s),cancel:async t=>(await e()).workspace.cancelSubscriptionAtPeriodEnd(t),resume:async t=>(await e()).workspace.resumeSubscription(t),getBillingPortalUrl:async(t,s)=>(await e()).workspace.createBillingPortalSession(t,s)},plans:{getGroup:async t=>(await e()).workspace.getPlanGroup(t),getVersions:async t=>(await e()).workspace.getPlanGroupVersions(t),getPublic:e=>p.getPublicPlans(e),getVersion:e=>p.getPlanGroupVersion(e)},invoices:{list:async(t,s,r)=>(await e()).workspace.listInvoices(t,s,r),get:async(t,s)=>(await e()).workspace.getInvoice(t,s)},usage:{record:async(t,s)=>(await e()).workspace.recordUsage(t,s),recordBatch:async(t,s)=>(await e()).workspace.recordUsageBatch(t,s),getQuota:async(t,s)=>(await e()).workspace.getQuotaUsageStatus(t,s),getAll:async t=>(await e()).workspace.getAllQuotaUsage(t),getLogs:async(t,s)=>(await e()).workspace.getUsageLogs(t,s)},settings:{get:async()=>(await e()).settings.getSettings()},features:{list:async()=>(await e()).workspace.getFeatures(),update:async(t,s,r)=>(await e()).workspace.updateFeature(t,s,r)}}),g=f(async()=>h(await(async()=>{if(!n)throw new Error("BuildBase: getSessionId callback is required for authenticated calls. Pass it in BuildBase({ getSessionId: ... }) or use withSession(id) / client.forSession(id).");const e=await n();if(!e)throw new Error("BuildBase: Not authenticated (getSessionId returned null)");return e})()));return{auth:async()=>{if(!n)return null;const e=await n();return e?{sessionId:e}:null},withSession:e=>{const t=h(e);return f(async()=>t)},client:{forSession:h},...g}}!function(e){e.loading="loading",e.redirecting="redirecting",e.authenticated="authenticated",e.unauthenticated="unauthenticated",e.authenticating="authenticating"}(ye||(ye={}));export{b as ApiVersion,p as AuthApi,ye as AuthStatus,I as BB_PARAM,h as BaseApi,g as BetaForm,Q as BillingIntervals,me as BuildBase,O as CURRENCY_DISPLAY,J as CURRENCY_FLAG,ee as DunningState,$ as EventEmitter,Z as InvoiceStatuses,_ as PLAN_CURRENCY_CODES,q as PLAN_CURRENCY_OPTIONS,we as PUSH_SERVICE_WORKER_SCRIPT,w as PushApi,v as SDKEvent,y as SettingsApi,X as SubscriptionItemType,Y as SubscriptionStatus,m as UserApi,k as WorkspaceApi,de as calculateBillableSeats,he as calculateSeatOverageCents,pe as calculateTotalSubscriptionCents,T as cleanBBParams,R as createBBUrl,x as createCheckoutRedirectUrls,me as default,S as eventEmitter,A as formatCents,B as formatOverageRate,M as formatOverageRateWithLabel,D as formatQuotaIncludedOverage,G as formatQuotaWithPrice,ae as getAvailableCurrenciesFromPlans,se as getBasePriceCents,ce as getBillingIntervalAndCurrencyFromPriceId,L as getCurrencyFlag,N as getCurrencySymbol,oe as getDisplayCurrency,le as getPerSeatPriceCents,te as getPricingVariant,H as getQuotaDisplayValue,ie as getQuotaDisplayWithVariant,ne as getQuotaOverageCents,V as getQuotaUnitLabelFromName,ue as getSeatPricing,re as getStripePriceIdForInterval,P as invalidateQuotaUsage,E as invalidateSubscription,C as readBBParams,fe as resolveMaxUsers,j as safeRedirect,ge as validateInvite,W as validateRedirectUrl};
|
|
1
|
+
let e=!0;function t(t,...s){e&&function(){try{const e="undefined"!=typeof globalThis?globalThis:null;return"development"===e?.process?.env?.NODE_ENV}catch{return!1}}()&&console.error(t,...s)}async function s(e,t){try{const s=await e.json();return s?.message||s?.error||t}catch{return t}}async function r(e){const t=await e.text();if(!t)throw new Error("Empty response body");try{return JSON.parse(t)}catch(e){throw new Error(`Invalid JSON response: ${t.substring(0,100)}${t.length>100?"...":""}`)}}async function n(e,t="Request failed"){if(!e.ok){let s=t;try{const t=await r(e);s=t.message||t.error||s}catch{s=function(e,t){const s={400:"Bad Request",401:"Unauthorized - Please check your session",403:"Forbidden - You do not have permission",404:"Resource not found",500:"Internal server error",502:"Bad Gateway",503:"Service unavailable"}[e.status]||e.statusText||t;return new Error(`${t} (${e.status}: ${s})`)}(e,t).message}throw new Error(s)}try{return await r(e)}catch(e){if(e instanceof Error&&e.message.includes("Invalid JSON"))throw e;throw new Error("Failed to parse response as JSON")}}class o extends Error{constructor(e,t,s,r){super(e),this.code=t,this.context=s,this.originalError=r,this.name="SDKError","undefined"!=typeof Error&&"captureStackTrace"in Error&&Error.captureStackTrace(this,o)}}const a=new class{constructor(){this.config={enableConsoleLogging:!0,showUserNotifications:!1}}configure(t){this.config={...this.config,...t},void 0!==t.enableConsoleLogging&&function(t){void 0!==t.enableLogging&&(e=t.enableLogging)}({enableLogging:t.enableConsoleLogging})}handleError(e,s={}){if(function(e){return e instanceof Error&&("AbortError"===e.name||"ERR_CANCELED"===e.code)}(e))return;const r=e instanceof Error?e:new o("string"==typeof e?e:"An unknown error occurred","UNKNOWN_ERROR",s),n=r instanceof o?r:new o(r.message,"SDK_ERROR",s,r);if(this.config.enableConsoleLogging&&t(`[SDK Error] ${s.component||"Unknown"}:`,{message:n.message,code:n.code,context:n.context,originalError:n.originalError,stack:n.stack}),this.config.onError)try{this.config.onError(n,s)}catch(e){!function(e,...t){console.error(e,...t)}("[SDK Error Handler] Error in custom error callback:",e)}this.config.showUserNotifications&&this.notifyUser(n,s)}notifyUser(e,t){"undefined"!=typeof window&&window.dispatchEvent&&window.dispatchEvent(new CustomEvent("sdk-error",{detail:{error:e,context:t}}))}wrapAsync(e,t){return(...s)=>e(...s).catch(e=>{throw this.handleError(e,t),e})}wrapSync(e,t){return(...s)=>{try{return e(...s)}catch(e){throw this.handleError(e,t),e}}}};function i(e,t={}){a.handleError(e,t)}const c="saas-session-id";function u(){if("undefined"==typeof window)return null;try{return function(e){if("undefined"==typeof window)return null;try{return localStorage.getItem(e)}catch(t){return i(t,{component:"storage",action:"getStorageItem",metadata:{key:e}}),null}}(c)}catch(e){return i(e,{component:"auth-utils",action:"getSessionId",metadata:{key:c}}),null}}function l(){const e=u(),t={};return e&&(t["x-session-id"]=e),t}const d="SDK is not ready (missing serverUrl, version, or orgId)";class h{constructor(e){this.serverUrl=e.serverUrl,this.version=e.version,this.orgId=e.orgId,this.requireOrgId=e.requireOrgId??!1,this.basePath=e.basePath??"public",this._sessionId=e.sessionId,this._timeout=e.timeout??3e4,this._maxRetries=e.maxRetries??0,this._debug=e.debug??!1,this._customHeaders=e.headers??{},this._onError=e.onError,this._fetch=e.fetch??globalThis.fetch}ensureReady(){if(!this.serverUrl?.trim()||!this.version)throw new Error(d);if(this.requireOrgId&&!this.orgId?.trim())throw new Error(d)}get baseUrl(){return this.ensureReady(),`${this.serverUrl}/api/${this.version}/${this.basePath}`}getAuthHeaders(){return this._sessionId?{"x-session-id":this._sessionId}:l()}url(e){const t=e.startsWith("/")?e.slice(1):e;return`${this.baseUrl.endsWith("/")?this.baseUrl.slice(0,-1):this.baseUrl}/${t}`}buildHeaders(e){const t={...this._customHeaders,...this.getAuthHeaders()};return e.headers&&Object.assign(t,e.headers),null==e.body||t["Content-Type"]||(t["Content-Type"]="application/json"),t}async executeFetch(e,t){const s=this.url(e),r=(t.method??"GET").toUpperCase(),n=this.buildHeaders(t),o={...t,headers:n};let a;if(this._timeout>0){const e=new AbortController;a=setTimeout(()=>e.abort(),this._timeout),o.signal=t.signal?AbortSignal.any([t.signal,e.signal]):e.signal}const i=async t=>{try{const e=this._fetch.bind(globalThis),n=await e(s,o);if(this._debug&&console.log(`[BuildBase] ${r} ${s} → ${n.status}`),n.status>=500&&t<this._maxRetries){const e=Math.min(1e3*Math.pow(2,t),1e4);return this._debug&&console.log(`[BuildBase] Retrying in ${e}ms (attempt ${t+1}/${this._maxRetries})`),await new Promise(t=>setTimeout(t,e)),i(t+1)}return n}catch(s){if(s instanceof Error&&"AbortError"===s.name){if(void 0!==a){const t=new Error(`Request timeout after ${this._timeout}ms: ${r} ${e}`);throw this._onError?.(t,{method:r,path:e}),t}throw s}if(t<this._maxRetries){const e=Math.min(1e3*Math.pow(2,t),1e4);return this._debug&&console.log(`[BuildBase] Network error, retrying in ${e}ms (attempt ${t+1}/${this._maxRetries})`),await new Promise(t=>setTimeout(t,e)),i(t+1)}throw s instanceof Error&&this._onError?.(s,{method:r,path:e}),s}};try{return await i(0)}finally{void 0!==a&&clearTimeout(a)}}async fetchJson(e,t={},s="Request failed"){this.ensureReady();try{const r=await this.executeFetch(e,t);return await n(r,s)}catch(s){throw s instanceof Error&&this._onError?.(s,{method:(t.method??"GET").toUpperCase(),path:e}),s}}async fetchResponse(e,t={}){return this.ensureReady(),this.executeFetch(e,t)}}class p extends h{constructor(e){super(e)}async requestAuth(e){const t=`${this.serverUrl}/api/${this.version}/auth/request`,s=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!s.ok){let e="Failed to initiate authentication";try{e=(await s.json()).message||e}catch{e=`Failed to initiate authentication (${s.status}: ${s.statusText})`}throw new Error(e)}return s.json()}async getProfile(e,t){return this.fetchJson("profile",{headers:{"x-session-id":e},signal:t},"Failed to fetch user profile")}}class f extends h{constructor(e){super({...e,basePath:"beta",requireOrgId:!0})}getAuthHeaders(){return{}}async fetchConfig(){return this.fetchJson(`config?orgId=${encodeURIComponent(this.orgId)}`,{},"Failed to fetch beta form configuration")}async submitBetaUser(e){return this.fetchJson("submit",{method:"POST",body:JSON.stringify(e)},"Failed to submit beta user request")}}class g{constructor(e){this.api=new f(e),this.orgId=e.orgId}async fetchConfig(){return this.api.fetchConfig()}async submitBetaUser(e){const t=e?.context??{},s=t?.country??("undefined"!=typeof navigator&&navigator.language?navigator.language.split("-")[1]:void 0),r=t?.language??("undefined"!=typeof navigator&&navigator.language?navigator.language.split("-")[0]:void 0),n=t?.timezone??("undefined"!=typeof Intl&&Intl.DateTimeFormat?Intl.DateTimeFormat().resolvedOptions().timeZone:void 0),o=t?.currency??("undefined"!=typeof Intl&&Intl.NumberFormat&&Intl.NumberFormat().resolvedOptions().currency?Intl.NumberFormat().resolvedOptions().currency:void 0);return this.api.submitBetaUser({orgId:this.orgId,formData:{...e,country:s,language:r,timezone:n,currency:o}})}}class w extends h{constructor(e){super({...e,requireOrgId:!0})}async getVapidPublicKey(){return this.fetchJson("push/vapid-public-key")}async subscribe(e,t){await this.fetchJson("push/subscribe",{method:"POST",body:JSON.stringify({endpoint:e.endpoint,keys:e.keys,userAgent:t})})}async unsubscribe(e){await this.fetchJson("push/unsubscribe",{method:"DELETE",body:JSON.stringify({endpoint:e})})}}class y extends h{constructor(e){super({...e,requireOrgId:!0})}async getSettings(e){return this.fetchJson(`${this.orgId}/settings`,{signal:e},"Failed to fetch settings")}}class m extends h{constructor(e){super(e)}async getAttributes(e){const t=await this.fetchResponse("users/attributes",{signal:e});if(!t.ok)throw new Error(await s(t,"Failed to fetch user attributes"));const r=await t.json();return r&&"object"==typeof r&&!Array.isArray(r)?r:{}}async updateAttributes(e){return this.fetchJson("users/attributes",{method:"PATCH",body:JSON.stringify({attributes:e})},"Failed to update user attributes")}async updateAttribute(e,t){return this.fetchJson(`users/attributes/${e}`,{method:"PATCH",body:JSON.stringify({value:t})},"Failed to update user attribute")}async getFeatures(e){const t=await this.fetchResponse("users/features",{signal:e});if(!t.ok)throw new Error(await s(t,"Failed to fetch user features"));const r=await t.json();return"object"==typeof r&&null!==r?r:{}}}class k extends h{constructor(e){super({...e,requireOrgId:!0})}async getWorkspaces(){return this.fetchJson("workspaces",{},"Failed to fetch workspaces")}async createWorkspace(e){return this.fetchJson("workspaces",{method:"POST",body:JSON.stringify(e)},"Failed to create workspace")}async updateWorkspace(e,t){return this.fetchJson(`workspaces/${e}`,{method:"PUT",body:JSON.stringify(t)},"Failed to update workspace")}async deleteWorkspace(e){return this.fetchJson(`workspaces/${e}`,{method:"DELETE"},"Failed to delete workspace")}async getWorkspaceUsers(e){return this.fetchJson(`workspaces/${e}/users`,{},"Failed to fetch workspace users")}async addUser(e,t){return this.fetchJson(`workspaces/${e}/users/add`,{method:"POST",body:JSON.stringify(t)},"Failed to invite member")}async removeUser(e,t){return this.fetchJson(`workspaces/${e}/users/${t}`,{method:"DELETE"},"Failed to remove user")}async updateUser(e,t,s){return this.fetchJson(`workspaces/${e}/users/${t}`,{method:"PATCH",body:JSON.stringify(s)},"Failed to update user")}async updateSettings(e){return this.fetchJson("workspaces/settings",{method:"PATCH",body:JSON.stringify(e)},"Failed to update workspace settings")}async updateWorkspacePermissions(e,t){return this.fetchJson(`workspaces/${e}/permissions`,{method:"PATCH",body:JSON.stringify({permissions:t})},"Failed to update workspace permissions")}async getFeatures(){return this.fetchJson("workspaces/features",{},"Failed to fetch features")}async updateFeature(e,t,s){return this.fetchJson(`workspaces/${e}/features`,{method:"PATCH",body:JSON.stringify({features:{[t]:s}})},"Failed to update feature")}async getWorkspace(e){return this.fetchJson(`workspaces/${e}`,{},"Failed to fetch workspace")}async getProfile(){return this.fetchJson("profile",{},"Failed to fetch profile")}async updateUserProfile(e){return this.fetchJson("profile",{method:"PATCH",body:JSON.stringify(e)},"Failed to update user profile")}async getCurrentSubscription(e){const t=await this.fetchResponse(`workspaces/${e}/subscription`);if(!t.ok){let e="Failed to fetch subscription";try{e=(await t.json()).message||e}catch{e=404===t.status?"Workspace not found or no subscription available":401===t.status?"Unauthorized - Please check your session":`Failed to fetch subscription (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch subscription");return s.data||s}return s}async getPlanGroup(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/plan-group`);if(!t.ok){let e="Failed to fetch plan group";try{e=(await t.json()).message||e}catch{e=404===t.status?"No plan group found for this workspace":401===t.status?"Unauthorized - Please check your session":`Failed to fetch plan group (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch plan group");return s.data||s}return s}async getPlanGroupByVersion(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/plan-group?groupVersionId=${encodeURIComponent(t)}`);if(!s.ok){let e="Failed to fetch plan group version";try{e=(await s.json()).message||e}catch{e=404===s.status?"Plan group version not found":401===s.status?"Unauthorized - Please check your session":`Failed to fetch plan group version (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to fetch plan group version");return r.data||r}return r}async getPlanGroupVersions(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/plan-group/versions`);if(!t.ok){let e="Failed to fetch plan group versions";try{e=(await t.json()).message||e}catch{e=404===t.status?"No plan group versions found":401===t.status?"Unauthorized - Please check your session":`Failed to fetch plan group versions (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch plan group versions");return s.data||s}return s}async getPublicPlans(e){if(!this.orgId)throw new Error("orgId is required for getPublicPlans");const t=await this.fetchResponse(`${this.orgId}/plans/${encodeURIComponent(e)}`);if(!t.ok){let s="Failed to fetch plans";try{s=(await t.json()).message||s}catch{s=404===t.status?`Plans "${e}" not found`:`Failed to fetch plans (${t.status}: ${t.statusText})`}throw new Error(s)}const s=await t.json();if(void 0!==s.success&&!s.success)throw new Error(s.message||"Failed to fetch plans");return s.data??s}async getPlanGroupVersion(e){const t=await this.fetchResponse(`plan-group-versions/${e}`);if(!t.ok){let e="Failed to fetch plan group version";try{e=(await t.json()).message||e}catch{e=404===t.status?"Plan group version not found":401===t.status?"Unauthorized - Please check your session":`Failed to fetch plan group version (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch plan group version");return s.data||s}return s}async createCheckoutSession(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/checkout`,{method:"POST",body:JSON.stringify(t)});if(!s.ok){let e="Failed to create checkout session";try{e=(await s.json()).message||e}catch{e=`Failed to create checkout session (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to create checkout session");return r.data||r}return r}async updateSubscription(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription`,{method:"PATCH",body:JSON.stringify(t)});if(!s.ok){let e="Failed to update subscription";try{e=(await s.json()).message||e}catch{e=`Failed to update subscription (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to update subscription");return r.data?.checkoutUrl||r.checkoutUrl,r.data||r}return r.checkoutUrl,r}async createBillingPortalSession(e,t){return this.fetchJson(`workspaces/${e}/subscription/billing-portal`,{method:"POST",body:JSON.stringify(t?{returnUrl:t}:{})})}async listInvoices(e,t=10,s){const r=new URLSearchParams;r.append("limit",t.toString()),s&&r.append("starting_after",s);const n=await this.fetchResponse(`workspaces/${e}/subscription/invoices?${r.toString()}`,{});if(!n.ok){let e="Failed to fetch invoices";try{e=(await n.json()).message||e}catch{e=404===n.status?"Workspace not found or no invoices available":401===n.status?"Unauthorized - Please check your session":`Failed to fetch invoices (${n.status}: ${n.statusText})`}throw new Error(e)}const o=await n.json();if(void 0!==o.success){if(!o.success)throw new Error(o.message||"Failed to fetch invoices");return o}return o}async getInvoice(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/invoices/${t}`,{});if(!s.ok){let e="Failed to fetch invoice";try{e=(await s.json()).message||e}catch{e=404===s.status?"Invoice not found":401===s.status?"Unauthorized - Please check your session":`Failed to fetch invoice (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to fetch invoice");return r}return r}async cancelSubscriptionAtPeriodEnd(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/cancel-at-period-end`,{method:"POST"});if(!t.ok){let e="Failed to cancel subscription";try{e=(await t.json()).message||e}catch{e=404===t.status?"Subscription not found":401===t.status?"Unauthorized - Please check your session":`Failed to cancel subscription (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to cancel subscription");return s.data||s}return s}async resumeSubscription(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/resume`,{method:"POST"});if(!t.ok){let e="Failed to resume subscription";try{e=(await t.json()).message||e}catch{e=404===t.status?"Subscription not found":401===t.status?"Unauthorized - Please check your session":`Failed to resume subscription (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to resume subscription");return s.data||s}return s}async recordUsage(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/usage`,{method:"POST",body:JSON.stringify(t)});if(!s.ok){let e="Failed to record usage";try{e=(await s.json()).message||e}catch{e=`Failed to record usage (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to record usage");return r.data||r}return r}async recordUsageBatch(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/usage/batch`,{method:"POST",body:JSON.stringify(t)});if(!s.ok){let e="Failed to record batch usage";try{e=(await s.json()).message||e}catch{e=`Failed to record batch usage (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();return r.data||r}async getQuotaUsageStatus(e,t){const s=await this.fetchResponse(`workspaces/${e}/subscription/usage/status?quotaSlug=${encodeURIComponent(t)}`);if(!s.ok){let e="Failed to fetch quota usage status";try{e=(await s.json()).message||e}catch{e=404===s.status?"Workspace not found or no subscription available":401===s.status?"Unauthorized - Please check your session":`Failed to fetch quota usage status (${s.status}: ${s.statusText})`}throw new Error(e)}const r=await s.json();if(void 0!==r.success){if(!r.success)throw new Error(r.message||"Failed to fetch quota usage status");return r.data||r}return r}async getAllQuotaUsage(e){const t=await this.fetchResponse(`workspaces/${e}/subscription/usage/all`);if(!t.ok){let e="Failed to fetch all quota usage";try{e=(await t.json()).message||e}catch{e=404===t.status?"Workspace not found or no subscription available":401===t.status?"Unauthorized - Please check your session":`Failed to fetch all quota usage (${t.status}: ${t.statusText})`}throw new Error(e)}const s=await t.json();if(void 0!==s.success){if(!s.success)throw new Error(s.message||"Failed to fetch all quota usage");return s.data||s}return s}async getUsageLogs(e,t){const s=new URLSearchParams;t?.quotaSlug&&s.append("quotaSlug",t.quotaSlug),t?.from&&s.append("from",t.from),t?.to&&s.append("to",t.to),t?.source&&s.append("source",t.source),t?.page&&s.append("page",t.page.toString()),t?.limit&&s.append("limit",t.limit.toString());const r=s.toString(),n=`workspaces/${e}/subscription/usage/logs${r?`?${r}`:""}`,o=await this.fetchResponse(n);if(!o.ok){let e="Failed to fetch usage logs";try{e=(await o.json()).message||e}catch{e=404===o.status?"Workspace not found":401===o.status?"Unauthorized - Please check your session":`Failed to fetch usage logs (${o.status}: ${o.statusText})`}throw new Error(e)}const a=await o.json();if(void 0!==a.success){if(!a.success)throw new Error(a.message||"Failed to fetch usage logs");return a.data||a}return a}}var b;!function(e){e.V1="v1"}(b||(b={}));const E={UserCreated:"user:created",UserUpdated:"user:updated",WorkspaceChanged:"workspace:changed",WorkspaceUpdated:"workspace:updated",WorkspaceUserAdded:"workspace:user-added",WorkspaceUserRemoved:"workspace:user-removed",WorkspaceUserRoleChanged:"workspace:user-role-changed",WorkspaceCreated:"workspace:created",WorkspaceDeleted:"workspace:deleted"};class v{constructor(){this.callbacks=null}setCallbacks(e){this.callbacks=e}getCallbacks(){return this.callbacks}async emit(e,t){if(this.callbacks?.handleEvent)try{await this.callbacks.handleEvent(e,t)}catch(t){i(t,{component:"EventEmitter",action:"emit",metadata:{eventType:e}})}}async emitUserCreated(e){await this.emit(E.UserCreated,{user:e})}async emitUserUpdated(e,t){await this.emit(E.UserUpdated,{user:e,previousUser:t})}async emitWorkspaceChanged(e,t){await this.emit(E.WorkspaceChanged,{workspace:e,previousWorkspace:t})}async emitWorkspaceUpdated(e){await this.emit(E.WorkspaceUpdated,{workspace:e})}async emitWorkspaceUserAdded(e,t,s){await this.emit(E.WorkspaceUserAdded,{userId:e,workspace:t,role:s})}async emitWorkspaceUserRemoved(e,t,s){await this.emit(E.WorkspaceUserRemoved,{userId:e,workspace:t,role:s})}async emitWorkspaceUserRoleChanged(e,t,s,r){await this.emit(E.WorkspaceUserRoleChanged,{userId:e,workspace:t,previousRole:s,newRole:r})}async emitWorkspaceCreated(e){await this.emit(E.WorkspaceCreated,{workspace:e})}async emitWorkspaceDeleted(e){await this.emit(E.WorkspaceDeleted,{workspace:e})}}const S=new v,$=new Set;function P(){$.forEach(e=>e())}const U=new Set;function R(){U.forEach(e=>e())}const I="bb";function F(e,t){let s;try{const e=t||("undefined"!=typeof window?window.location.href:"https://localhost");s=new URL(e),s.search=""}catch{s=new URL("https://localhost")}return s.searchParams.set(I,function(e){return Object.entries(e).filter(([,e])=>null!=e&&""!==e).map(([e,t])=>`${encodeURIComponent(e)}:${encodeURIComponent(t)}`).join(",")}(e)),s.toString()}function W(e,t){const s=t||("undefined"!=typeof window?window.location.href:void 0);return{successUrl:F({action:"checkout",status:"success",ws:e,screen:"subscription"},s),cancelUrl:F({action:"checkout",status:"cancel",ws:e,screen:"subscription"},s)}}function _(){if("undefined"==typeof window)return null;try{const e=new URLSearchParams(window.location.search).get(I);if(!e)return null;const t=function(e){const t={};if(!e)return t;const s=e.split(",");for(const e of s){const s=e.indexOf(":");if(-1===s)continue;const r=decodeURIComponent(e.slice(0,s)),n=decodeURIComponent(e.slice(s+1));r&&(t[r]=n)}return t}(e);return Object.keys(t).length>0?t:null}catch{return null}}function C(){if("undefined"!=typeof window)try{const e=new URL(window.location.href);e.searchParams.has(I)&&(e.searchParams.delete(I),window.history.replaceState({},"",e.toString()))}catch{}}function T(e){if(!e||"string"!=typeof e)return null;try{const t=new URL(e);return"https:"===t.protocol?e:"http:"!==t.protocol||"localhost"!==t.hostname&&"127.0.0.1"!==t.hostname&&"::1"!==t.hostname?null:e}catch{return null}}function O(e,t="/"){const s=T(e);window.location.href=s||t}const A={usd:"$",eur:"€",gbp:"£",jpy:"¥",cad:"CA$",aud:"A$",chf:"CHF",cny:"¥",hkd:"HK$",sgd:"S$",inr:"₹",mxn:"MX$",brl:"R$",nzd:"NZ$",sek:"kr",nok:"kr",dkk:"kr",pln:"zł",thb:"฿"},x={usd:"🇺🇸",eur:"🇪🇺",gbp:"🇬🇧",jpy:"🇯🇵",cad:"🇨🇦",aud:"🇦🇺",chf:"🇨🇭",cny:"🇨🇳",hkd:"🇭🇰",sgd:"🇸🇬",inr:"🇮🇳",mxn:"🇲🇽",brl:"🇧🇷",nzd:"🇳🇿",sek:"🇸🇪",nok:"🇳🇴",dkk:"🇩🇰",pln:"🇵🇱",thb:"🇹🇭"};function j(e){return e&&e.trim()?x[e.trim().toLowerCase()]??"":""}function N(e){if(!e||!e.trim())return"";const t=e.trim().toLowerCase();return A[t]??t.toUpperCase()}const L=["usd","eur","gbp","jpy","cad","aud","chf","cny","hkd","sgd","inr","mxn","brl","nzd","sek","nok","dkk","pln","thb"],J=L.map(e=>({value:e,label:`${e.toUpperCase()} (${N(e)})`}));function B(e,t){return N(t)+(e/100).toFixed(2)}const M={unit:"unit",units:"units",included:"Included",afterThat:"after that",afterIncluded:"After included"};function q(e,t,s,r){if(null==e||e<0)return null;const n={...M,...r},o=null!=t&&t>=1?t:1,a=N(s),i=(e/100).toFixed(2);return 1===o?`${a}${i}/${n.unit}`:`${a}${i}/${o.toLocaleString()} ${n.units}`}function V(e,t,s,r,n,o){if(null==e||e<0)return null;const a={...M,...o},i=null!=t&&t>=1?t:1,c=N(r),u=(e/100).toFixed(2);if(s){const e=n??(s.endsWith("s")?s:`${s}s`);return i>=2?`${c}${u}/${i.toLocaleString()} ${e}`:`${c}${u}/${s}`}return 1===i?`${c}${u}/${a.unit}`:`${c}${u}/${i.toLocaleString()} ${a.units}`}function K(e,t="unit"){const s=(e||"").trim().toLowerCase();if(!s)return t;const r=s.split(/\s+/)[0]??s;return new Set(["series","species","status","analysis","basis","bus","campus","corpus","axis"]).has(r)?r:r.endsWith("ies")&&r.length>3?r.slice(0,-3)+"y":r.endsWith("ses")||r.endsWith("xes")||r.endsWith("zes")||r.endsWith("ches")||r.endsWith("shes")?r.slice(0,-2):r.endsWith("s")&&!r.endsWith("ss")&&r.length>1?r.slice(0,-1):r||t}function z(e,t,s,r,n,o,a){const i={...M,...a},c=o??(s.endsWith("s")?s:`${s}s`),u=null!=n&&n>=2?`${n.toLocaleString()} ${c}`:s;return null!=e&&null!=t?`${i.included}: ${e.toLocaleString()}, ${i.afterThat} ${B(t,r)}/${u}`:null!=e?`${i.included}: ${e.toLocaleString()}`:null!=t?`${i.afterIncluded}: ${B(t,r)}/${u}`:"—"}function D(e,t){if(null==e)return null;const s=e[t??"monthly"];return s?{included:s.included,...void 0!==s.overage&&{overage:s.overage},...void 0!==s.unitSize&&{unitSize:s.unitSize}}:null}const G={included:"included",then:"then"};function H(e,t,s={}){const{overageInCents:r=!0,currency:n}=s,o=s.labels??G,a=s.currencySymbol??N(n??"");if(null==e)return"—";const{included:i,overage:c}=e,u=`${i} ${o.included}`;if(null==c)return u;const l=r?c/100:c,d="number"==typeof l&&Number.isFinite(l)?l.toFixed(2):String(c),h=t&&"unitSize"in e&&null!=e.unitSize&&e.unitSize>0?` / ${e.unitSize.toLocaleString()} ${t}`:t?` / ${t}`:"";return`${u}, ${o.then} ${a}${d}${h}`}const Q={Monthly:"monthly",Yearly:"yearly",Quarterly:"quarterly"},Y={Active:"active",Trialing:"trialing",Canceled:"canceled",PastDue:"past_due",Paused:"paused",Incomplete:"incomplete",Unpaid:"unpaid"},Z={Draft:"draft",Open:"open",Paid:"paid",Uncollectible:"uncollectible",Void:"void"},X={Feature:"feature",Limit:"limit",Quota:"quota"},ee={None:"none",Notified:"notified",Warning:"warning",Final:"final",Suspended:"suspended"};function te(e,t){const s=e.pricingVariants;if(!s?.length)return null;const r=t.toLowerCase();return s.find(e=>e.currency?.toLowerCase()===r)??null}function se(e,t,s){const r=te(e,t);if(!r?.basePricing)return null;const n=r.basePricing[s];return null!=n?n:null}function re(e,t,s){const r=te(e,t);if(!r?.stripePrices)return null;const n=s===Q.Monthly?"monthlyPriceId":s===Q.Yearly?"yearlyPriceId":"quarterlyPriceId",o=s===Q.Monthly?"monthly":s===Q.Yearly?"yearly":void 0;return r.stripePrices[n]??(o?r.stripePrices[o]:void 0)??null}function ne(e,t,s,r){const n=te(e,t),o=n?.quotaOverages?.[s];if(o)return o[r]}function oe(e,t){const s=te(e,t);return s?s.currency:e.plan?.currency??""}function ae(e){const t=new Set;for(const s of e)s.pricingVariants?.forEach(e=>{e.currency&&t.add(e.currency.toLowerCase())});return Array.from(t).sort()}function ie(e,t,s,r){const n=e.quotas?.[s];if(null==n)return null;const o=n[r];if(!o)return null;const a=ne(e,t,s,r);return{included:o.included,...void 0!==o.unitSize&&{unitSize:o.unitSize},...void 0!==a&&{overage:a}}}function ce(e,t){if(!e)return null;for(const s of t){const t=s.pricingVariants;if(t?.length)for(const s of t){const t=s.stripePrices;if(t){if(t.monthlyPriceId===e||t.monthly===e)return{interval:"monthly",currency:s.currency};if(t.yearlyPriceId===e||t.yearly===e)return{interval:"yearly",currency:s.currency};if(t.quarterlyPriceId===e)return{interval:"quarterly",currency:s.currency}}}}return null}function ue(e,t){const s=te(e,t);return s?.seatPricing?.enabled?s.seatPricing:null}function le(e,t,s){const r=ue(e,t);return r?.perSeat?r.perSeat[s]??null:null}function de(e,t){return Math.max(0,e-(t||0))}function he(e,t,s,r){const n=ue(e,t);if(!n)return null;return de(r,n.includedSeats)*(le(e,t,s)??0)}function pe(e,t,s,r){const n=se(e,t,s);if(null===n)return null;if(void 0===r)return n;return n+(he(e,t,s,r)??0)}function fe(e){const{planVersion:t,currency:s="usd",settingsMaxUsers:r}=e;if(t){const e=ue(t,s);if(e)return{maxUsers:e.maxSeats??0,source:"seat_pricing",includedSeats:e.includedSeats??0,hasSeatPricing:!0}}return null!=r&&r>0?{maxUsers:r,source:"settings",includedSeats:0,hasSeatPricing:!1}:{maxUsers:0,source:"none",includedSeats:0,hasSeatPricing:!1}}function ge(e){const{memberCount:t,maxUsersConfig:s,hasSubscription:r=!0,requireSubscription:n=!1}=e;if(n&&!r)return{canInvite:!1,blockReason:"no_subscription",blockMessageKey:"users.subscriptionRequired",blockMessageValues:{}};const{maxUsers:o,source:a}=s;if(o<=0)return{canInvite:!0,blockReason:null,blockMessageKey:null,blockMessageValues:null};if(t>=o){return{canInvite:!1,blockReason:{seat_pricing:"seat_limit_reached",settings:"settings_user_limit_reached"}[a]??"seat_limit_reached",blockMessageKey:{seat_pricing:"users.seatLimitMessage",settings:"users.settingsLimitMessage"}[a]??"users.memberLimitMessage",blockMessageValues:{maxUsers:o}}}return{canInvite:!0,blockReason:null,blockMessageKey:null,blockMessageValues:null}}const we={WORKSPACE_SETTINGS_VIEW:"workspace:settings:view",WORKSPACE_SETTINGS_EDIT:"workspace:settings:edit",WORKSPACE_DELETE:"workspace:delete",WORKSPACE_MEMBERS_VIEW:"workspace:members:view",WORKSPACE_MEMBERS_INVITE:"workspace:members:invite",WORKSPACE_MEMBERS_REMOVE:"workspace:members:remove",WORKSPACE_MEMBERS_ROLE_CHANGE:"workspace:members:role-change",WORKSPACE_FEATURES_VIEW:"workspace:features:view",WORKSPACE_FEATURES_EDIT:"workspace:features:edit",WORKSPACE_BILLING_VIEW:"workspace:billing:view",WORKSPACE_BILLING_MANAGE:"workspace:billing:manage",WORKSPACE_USAGE_VIEW:"workspace:usage:view"},ye=Object.values(we),me={admin:ye.filter(e=>e!==we.WORKSPACE_DELETE),member:[we.WORKSPACE_SETTINGS_VIEW,we.WORKSPACE_MEMBERS_VIEW,we.WORKSPACE_FEATURES_VIEW,we.WORKSPACE_BILLING_VIEW,we.WORKSPACE_USAGE_VIEW],viewer:[we.WORKSPACE_SETTINGS_VIEW,we.WORKSPACE_MEMBERS_VIEW]};function ke(e){const t=new Set;for(const s of Object.values(e))for(const e of s)t.add(e);return Array.from(t)}function be(e){const{userId:t,workspace:s,settings:r,appPermissions:n}=e;if(!s||!t)return new Set;if(function(e,t){if(!t)return!1;const s=(r=e.createdBy)?"string"==typeof r?r:"object"==typeof r&&"_id"in r&&"string"==typeof r._id?r._id:null:null;var r;return null!==s&&s===t}(s,t)){const e=new Set(ye);if(n)for(const t of ke(n))e.add(t);if(s.permissions)for(const t of ke(s.permissions))e.add(t);if(r?.workspace?.permissions)for(const t of ke(r.workspace.permissions))e.add(t);return e}const o=e.workspaceRole??function(e,t){if(!t||!e.users||!Array.isArray(e.users))return null;const s=e.users.find(e=>"string"==typeof e?e===t:"object"==typeof e&&null!==e&&"_id"in e&&e._id===t);return s&&"object"==typeof s&&"role"in s&&"string"==typeof s.role?s.role:null}(s,t);if(!o)return new Set;const a=s.permissions,i=r?.workspace?.permissions,c=e=>e.filter(e=>e.startsWith("workspace:")),u=e=>e.filter(e=>!e.startsWith("workspace:")),l=a?.[o]?c(a[o]):[],d=i?.[o]?c(i[o]):[],h=me[o]??[];let p;if(l.length>0)p=l;else if(d.length>0)p=d;else if(h.length>0)p=h;else{p=me[r?.workspace?.defaultRole??"member"]??me.member??[]}const f=new Set(p),g=a?.[o]?u(a[o]):[],w=n?.[o]?u(n[o]):[],y=g.length>0?g:w;for(const e of y)f.add(e);return function(e,t,s){if(!s?.workspace)return;const{canInviteMembers:r}=s.workspace;(!1===r||"admin-only"===r&&"admin"!==t)&&e.delete(we.WORKSPACE_MEMBERS_INVITE)}(f,o,r),f}function Ee(e,t){const s=be(t);return Array.isArray(e)?e.every(e=>s.has(e)):s.has(e)}const ve="\n// BuildBase Push Notification Service Worker\n// Place this file in your app's public directory (e.g. public/push-sw.js)\n\nself.addEventListener('push', function(event) {\n if (!event.data) return;\n\n try {\n var payload = event.data.json();\n var title = payload.title || 'Notification';\n var options = {\n body: payload.body || '',\n icon: payload.icon || undefined,\n badge: payload.icon || undefined,\n data: { url: payload.url, ...(payload.data || {}) },\n tag: 'buildbase-push-' + Date.now(),\n };\n\n event.waitUntil(\n self.registration.showNotification(title, options)\n );\n } catch (e) {\n console.error('[PushSW] Failed to show notification:', e);\n }\n});\n\nself.addEventListener('notificationclick', function(event) {\n event.notification.close();\n\n var url = event.notification.data && event.notification.data.url;\n if (url) {\n event.waitUntil(\n clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {\n for (var i = 0; i < clientList.length; i++) {\n var client = clientList[i];\n if (client.url === url && 'focus' in client) {\n return client.focus();\n }\n }\n if (clients.openWindow) {\n return clients.openWindow(url);\n }\n })\n );\n }\n});\n";var Se;function $e(e){const{serverUrl:t,orgId:s,version:r="v1",getSessionId:n,timeout:o,maxRetries:a,debug:i,headers:c,onError:u,fetch:l}=e;if(!t)throw new Error("BuildBase: serverUrl is required");if(!s)throw new Error("BuildBase: orgId is required");const d={...void 0!==o&&{timeout:o},...void 0!==a&&{maxRetries:a},...void 0!==i&&{debug:i},...c&&{headers:c},...u&&{onError:u},...l&&{fetch:l}},h=e=>{const n={serverUrl:t,version:r,orgId:s,sessionId:e,...d};return{workspace:new k(n),user:new m(n),settings:new y(n),push:new w(n)}},p=new k({serverUrl:t,version:r,orgId:s,...d}),f=e=>({workspace:{list:async()=>(await e()).workspace.getWorkspaces(),get:async t=>(await e()).workspace.getWorkspace(t),create:async t=>(await e()).workspace.createWorkspace(t),update:async(t,s)=>(await e()).workspace.updateWorkspace(t,s),delete:async t=>(await e()).workspace.deleteWorkspace(t)},users:{list:async t=>(await e()).workspace.getWorkspaceUsers(t),invite:async(t,s,r)=>(await e()).workspace.addUser(t,{email:s,role:r}),remove:async(t,s)=>(await e()).workspace.removeUser(t,s),updateRole:async(t,s,r)=>(await e()).workspace.updateUser(t,s,{role:r}),getProfile:async()=>(await e()).workspace.getProfile(),updateProfile:async t=>(await e()).workspace.updateUserProfile(t)},subscription:{get:async t=>(await e()).workspace.getCurrentSubscription(t),checkout:async(t,s)=>(await e()).workspace.createCheckoutSession(t,s),update:async(t,s)=>(await e()).workspace.updateSubscription(t,s),cancel:async t=>(await e()).workspace.cancelSubscriptionAtPeriodEnd(t),resume:async t=>(await e()).workspace.resumeSubscription(t),getBillingPortalUrl:async(t,s)=>(await e()).workspace.createBillingPortalSession(t,s)},plans:{getGroup:async t=>(await e()).workspace.getPlanGroup(t),getVersions:async t=>(await e()).workspace.getPlanGroupVersions(t),getPublic:e=>p.getPublicPlans(e),getVersion:e=>p.getPlanGroupVersion(e)},invoices:{list:async(t,s,r)=>(await e()).workspace.listInvoices(t,s,r),get:async(t,s)=>(await e()).workspace.getInvoice(t,s)},usage:{record:async(t,s)=>(await e()).workspace.recordUsage(t,s),recordBatch:async(t,s)=>(await e()).workspace.recordUsageBatch(t,s),getQuota:async(t,s)=>(await e()).workspace.getQuotaUsageStatus(t,s),getAll:async t=>(await e()).workspace.getAllQuotaUsage(t),getLogs:async(t,s)=>(await e()).workspace.getUsageLogs(t,s)},settings:{get:async()=>(await e()).settings.getSettings()},features:{list:async()=>(await e()).workspace.getFeatures(),update:async(t,s,r)=>(await e()).workspace.updateFeature(t,s,r)},permissions:{check:async(t,s,r)=>{const n=await e(),[o,a,i]=await Promise.all([n.workspace.getWorkspace(t),n.settings.getSettings(),n.workspace.getWorkspaceUsers(t)]),c=i.find(e=>("string"==typeof e.user?e.user:e.user._id)===s);return Ee(r,{userId:s,workspaceRole:c?.role??null,workspace:o,settings:a})},resolve:async(t,s)=>{const r=await e(),[n,o,a]=await Promise.all([r.workspace.getWorkspace(t),r.settings.getSettings(),r.workspace.getWorkspaceUsers(t)]),i=a.find(e=>("string"==typeof e.user?e.user:e.user._id)===s);return be({userId:s,workspaceRole:i?.role??null,workspace:n,settings:o})}}}),g=f(async()=>h(await(async()=>{if(!n)throw new Error("BuildBase: getSessionId callback is required for authenticated calls. Pass it in BuildBase({ getSessionId: ... }) or use withSession(id) / client.forSession(id).");const e=await n();if(!e)throw new Error("BuildBase: Not authenticated (getSessionId returned null)");return e})()));return{auth:async()=>{if(!n)return null;const e=await n();return e?{sessionId:e}:null},withSession:e=>{const t=h(e);return f(async()=>t)},client:{forSession:h},...g}}!function(e){e.loading="loading",e.redirecting="redirecting",e.authenticated="authenticated",e.unauthenticated="unauthenticated",e.authenticating="authenticating"}(Se||(Se={}));export{b as ApiVersion,p as AuthApi,Se as AuthStatus,I as BB_PARAM,h as BaseApi,g as BetaForm,Q as BillingIntervals,$e as BuildBase,A as CURRENCY_DISPLAY,x as CURRENCY_FLAG,me as DEFAULT_ROLE_PERMISSIONS,ee as DunningState,v as EventEmitter,Z as InvoiceStatuses,L as PLAN_CURRENCY_CODES,J as PLAN_CURRENCY_OPTIONS,ve as PUSH_SERVICE_WORKER_SCRIPT,we as Permission,w as PushApi,E as SDKEvent,y as SettingsApi,X as SubscriptionItemType,Y as SubscriptionStatus,m as UserApi,k as WorkspaceApi,de as calculateBillableSeats,he as calculateSeatOverageCents,pe as calculateTotalSubscriptionCents,C as cleanBBParams,F as createBBUrl,W as createCheckoutRedirectUrls,$e as default,S as eventEmitter,B as formatCents,q as formatOverageRate,V as formatOverageRateWithLabel,z as formatQuotaIncludedOverage,H as formatQuotaWithPrice,ae as getAvailableCurrenciesFromPlans,se as getBasePriceCents,ce as getBillingIntervalAndCurrencyFromPriceId,j as getCurrencyFlag,N as getCurrencySymbol,oe as getDisplayCurrency,le as getPerSeatPriceCents,te as getPricingVariant,D as getQuotaDisplayValue,ie as getQuotaDisplayWithVariant,ne as getQuotaOverageCents,K as getQuotaUnitLabelFromName,ue as getSeatPricing,re as getStripePriceIdForInterval,Ee as hasPermission,R as invalidateQuotaUsage,P as invalidateSubscription,_ as readBBParams,fe as resolveMaxUsers,be as resolvePermissions,O as safeRedirect,ge as validateInvite,T as validateRedirectUrl};
|
package/dist/react/index.d.ts
CHANGED
|
@@ -559,6 +559,8 @@ interface IWorkspace {
|
|
|
559
559
|
* When set, subscription UI only shows/uses this currency.
|
|
560
560
|
*/
|
|
561
561
|
billingCurrency?: string | null;
|
|
562
|
+
/** Per-workspace permission overrides. Takes priority over org-level settings.permissions. */
|
|
563
|
+
permissions?: Record<string, string[]>;
|
|
562
564
|
/** Workspace onboarding config. Set on creation based on org settings. SDK shows trial CTA. */
|
|
563
565
|
pendingOnboarding?: {
|
|
564
566
|
mode: 'trial';
|
|
@@ -753,6 +755,8 @@ interface ISettings {
|
|
|
753
755
|
canCreateWorkspace: boolean | 'owner-only';
|
|
754
756
|
/** Whether members can invite others. false = disabled, 'admin-only' = restricted */
|
|
755
757
|
canInviteMembers: boolean | 'admin-only';
|
|
758
|
+
/** Custom role→permission mapping. Overrides SDK defaults when provided by backend. */
|
|
759
|
+
permissions?: Record<string, string[]>;
|
|
756
760
|
/** Show workspace switcher in the UI */
|
|
757
761
|
showSwitcher: boolean;
|
|
758
762
|
/** Max workspaces a user can own. 0 = unlimited */
|
|
@@ -1006,6 +1010,10 @@ declare class WorkspaceApi extends BaseApi {
|
|
|
1006
1010
|
workspace: IWorkspace;
|
|
1007
1011
|
message: string;
|
|
1008
1012
|
}>;
|
|
1013
|
+
updateSettings(data: {
|
|
1014
|
+
permissions: Record<string, string[]>;
|
|
1015
|
+
}): Promise<any>;
|
|
1016
|
+
updateWorkspacePermissions(workspaceId: string, permissions: Record<string, string[]>): Promise<any>;
|
|
1009
1017
|
getFeatures(): Promise<IWorkspaceFeature[]>;
|
|
1010
1018
|
updateFeature(workspaceId: string, key: string, value: boolean): Promise<IWorkspace>;
|
|
1011
1019
|
getWorkspace(workspaceId: string): Promise<IWorkspace>;
|
|
@@ -1560,6 +1568,90 @@ declare function validateInvite(opts: {
|
|
|
1560
1568
|
requireSubscription?: boolean;
|
|
1561
1569
|
}): InviteValidation;
|
|
1562
1570
|
|
|
1571
|
+
/**
|
|
1572
|
+
* Role-based permission system.
|
|
1573
|
+
* Framework-agnostic — used by both React hooks and server-side BuildBase.
|
|
1574
|
+
*
|
|
1575
|
+
* Two types of permissions:
|
|
1576
|
+
*
|
|
1577
|
+
* 1. **Platform permissions** (ours) — prefixed with `workspace:`, control SDK
|
|
1578
|
+
* built-in features (settings, billing, members, usage). Defined as constants
|
|
1579
|
+
* in `Permission`. Enforced by the BuildBase backend.
|
|
1580
|
+
*
|
|
1581
|
+
* 2. **App permissions** (developer's) — any custom string (e.g. `projects:create`,
|
|
1582
|
+
* `reports:export`). Defined and enforced by the developer in their own app.
|
|
1583
|
+
* Flow through the same `usePermissions()` / `can()` / `<WhenPermission>` API.
|
|
1584
|
+
*
|
|
1585
|
+
* Both are resolved from the same role→permission map. Owner always gets all
|
|
1586
|
+
* platform permissions + any app permissions defined in the config.
|
|
1587
|
+
*/
|
|
1588
|
+
declare const Permission: {
|
|
1589
|
+
readonly WORKSPACE_SETTINGS_VIEW: "workspace:settings:view";
|
|
1590
|
+
readonly WORKSPACE_SETTINGS_EDIT: "workspace:settings:edit";
|
|
1591
|
+
readonly WORKSPACE_DELETE: "workspace:delete";
|
|
1592
|
+
readonly WORKSPACE_MEMBERS_VIEW: "workspace:members:view";
|
|
1593
|
+
readonly WORKSPACE_MEMBERS_INVITE: "workspace:members:invite";
|
|
1594
|
+
readonly WORKSPACE_MEMBERS_REMOVE: "workspace:members:remove";
|
|
1595
|
+
readonly WORKSPACE_MEMBERS_ROLE_CHANGE: "workspace:members:role-change";
|
|
1596
|
+
readonly WORKSPACE_FEATURES_VIEW: "workspace:features:view";
|
|
1597
|
+
readonly WORKSPACE_FEATURES_EDIT: "workspace:features:edit";
|
|
1598
|
+
readonly WORKSPACE_BILLING_VIEW: "workspace:billing:view";
|
|
1599
|
+
readonly WORKSPACE_BILLING_MANAGE: "workspace:billing:manage";
|
|
1600
|
+
readonly WORKSPACE_USAGE_VIEW: "workspace:usage:view";
|
|
1601
|
+
};
|
|
1602
|
+
type PermissionKey = (typeof Permission)[keyof typeof Permission];
|
|
1603
|
+
type RolePermissionMap = Record<string, string[]>;
|
|
1604
|
+
declare const DEFAULT_ROLE_PERMISSIONS: RolePermissionMap;
|
|
1605
|
+
interface WorkspaceLike {
|
|
1606
|
+
_id: string;
|
|
1607
|
+
createdBy: string | {
|
|
1608
|
+
_id: string;
|
|
1609
|
+
} | null | undefined;
|
|
1610
|
+
users?: Array<string | {
|
|
1611
|
+
_id: string;
|
|
1612
|
+
role?: string;
|
|
1613
|
+
}>;
|
|
1614
|
+
permissions?: Record<string, string[]>;
|
|
1615
|
+
}
|
|
1616
|
+
interface SettingsLike {
|
|
1617
|
+
workspace?: {
|
|
1618
|
+
defaultRole?: string;
|
|
1619
|
+
permissions?: Record<string, string[]>;
|
|
1620
|
+
canInviteMembers?: boolean | 'admin-only';
|
|
1621
|
+
canCreateWorkspace?: boolean | 'owner-only';
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
interface PermissionContext {
|
|
1625
|
+
userId: string | null;
|
|
1626
|
+
workspaceRole?: string | null;
|
|
1627
|
+
workspace: WorkspaceLike | null;
|
|
1628
|
+
settings?: SettingsLike | null;
|
|
1629
|
+
/** Developer-defined app permissions per role. Merged with platform defaults. */
|
|
1630
|
+
appPermissions?: Record<string, string[]>;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Resolve the full set of permissions for a user in a workspace.
|
|
1634
|
+
*
|
|
1635
|
+
* Returns both platform permissions (workspace:*) and app permissions
|
|
1636
|
+
* (developer-defined custom strings) in a single Set.
|
|
1637
|
+
*
|
|
1638
|
+
* Resolution order (matches backend 3-tier):
|
|
1639
|
+
* 1. If user is workspace owner → all platform permissions + all app permissions
|
|
1640
|
+
* 2. workspace.permissions[role] (per-workspace overrides)
|
|
1641
|
+
* 3. settings.workspace.permissions[role] (org-level template)
|
|
1642
|
+
* 4. DEFAULT_ROLE_PERMISSIONS[role] (SDK built-in defaults)
|
|
1643
|
+
* 5. Merge in appPermissions (developer-defined) for the role
|
|
1644
|
+
* 6. If role not found → use defaultRole from settings, then 'member'
|
|
1645
|
+
* 7. Apply setting restrictions (canInviteMembers, canCreateWorkspace)
|
|
1646
|
+
*/
|
|
1647
|
+
declare function resolvePermissions(ctx: PermissionContext): Set<string>;
|
|
1648
|
+
/**
|
|
1649
|
+
* Check if a user has a specific permission (or all of an array).
|
|
1650
|
+
* Works with both platform permissions (Permission.WORKSPACE_*) and
|
|
1651
|
+
* app permissions (any custom string).
|
|
1652
|
+
*/
|
|
1653
|
+
declare function hasPermission(permission: string | string[], ctx: PermissionContext): boolean;
|
|
1654
|
+
|
|
1563
1655
|
/**
|
|
1564
1656
|
* Push notification service worker source code.
|
|
1565
1657
|
* Export this string and write it to a file in your app's `public/` directory.
|
|
@@ -1599,6 +1691,7 @@ interface SDKMessages {
|
|
|
1599
1691
|
usage: string;
|
|
1600
1692
|
features: string;
|
|
1601
1693
|
notifications: string;
|
|
1694
|
+
permissions: string;
|
|
1602
1695
|
danger: string;
|
|
1603
1696
|
};
|
|
1604
1697
|
sidebar: {
|
|
@@ -1611,6 +1704,7 @@ interface SDKMessages {
|
|
|
1611
1704
|
usage: string;
|
|
1612
1705
|
features: string;
|
|
1613
1706
|
notifications: string;
|
|
1707
|
+
permissions: string;
|
|
1614
1708
|
danger: string;
|
|
1615
1709
|
};
|
|
1616
1710
|
common: {
|
|
@@ -2019,6 +2113,14 @@ interface SDKMessages {
|
|
|
2019
2113
|
failedToSubscribe: string;
|
|
2020
2114
|
failedToUnsubscribe: string;
|
|
2021
2115
|
};
|
|
2116
|
+
permissions: {
|
|
2117
|
+
title: string;
|
|
2118
|
+
description: string;
|
|
2119
|
+
ownerOnly: string;
|
|
2120
|
+
save: string;
|
|
2121
|
+
saving: string;
|
|
2122
|
+
saveSuccess: string;
|
|
2123
|
+
};
|
|
2022
2124
|
errors: {
|
|
2023
2125
|
networkError: string;
|
|
2024
2126
|
unauthorized: string;
|
|
@@ -2109,6 +2211,23 @@ interface SaaSOSProviderProps extends IOsState {
|
|
|
2109
2211
|
children: react__default.ReactNode;
|
|
2110
2212
|
/** SDK UI language. Defaults to 'en'. Supported: en, es, fr, de, ja, zh, hi, ar */
|
|
2111
2213
|
locale?: SDKLocale;
|
|
2214
|
+
/**
|
|
2215
|
+
* Default app permissions per role.
|
|
2216
|
+
* Defines what permissions exist in your app and which roles get them by default.
|
|
2217
|
+
* Workspace owners can customize per-workspace via the Settings → Permissions screen.
|
|
2218
|
+
*
|
|
2219
|
+
* @example
|
|
2220
|
+
* ```tsx
|
|
2221
|
+
* <SaaSOSProvider
|
|
2222
|
+
* defaultPermissions={{
|
|
2223
|
+
* admin: ['projects:create', 'projects:delete', 'reports:export'],
|
|
2224
|
+
* editor: ['projects:create', 'reports:export'],
|
|
2225
|
+
* member: ['projects:view'],
|
|
2226
|
+
* }}
|
|
2227
|
+
* >
|
|
2228
|
+
* ```
|
|
2229
|
+
*/
|
|
2230
|
+
defaultPermissions?: Record<string, string[]>;
|
|
2112
2231
|
}
|
|
2113
2232
|
declare const SaaSOSProvider: react__default.FC<SaaSOSProviderProps>;
|
|
2114
2233
|
|
|
@@ -2120,6 +2239,7 @@ declare const SettingsScreen: {
|
|
|
2120
2239
|
readonly Usage: "usage";
|
|
2121
2240
|
readonly Features: "features";
|
|
2122
2241
|
readonly Notifications: "notifications";
|
|
2242
|
+
readonly Permissions: "permissions";
|
|
2123
2243
|
readonly Danger: "danger";
|
|
2124
2244
|
};
|
|
2125
2245
|
type WorkspaceSettingsSection = (typeof SettingsScreen)[keyof typeof SettingsScreen];
|
|
@@ -2298,6 +2418,84 @@ declare const WhenWorkspaceRoles: {
|
|
|
2298
2418
|
displayName: string;
|
|
2299
2419
|
};
|
|
2300
2420
|
|
|
2421
|
+
interface WhenPermissionProps {
|
|
2422
|
+
/** Single permission or array of permissions (all must be granted). Works with both platform permissions (Permission.*) and app permissions (custom strings). */
|
|
2423
|
+
permission: string | string[];
|
|
2424
|
+
children: React.ReactNode;
|
|
2425
|
+
fallback?: React.ReactNode;
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* Conditional component that renders children only when the current user
|
|
2429
|
+
* has the specified permission(s) in the current workspace.
|
|
2430
|
+
*
|
|
2431
|
+
* @example
|
|
2432
|
+
* ```tsx
|
|
2433
|
+
* import { WhenPermission, Permission } from '@buildbase/sdk/react';
|
|
2434
|
+
*
|
|
2435
|
+
* <WhenPermission permission={Permission.WORKSPACE_MEMBERS_INVITE}>
|
|
2436
|
+
* <InviteForm />
|
|
2437
|
+
* </WhenPermission>
|
|
2438
|
+
*
|
|
2439
|
+
* <WhenPermission
|
|
2440
|
+
* permission={[Permission.WORKSPACE_BILLING_VIEW, Permission.WORKSPACE_BILLING_MANAGE]}
|
|
2441
|
+
* fallback={<p>You don't have access to billing.</p>}
|
|
2442
|
+
* >
|
|
2443
|
+
* <BillingDashboard />
|
|
2444
|
+
* </WhenPermission>
|
|
2445
|
+
* ```
|
|
2446
|
+
*/
|
|
2447
|
+
declare const WhenPermission: {
|
|
2448
|
+
(props: WhenPermissionProps): react.ReactNode;
|
|
2449
|
+
displayName: string;
|
|
2450
|
+
};
|
|
2451
|
+
|
|
2452
|
+
/**
|
|
2453
|
+
* Resolve the current user's permissions in the current (or specified) workspace.
|
|
2454
|
+
*
|
|
2455
|
+
* Returns both platform permissions (workspace:*, billing:*) managed by BuildBase
|
|
2456
|
+
* and app permissions (custom strings) defined by the developer.
|
|
2457
|
+
*
|
|
2458
|
+
* @example Platform permissions (automatic)
|
|
2459
|
+
* ```tsx
|
|
2460
|
+
* import { usePermissions, Permission } from '@buildbase/sdk/react';
|
|
2461
|
+
*
|
|
2462
|
+
* function InviteSection() {
|
|
2463
|
+
* const { can } = usePermissions();
|
|
2464
|
+
* if (!can(Permission.WORKSPACE_MEMBERS_INVITE)) return null;
|
|
2465
|
+
* return <InviteForm />;
|
|
2466
|
+
* }
|
|
2467
|
+
* ```
|
|
2468
|
+
*
|
|
2469
|
+
* @example App permissions (developer-defined)
|
|
2470
|
+
* ```tsx
|
|
2471
|
+
* function ProjectActions() {
|
|
2472
|
+
* const { can } = usePermissions();
|
|
2473
|
+
* return (
|
|
2474
|
+
* <>
|
|
2475
|
+
* {can('projects:create') && <CreateButton />}
|
|
2476
|
+
* {can('reports:export') && <ExportButton />}
|
|
2477
|
+
* </>
|
|
2478
|
+
* );
|
|
2479
|
+
* }
|
|
2480
|
+
* ```
|
|
2481
|
+
*/
|
|
2482
|
+
declare function usePermissions(workspace?: {
|
|
2483
|
+
_id: string;
|
|
2484
|
+
createdBy: string | {
|
|
2485
|
+
_id: string;
|
|
2486
|
+
} | null | undefined;
|
|
2487
|
+
users?: Array<string | {
|
|
2488
|
+
_id: string;
|
|
2489
|
+
role?: string;
|
|
2490
|
+
}>;
|
|
2491
|
+
permissions?: Record<string, string[]>;
|
|
2492
|
+
} | null): {
|
|
2493
|
+
can: (permission: string | string[]) => boolean;
|
|
2494
|
+
permissions: Set<string>;
|
|
2495
|
+
isOwner: boolean;
|
|
2496
|
+
role: string | null;
|
|
2497
|
+
};
|
|
2498
|
+
|
|
2301
2499
|
interface IProps {
|
|
2302
2500
|
slug: string;
|
|
2303
2501
|
children: React.ReactNode;
|
|
@@ -2926,6 +3124,10 @@ declare const useSaaSWorkspaces: () => {
|
|
|
2926
3124
|
allFeatures: IWorkspaceFeature[];
|
|
2927
3125
|
getFeatures: () => Promise<IWorkspaceFeature[] | null>;
|
|
2928
3126
|
updateFeature: (workspaceId: string, key: string, value: boolean) => Promise<IWorkspace>;
|
|
3127
|
+
updateWorkspaceSettings: (data: {
|
|
3128
|
+
permissions: Record<string, string[]>;
|
|
3129
|
+
}) => Promise<any>;
|
|
3130
|
+
updateWorkspacePermissions: (workspaceId: string, permissions: Record<string, string[]>) => Promise<any>;
|
|
2929
3131
|
getWorkspace: (workspaceId: string) => Promise<IWorkspace>;
|
|
2930
3132
|
updateWorkspace: (ws: IWorkspace, _data: Partial<IWorkspace>) => Promise<void>;
|
|
2931
3133
|
getUsers: (workspaceId: string) => Promise<IWorkspaceUser[]>;
|
|
@@ -3901,5 +4103,5 @@ declare const PushNotificationProvider: react__default.FC<PushNotificationProvid
|
|
|
3901
4103
|
*/
|
|
3902
4104
|
declare function usePushNotifications(): PushNotificationContextValue;
|
|
3903
4105
|
|
|
3904
|
-
export { ApiVersion, AuthApi, AuthStatus, BB_PARAM, BaseApi, BetaForm, BillingIntervals, CURRENCY_DISPLAY, CURRENCY_FLAG, DunningState, EventEmitter, InvoiceStatuses, PLAN_CURRENCY_CODES, PLAN_CURRENCY_OPTIONS, PUSH_SERVICE_WORKER_SCRIPT, PricingPage, PushApi, PushNotificationProvider, QuotaUsageContextProvider, SDKEvent, SETTINGS_SCREENS, SUPPORTED_LOCALES, SaaSOSProvider, SettingsApi, SettingsScreen, SubscriptionContextProvider, SubscriptionItemType, SubscriptionStatus, UserApi, WhenAuthenticated, WhenNoSubscription, WhenNotTrialing, WhenQuotaAvailable, WhenQuotaExhausted, WhenQuotaOverage, WhenQuotaThreshold, WhenRoles, WhenSubscription, WhenSubscriptionToPlans, WhenTrialEnding, WhenTrialing, WhenUnauthenticated, WhenUserFeatureDisabled, WhenUserFeatureEnabled, WhenWorkspaceFeatureDisabled, WhenWorkspaceFeatureEnabled, WhenWorkspaceRoles, WorkspaceApi, WorkspaceSwitcher, calculateBillableSeats, calculateSeatOverageCents, calculateTotalSubscriptionCents, cleanBBParams, createBBUrl, createCheckoutRedirectUrls, eventEmitter, formatCents, formatOverageRate, formatOverageRateWithLabel, formatQuotaIncludedOverage, formatQuotaWithPrice, getAvailableCurrenciesFromPlans, getBasePriceCents, getBillingIntervalAndCurrencyFromPriceId, getCurrencyFlag, getCurrencySymbol, getDisplayCurrency, getPerSeatPriceCents, getPricingVariant, getQuotaDisplayValue, getQuotaDisplayWithVariant, getQuotaOverageCents, getQuotaUnitLabelFromName, getSeatPricing, getStripePriceIdForInterval, invalidateQuotaUsage, invalidateSubscription, readBBParams, resolveMaxUsers, safeRedirect, useAllQuotaUsage, useBillingPortal, useCancelSubscription, useCreateCheckoutSession, useInvoice, useInvoices, usePlanGroup, usePlanGroupVersions, usePublicPlanGroupVersion, usePublicPlans, usePushNotifications, useQuotaUsageContext, useQuotaUsageStatus, useRecordUsage, useResumeSubscription, useSaaSAuth, useSaaSOs, useSaaSSettings, useSaaSWorkspaces, useSeatStatus, useSubscription, useSubscriptionContext, useSubscriptionManagement, useTranslation, useTrialStatus, useUpdateSubscription, useUsageLogs, useUserAttributes, useUserFeatures, validateInvite, validateRedirectUrl };
|
|
3905
|
-
export type { BetaFormData, BetaFormResponse, BillingInterval, CheckoutResult, EventData, EventType, FormatQuotaWithPriceOptions, IAllQuotaUsageResponse, IBaseApiConfig, IBasePricing, IBetaConfig, ICheckoutSessionRequest, ICheckoutSessionResponse, IEventCallbacks, IInvoice, IInvoiceListResponse, IInvoiceResponse, IOsConfig, IOsState, IPlan, IPlanGroup, IPlanGroupInfo, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionSummary, IPlanVersionWithPlan, IPricingVariant, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanVersion, IPublicPlansResponse, IQuotaByInterval, IQuotaIntervalValue, IQuotaOveragePriceIdsByInterval, IQuotaOveragesByInterval, IQuotaUsageStatus, IQuotaUsageStatusResponse, IRecordUsageRequest, IRecordUsageResponse, IStripePricesByInterval, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, IUsageLogEntry, IUsageLogsQuery, IUsageLogsResponse, InviteBlockReason, InviteValidation, InvoiceStatus, MaxUsersConfig, OnWorkspaceChangeParams, PlanVersionWithPricingVariants, PricingPageDetails, PricingPageProps, QuotaDisplayValue, QuotaDisplayWithOverage, QuotaUsageContextValue, SDKLocale, SDKMessages, SaaSOSProviderProps, SeatStatus, SubscriptionContextValue, SubscriptionStatusType, TrialStatus, UserCreatedEventData, UserUpdatedEventData, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceSettingsSection, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };
|
|
4106
|
+
export { ApiVersion, AuthApi, AuthStatus, BB_PARAM, BaseApi, BetaForm, BillingIntervals, CURRENCY_DISPLAY, CURRENCY_FLAG, DEFAULT_ROLE_PERMISSIONS, DunningState, EventEmitter, InvoiceStatuses, PLAN_CURRENCY_CODES, PLAN_CURRENCY_OPTIONS, PUSH_SERVICE_WORKER_SCRIPT, Permission, PricingPage, PushApi, PushNotificationProvider, QuotaUsageContextProvider, SDKEvent, SETTINGS_SCREENS, SUPPORTED_LOCALES, SaaSOSProvider, SettingsApi, SettingsScreen, SubscriptionContextProvider, SubscriptionItemType, SubscriptionStatus, UserApi, WhenAuthenticated, WhenNoSubscription, WhenNotTrialing, WhenPermission, WhenQuotaAvailable, WhenQuotaExhausted, WhenQuotaOverage, WhenQuotaThreshold, WhenRoles, WhenSubscription, WhenSubscriptionToPlans, WhenTrialEnding, WhenTrialing, WhenUnauthenticated, WhenUserFeatureDisabled, WhenUserFeatureEnabled, WhenWorkspaceFeatureDisabled, WhenWorkspaceFeatureEnabled, WhenWorkspaceRoles, WorkspaceApi, WorkspaceSwitcher, calculateBillableSeats, calculateSeatOverageCents, calculateTotalSubscriptionCents, cleanBBParams, createBBUrl, createCheckoutRedirectUrls, eventEmitter, formatCents, formatOverageRate, formatOverageRateWithLabel, formatQuotaIncludedOverage, formatQuotaWithPrice, getAvailableCurrenciesFromPlans, getBasePriceCents, getBillingIntervalAndCurrencyFromPriceId, getCurrencyFlag, getCurrencySymbol, getDisplayCurrency, getPerSeatPriceCents, getPricingVariant, getQuotaDisplayValue, getQuotaDisplayWithVariant, getQuotaOverageCents, getQuotaUnitLabelFromName, getSeatPricing, getStripePriceIdForInterval, hasPermission, invalidateQuotaUsage, invalidateSubscription, readBBParams, resolveMaxUsers, resolvePermissions, safeRedirect, useAllQuotaUsage, useBillingPortal, useCancelSubscription, useCreateCheckoutSession, useInvoice, useInvoices, usePermissions, usePlanGroup, usePlanGroupVersions, usePublicPlanGroupVersion, usePublicPlans, usePushNotifications, useQuotaUsageContext, useQuotaUsageStatus, useRecordUsage, useResumeSubscription, useSaaSAuth, useSaaSOs, useSaaSSettings, useSaaSWorkspaces, useSeatStatus, useSubscription, useSubscriptionContext, useSubscriptionManagement, useTranslation, useTrialStatus, useUpdateSubscription, useUsageLogs, useUserAttributes, useUserFeatures, validateInvite, validateRedirectUrl };
|
|
4107
|
+
export type { BetaFormData, BetaFormResponse, BillingInterval, CheckoutResult, EventData, EventType, FormatQuotaWithPriceOptions, IAllQuotaUsageResponse, IBaseApiConfig, IBasePricing, IBetaConfig, ICheckoutSessionRequest, ICheckoutSessionResponse, IEventCallbacks, IInvoice, IInvoiceListResponse, IInvoiceResponse, IOsConfig, IOsState, IPlan, IPlanGroup, IPlanGroupInfo, IPlanGroupLatestVersion, IPlanGroupResponse, IPlanGroupVersion, IPlanGroupVersionWithPlans, IPlanGroupVersionsResponse, IPlanVersion, IPlanVersionSummary, IPlanVersionWithPlan, IPricingVariant, IPublicPlanItem, IPublicPlanItemCategory, IPublicPlanVersion, IPublicPlansResponse, IQuotaByInterval, IQuotaIntervalValue, IQuotaOveragePriceIdsByInterval, IQuotaOveragesByInterval, IQuotaUsageStatus, IQuotaUsageStatusResponse, IRecordUsageRequest, IRecordUsageResponse, IStripePricesByInterval, ISubscription, ISubscriptionItem, ISubscriptionResponse, ISubscriptionUpdateRequest, ISubscriptionUpdateResponse, IUsageLogEntry, IUsageLogsQuery, IUsageLogsResponse, InviteBlockReason, InviteValidation, InvoiceStatus, MaxUsersConfig, OnWorkspaceChangeParams, PermissionContext, PermissionKey, PlanVersionWithPricingVariants, PricingPageDetails, PricingPageProps, QuotaDisplayValue, QuotaDisplayWithOverage, QuotaUsageContextValue, RolePermissionMap, SDKLocale, SDKMessages, SaaSOSProviderProps, SeatStatus, SubscriptionContextValue, SubscriptionStatusType, TrialStatus, UserCreatedEventData, UserUpdatedEventData, WorkspaceChangedEventData, WorkspaceCreatedEventData, WorkspaceDeletedEventData, WorkspaceSettingsSection, WorkspaceUpdatedEventData, WorkspaceUserAddedEventData, WorkspaceUserRemovedEventData, WorkspaceUserRoleChangedEventData };
|