@saas-support/react 0.2.0
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/README.md +732 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +491 -0
- package/dist/index.js +524 -0
- package/dist/react.cjs +593 -0
- package/dist/react.d.ts +783 -0
- package/dist/react.js +1908 -0
- package/package.json +52 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class b extends Error{constructor(t,e,s="unknown"){super(e),this.name="SaaSError",this.code=t,this.domain=s}get isNotFound(){return this.code===404}get isUnauthorized(){return this.code===401}get isForbidden(){return this.code===403}get isConflict(){return this.code===409}get isRateLimited(){return this.code===429}}class g{constructor(t,e){this.baseUrl=t,this.authMode=e}async request(t,e,s,r){const i={"Content-Type":"application/json",...this.getAuthHeaders(),...r},a=await(await fetch(`${this.baseUrl}${e}`,{method:t,headers:i,body:s?JSON.stringify(s):void 0})).json();if(a.code&&a.code>=400){const d=this.inferDomain(e);throw new b(a.code,a.message||"Request failed",d)}return a.data}async get(t,e){return this.request("GET",t,void 0,e)}async post(t,e,s){return this.request("POST",t,e,s)}async patch(t,e,s){return this.request("PATCH",t,e,s)}async del(t,e){return this.request("DELETE",t,void 0,e)}getAuthHeaders(){switch(this.authMode.type){case"publishableKey":case"apiKey":return{"X-API-Key":this.authMode.key};case"portalToken":case"embedToken":return{Authorization:`Bearer ${this.authMode.token}`}}}inferDomain(t){return t.startsWith("/auth")?"auth":t.startsWith("/billing")?"billing":t.startsWith("/report")?"report":"unknown"}}class R{constructor(t){this.accessToken=null,this.refreshToken=null,this.refreshTimer=null,this.onRefreshNeeded=null,this.storageKey=`ss_rt_${t.slice(0,12)}`,this.refreshToken=this.loadRefreshToken()}setRefreshCallback(t){this.onRefreshNeeded=t}getAccessToken(){return this.accessToken}getRefreshToken(){return this.refreshToken}hasRefreshToken(){return this.refreshToken!==null}setTokens(t,e){this.accessToken=t,this.refreshToken=e,this.saveRefreshToken(e),this.scheduleRefresh(t)}clearTokens(){this.accessToken=null,this.refreshToken=null,this.removeRefreshToken(),this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}destroy(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}scheduleRefresh(t){var r;this.refreshTimer&&clearTimeout(this.refreshTimer);const e=this.getTokenExpiry(t);if(!e)return;const s=e*1e3-Date.now()-6e4;if(s<=0){(r=this.onRefreshNeeded)==null||r.call(this);return}this.refreshTimer=setTimeout(()=>{var i;(i=this.onRefreshNeeded)==null||i.call(this)},s)}getTokenExpiry(t){try{const e=t.split(".")[1];return JSON.parse(atob(e)).exp??null}catch{return null}}loadRefreshToken(){try{return localStorage.getItem(this.storageKey)}catch{return null}}saveRefreshToken(t){try{localStorage.setItem(this.storageKey,t)}catch{}}removeRefreshToken(){try{localStorage.removeItem(this.storageKey)}catch{}}}class M{constructor(){this.listeners=new Map}on(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),()=>{var s;(s=this.listeners.get(t))==null||s.delete(e)}}emit(t,e){var s;(s=this.listeners.get(t))==null||s.forEach(r=>r(e))}removeAll(){this.listeners.clear()}}const k=500,T=600,U=5*60*1e3;class w{constructor(t,e,s,r){this.cachedUser=null,this.cachedSettings=null,this.loaded=!1,this.transport=t,this.tokenManager=e,this.emitter=s,this.baseUrl=r}async load(){var t,e;if(!this.loaded){try{this.cachedSettings=await this.transport.get("/auth/settings")}catch{}if((t=this.tokenManager)!=null&&t.hasRefreshToken())try{await this.performRefresh()}catch{(e=this.tokenManager)==null||e.clearTokens()}this.loaded=!0}}async signIn(t,e){const s=await this.transport.post("/auth/login",{email:t,password:e});if("mfaRequired"in s&&s.mfaRequired)return s;const r=s;return this.setSession(r),r}async signUp(t,e){const s=await this.transport.post("/auth/register",{email:t,password:e});return this.setSession(s),s}async signOut(){var e;const t=(e=this.tokenManager)==null?void 0:e.getRefreshToken();if(t)try{await this.transport.post("/auth/logout",{refreshToken:t})}catch{}this.clearSession()}async signInWithOAuth(t){const e=`${this.baseUrl}/auth/oauth/${t}/popup-callback`,{authUrl:s,state:r}=await this.transport.get(`/auth/oauth/${t}?redirect_uri=${encodeURIComponent(e)}`),i=window.screenX+(window.innerWidth-k)/2,y=window.screenY+(window.innerHeight-T)/2,a=window.open(s,"saas-support-oauth",`width=${k},height=${T},left=${i},top=${y},toolbar=no,menubar=no`);return new Promise((d,u)=>{let o=!1;const c=async h=>{var m;if(((m=h.data)==null?void 0:m.type)==="saas-support:oauth-callback"&&!o){if(o=!0,window.removeEventListener("message",c),clearTimeout(f),clearInterval(p),a==null||a.close(),h.data.error){u(new Error(`OAuth error: ${h.data.error}`));return}try{const l=await this.transport.post(`/auth/oauth/${t}/callback`,{code:h.data.code,state:h.data.state||r});this.setSession(l),d(l)}catch(l){u(l)}}};window.addEventListener("message",c);const f=setTimeout(()=>{o||(o=!0,window.removeEventListener("message",c),clearInterval(p),a==null||a.close(),u(new Error("OAuth popup timed out")))},U),p=setInterval(()=>{a!=null&&a.closed&&!o&&(o=!0,clearInterval(p),clearTimeout(f),window.removeEventListener("message",c),u(new Error("OAuth popup was closed")))},500)})}async submitMfaCode(t,e){const s=await this.transport.post("/auth/login/mfa",{mfaToken:t,code:e});return this.setSession(s),s}async sendMagicLink(t,e){await this.transport.post("/auth/magic-link/send",{email:t,redirectUrl:e})}async verifyMagicLink(t){const e=await this.transport.post("/auth/magic-link/verify",{token:t});return this.setSession(e),e}async sendPasswordReset(t,e){await this.transport.post("/auth/password-reset/send",{email:t,redirectUrl:e})}async resetPassword(t,e){await this.transport.post("/auth/password-reset/verify",{token:t,newPassword:e})}async setupMfa(){return this.transport.post("/auth/mfa/setup",void 0,this.authHeaders())}async verifyMfa(t){return this.transport.post("/auth/mfa/verify",{code:t},this.authHeaders())}async disableMfa(t){await this.transport.post("/auth/mfa/disable",{code:t},this.authHeaders())}async getToken(){var e,s,r;const t=((e=this.tokenManager)==null?void 0:e.getAccessToken())??null;if(t)return t;if((s=this.tokenManager)!=null&&s.hasRefreshToken())try{return await this.performRefresh(),((r=this.tokenManager)==null?void 0:r.getAccessToken())??null}catch{return this.clearSession(),null}return null}async getUser(){if(this.cachedUser)return this.cachedUser;const t=await this.getToken();if(!t)return null;try{return this.cachedUser=await this.transport.get("/auth/me",{Authorization:`Bearer ${t}`}),this.cachedUser}catch{return null}}getUserSync(){return this.cachedUser}isLoaded(){return this.loaded}async getSettings(){if(this.cachedSettings)return this.cachedSettings;try{return this.cachedSettings=await this.transport.get("/auth/settings"),this.cachedSettings}catch{return null}}onAuthStateChange(t){return this.emitter.on("authStateChange",t)}async updateProfile(t){const e=await this.transport.patch("/auth/me",{metadata:t},this.authHeaders());return this.cachedUser=e,this.emitter.emit("authStateChange",e),e}async listOrgs(){return this.transport.get("/auth/orgs",this.authHeaders())}async createOrg(t,e){return this.transport.post("/auth/orgs",{name:t,slug:e},this.authHeaders())}async getOrg(t){return this.transport.get(`/auth/orgs/${t}`,this.authHeaders())}async updateOrg(t,e){return this.transport.patch(`/auth/orgs/${t}`,e,this.authHeaders())}async deleteOrg(t){await this.transport.del(`/auth/orgs/${t}`,this.authHeaders())}async listMembers(t){return this.transport.get(`/auth/orgs/${t}/members`,this.authHeaders())}async sendInvite(t,e,s){return this.transport.post(`/auth/orgs/${t}/invites`,{email:e,role:s},this.authHeaders())}async updateMemberRole(t,e,s){await this.transport.patch(`/auth/orgs/${t}/members/${e}`,{role:s},this.authHeaders())}async removeMember(t,e){await this.transport.del(`/auth/orgs/${t}/members/${e}`,this.authHeaders())}async acceptInvite(t){return this.transport.post(`/auth/invites/${t}/accept`,void 0,this.authHeaders())}async performRefresh(){var s;const t=(s=this.tokenManager)==null?void 0:s.getRefreshToken();if(!t)throw new Error("No refresh token");const e=await this.transport.post("/auth/refresh",{refreshToken:t});if(this.tokenManager.setTokens(e.accessToken,e.refreshToken),!this.cachedUser)try{this.cachedUser=await this.transport.get("/auth/me",{Authorization:`Bearer ${e.accessToken}`}),this.emitter.emit("authStateChange",this.cachedUser)}catch{}}setSession(t){var e;(e=this.tokenManager)==null||e.setTokens(t.accessToken,t.refreshToken),this.cachedUser=t.user,this.emitter.emit("authStateChange",t.user)}clearSession(){var t;(t=this.tokenManager)==null||t.clearTokens(),this.cachedUser=null,this.emitter.emit("authStateChange",null)}authHeaders(){var e;const t=(e=this.tokenManager)==null?void 0:e.getAccessToken();return t?{Authorization:`Bearer ${t}`}:{}}}class S{constructor(t){this.transport=t}async createCustomer(t){return this.transport.post("/billing/customers",t)}async getCustomer(t){return this.transport.get(`/billing/customers/${t}`)}async updateCustomer(t,e){return this.transport.patch(`/billing/customers/${t}`,e)}async subscribe(t,e){return this.transport.post(`/billing/customers/${t}/subscribe`,{planId:e})}async changePlan(t,e){return this.transport.patch(`/billing/customers/${t}/subscription`,{planId:e})}async cancelSubscription(t){return this.transport.del(`/billing/customers/${t}/subscription`)}async getInvoices(t){return this.transport.get(`/billing/customers/${t}/invoices`)}async ingestUsageEvent(t){return this.transport.post("/billing/events",t)}async getCurrentUsage(t){return this.transport.get(`/billing/customers/${t}/usage`)}async createPortalToken(t,e){return this.transport.post("/billing/portal-tokens",{customerId:t,expiresIn:e})}async applyCoupon(t,e){return this.transport.post(`/billing/customers/${t}/coupon`,{code:e})}}class ${constructor(t){this.transport=t}async executeQuery(t){return this.transport.post("/report/query",t)}async listQueries(t){const e=t?this.toQueryString(t):"";return this.transport.get(`/report/queries${e}`)}async saveQuery(t){return this.transport.post("/report/queries",t)}async updateQuery(t,e){return this.transport.patch(`/report/queries/${t}`,e)}async deleteQuery(t){await this.transport.del(`/report/queries/${t}`)}async listDashboards(t){const e=t?this.toQueryString(t):"";return this.transport.get(`/report/dashboards${e}`)}async createDashboard(t){return this.transport.post("/report/dashboards",t)}async getDashboard(t){return this.transport.get(`/report/dashboards/${t}`)}async updateDashboard(t,e){return this.transport.patch(`/report/dashboards/${t}`,e)}async deleteDashboard(t){await this.transport.del(`/report/dashboards/${t}`)}async createEmbedToken(t){return this.transport.post("/report/embed-tokens",t)}async listEmbedTokens(){return this.transport.get("/report/embed-tokens")}async revokeEmbedToken(t){await this.transport.del(`/report/embed-tokens/${t}`)}toQueryString(t){const e=Object.entries(t).filter(([,s])=>s!=null&&s!=="");return e.length===0?"":"?"+e.map(([s,r])=>`${s}=${encodeURIComponent(String(r))}`).join("&")}}const v="https://api.saas-support.com/v1";class E{constructor(t){if(this.tokenManager=null,this.loaded=!1,!t.publishableKey&&!t.apiKey)throw new Error("SaaSSupport: either publishableKey or apiKey is required");const e=t.baseUrl??v;this.emitter=new M;const s=t.publishableKey?new g(e,{type:"publishableKey",key:t.publishableKey}):null,r=t.apiKey?new g(e,{type:"apiKey",key:t.apiKey}):null;t.publishableKey&&(this.tokenManager=new R(t.publishableKey)),this.auth=new w(s??r,this.tokenManager,this.emitter,e),this.billing=new S(r??s),this.report=new $(r??s),this.tokenManager&&this.tokenManager.setRefreshCallback(()=>this.auth.performRefresh())}async load(){this.loaded||(await this.auth.load(),this.loaded=!0)}isLoaded(){return this.loaded}onError(t){return this.emitter.on("error",t)}destroy(){var t;(t=this.tokenManager)==null||t.destroy(),this.emitter.removeAll()}}function C(n){return"mfaRequired"in n&&n.mfaRequired===!0}exports.AuthClient=w;exports.BillingClient=S;exports.ReportClient=$;exports.SaaSError=b;exports.SaaSSupport=E;exports.Transport=g;exports.isMfaRequired=C;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
export declare interface Appearance {
|
|
2
|
+
baseTheme?: 'light' | 'dark';
|
|
3
|
+
variables?: ThemeVariables;
|
|
4
|
+
elements?: ElementOverrides;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export declare interface ApplyCouponResult {
|
|
8
|
+
applied: boolean;
|
|
9
|
+
discountType: string;
|
|
10
|
+
amount: number;
|
|
11
|
+
duration: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export declare class AuthClient {
|
|
15
|
+
private transport;
|
|
16
|
+
private tokenManager;
|
|
17
|
+
private emitter;
|
|
18
|
+
private baseUrl;
|
|
19
|
+
private cachedUser;
|
|
20
|
+
private cachedSettings;
|
|
21
|
+
private loaded;
|
|
22
|
+
constructor(transport: Transport, tokenManager: TokenManager | null, emitter: EventEmitter<SaaSEvents>, baseUrl: string);
|
|
23
|
+
load(): Promise<void>;
|
|
24
|
+
signIn(email: string, password: string): Promise<AuthResult>;
|
|
25
|
+
signUp(email: string, password: string): Promise<SignUpResult>;
|
|
26
|
+
signOut(): Promise<void>;
|
|
27
|
+
signInWithOAuth(provider: OAuthProvider): Promise<SignInResult>;
|
|
28
|
+
submitMfaCode(mfaToken: string, code: string): Promise<SignInResult>;
|
|
29
|
+
sendMagicLink(email: string, redirectUrl: string): Promise<void>;
|
|
30
|
+
verifyMagicLink(token: string): Promise<SignInResult>;
|
|
31
|
+
sendPasswordReset(email: string, redirectUrl: string): Promise<void>;
|
|
32
|
+
resetPassword(token: string, newPassword: string): Promise<void>;
|
|
33
|
+
setupMfa(): Promise<MfaSetupResult>;
|
|
34
|
+
verifyMfa(code: string): Promise<MfaVerifyResult>;
|
|
35
|
+
disableMfa(code: string): Promise<void>;
|
|
36
|
+
getToken(): Promise<string | null>;
|
|
37
|
+
getUser(): Promise<User | null>;
|
|
38
|
+
getUserSync(): User | null;
|
|
39
|
+
isLoaded(): boolean;
|
|
40
|
+
getSettings(): Promise<ProjectSettings | null>;
|
|
41
|
+
onAuthStateChange(callback: AuthStateCallback): () => void;
|
|
42
|
+
updateProfile(metadata: Record<string, unknown>): Promise<User>;
|
|
43
|
+
listOrgs(): Promise<Org[]>;
|
|
44
|
+
createOrg(name: string, slug: string): Promise<Org>;
|
|
45
|
+
getOrg(orgId: string): Promise<Org>;
|
|
46
|
+
updateOrg(orgId: string, params: {
|
|
47
|
+
name?: string;
|
|
48
|
+
avatarUrl?: string;
|
|
49
|
+
}): Promise<Org>;
|
|
50
|
+
deleteOrg(orgId: string): Promise<void>;
|
|
51
|
+
listMembers(orgId: string): Promise<Member[]>;
|
|
52
|
+
sendInvite(orgId: string, email: string, role: string): Promise<Invite>;
|
|
53
|
+
updateMemberRole(orgId: string, userId: string, role: string): Promise<void>;
|
|
54
|
+
removeMember(orgId: string, userId: string): Promise<void>;
|
|
55
|
+
acceptInvite(token: string): Promise<{
|
|
56
|
+
orgId: string;
|
|
57
|
+
role: string;
|
|
58
|
+
}>;
|
|
59
|
+
/* Excluded from this release type: performRefresh */
|
|
60
|
+
private setSession;
|
|
61
|
+
private clearSession;
|
|
62
|
+
private authHeaders;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export declare type AuthMode = {
|
|
66
|
+
type: 'publishableKey';
|
|
67
|
+
key: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'apiKey';
|
|
70
|
+
key: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'portalToken';
|
|
73
|
+
token: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'embedToken';
|
|
76
|
+
token: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export declare type AuthResult = SignInResult | MfaRequiredResult;
|
|
80
|
+
|
|
81
|
+
export declare type AuthStateCallback = (user: User | null) => void;
|
|
82
|
+
|
|
83
|
+
export declare class BillingClient {
|
|
84
|
+
private transport;
|
|
85
|
+
constructor(transport: Transport);
|
|
86
|
+
createCustomer(params: {
|
|
87
|
+
email: string;
|
|
88
|
+
name?: string;
|
|
89
|
+
metadata?: string;
|
|
90
|
+
}): Promise<Customer>;
|
|
91
|
+
getCustomer(customerId: string): Promise<Customer>;
|
|
92
|
+
updateCustomer(customerId: string, params: {
|
|
93
|
+
email?: string;
|
|
94
|
+
name?: string;
|
|
95
|
+
metadata?: string;
|
|
96
|
+
}): Promise<Customer>;
|
|
97
|
+
subscribe(customerId: string, planId: string): Promise<Subscription>;
|
|
98
|
+
changePlan(customerId: string, planId: string): Promise<Subscription>;
|
|
99
|
+
cancelSubscription(customerId: string): Promise<{
|
|
100
|
+
canceledAtPeriodEnd: boolean;
|
|
101
|
+
}>;
|
|
102
|
+
getInvoices(customerId: string): Promise<Invoice[]>;
|
|
103
|
+
ingestUsageEvent(params: {
|
|
104
|
+
customerId: string;
|
|
105
|
+
metric: string;
|
|
106
|
+
quantity: number;
|
|
107
|
+
timestamp?: string;
|
|
108
|
+
idempotencyKey?: string;
|
|
109
|
+
}): Promise<{
|
|
110
|
+
id: string;
|
|
111
|
+
ingested: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
getCurrentUsage(customerId: string): Promise<UsageSummary[]>;
|
|
114
|
+
createPortalToken(customerId: string, expiresIn?: number): Promise<PortalTokenResult>;
|
|
115
|
+
applyCoupon(customerId: string, code: string): Promise<ApplyCouponResult>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export declare interface Customer {
|
|
119
|
+
id: string;
|
|
120
|
+
projectId: string;
|
|
121
|
+
email: string;
|
|
122
|
+
name?: string;
|
|
123
|
+
stripeCustomerId?: string;
|
|
124
|
+
balanceCents: number;
|
|
125
|
+
metadata?: string;
|
|
126
|
+
taxExempt: boolean;
|
|
127
|
+
taxId?: string;
|
|
128
|
+
createdAt: string;
|
|
129
|
+
updatedAt: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export declare interface Dashboard {
|
|
133
|
+
id: string;
|
|
134
|
+
projectId: string;
|
|
135
|
+
name: string;
|
|
136
|
+
layoutJson: string;
|
|
137
|
+
isPublic: boolean;
|
|
138
|
+
refreshIntervalSeconds: number;
|
|
139
|
+
createdAt: string;
|
|
140
|
+
updatedAt: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export declare interface ElementOverrides {
|
|
144
|
+
card?: React.CSSProperties;
|
|
145
|
+
headerTitle?: React.CSSProperties;
|
|
146
|
+
formField?: React.CSSProperties;
|
|
147
|
+
submitButton?: React.CSSProperties;
|
|
148
|
+
socialButton?: React.CSSProperties;
|
|
149
|
+
footerLink?: React.CSSProperties;
|
|
150
|
+
divider?: React.CSSProperties;
|
|
151
|
+
errorMessage?: React.CSSProperties;
|
|
152
|
+
pricingCard?: React.CSSProperties;
|
|
153
|
+
badge?: React.CSSProperties;
|
|
154
|
+
table?: React.CSSProperties;
|
|
155
|
+
tableHeader?: React.CSSProperties;
|
|
156
|
+
tableRow?: React.CSSProperties;
|
|
157
|
+
progressBar?: React.CSSProperties;
|
|
158
|
+
chartContainer?: React.CSSProperties;
|
|
159
|
+
queryInput?: React.CSSProperties;
|
|
160
|
+
dashboardGrid?: React.CSSProperties;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export declare interface EmbedToken {
|
|
164
|
+
id: string;
|
|
165
|
+
projectId: string;
|
|
166
|
+
dashboardId?: string;
|
|
167
|
+
customerId?: string;
|
|
168
|
+
filterRules?: FilterRule[];
|
|
169
|
+
expiresAt: string;
|
|
170
|
+
createdAt: string;
|
|
171
|
+
revokedAt?: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export declare interface EmbedTokenResult {
|
|
175
|
+
embedToken: string;
|
|
176
|
+
expiresAt: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
declare class EventEmitter<Events extends Record<string, any>> {
|
|
180
|
+
private listeners;
|
|
181
|
+
on<K extends keyof Events>(event: K, listener: Listener<Events[K]>): () => void;
|
|
182
|
+
emit<K extends keyof Events>(event: K, data: Events[K]): void;
|
|
183
|
+
removeAll(): void;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export declare interface FilterRule {
|
|
187
|
+
table?: string;
|
|
188
|
+
column: string;
|
|
189
|
+
op: 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'between';
|
|
190
|
+
value: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export declare interface Invite {
|
|
194
|
+
inviteId: string;
|
|
195
|
+
email: string;
|
|
196
|
+
role: string;
|
|
197
|
+
token: string;
|
|
198
|
+
expiresAt: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export declare interface Invoice {
|
|
202
|
+
id: string;
|
|
203
|
+
projectId: string;
|
|
204
|
+
customerId: string;
|
|
205
|
+
subscriptionId?: string;
|
|
206
|
+
amountCents: number;
|
|
207
|
+
status: 'draft' | 'open' | 'paid' | 'void' | 'uncollectible';
|
|
208
|
+
stripeInvoiceId?: string;
|
|
209
|
+
pdfUrl?: string;
|
|
210
|
+
dueDate?: string;
|
|
211
|
+
paidAt?: string;
|
|
212
|
+
createdAt: string;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export declare function isMfaRequired(result: AuthResult): result is MfaRequiredResult;
|
|
216
|
+
|
|
217
|
+
declare type Listener<T> = (data: T) => void;
|
|
218
|
+
|
|
219
|
+
export declare interface ListParams {
|
|
220
|
+
page?: number;
|
|
221
|
+
perPage?: number;
|
|
222
|
+
sort?: string;
|
|
223
|
+
order?: string;
|
|
224
|
+
search?: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export declare interface Member {
|
|
228
|
+
userId: string;
|
|
229
|
+
email: string;
|
|
230
|
+
role: string;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export declare interface MfaRequiredResult {
|
|
234
|
+
mfaRequired: true;
|
|
235
|
+
mfaToken: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export declare interface MfaSetupResult {
|
|
239
|
+
secret: string;
|
|
240
|
+
uri: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export declare interface MfaVerifyResult {
|
|
244
|
+
backupCodes: string[];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export declare type OAuthProvider = 'google' | 'github';
|
|
248
|
+
|
|
249
|
+
export declare interface OffsetPage<T> {
|
|
250
|
+
data: T[];
|
|
251
|
+
meta: {
|
|
252
|
+
page: number;
|
|
253
|
+
perPage: number;
|
|
254
|
+
total: number;
|
|
255
|
+
totalPages: number;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export declare interface Org {
|
|
260
|
+
id: string;
|
|
261
|
+
projectId: string;
|
|
262
|
+
name: string;
|
|
263
|
+
slug: string;
|
|
264
|
+
avatarUrl?: string;
|
|
265
|
+
metadata?: string;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export declare interface Plan {
|
|
269
|
+
id: string;
|
|
270
|
+
name: string;
|
|
271
|
+
description?: string;
|
|
272
|
+
amountCents: number;
|
|
273
|
+
interval: 'month' | 'year';
|
|
274
|
+
currency: string;
|
|
275
|
+
trialDays: number;
|
|
276
|
+
isFree: boolean;
|
|
277
|
+
features: string[];
|
|
278
|
+
isActive: boolean;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export declare interface PortalTokenResult {
|
|
282
|
+
portalToken: string;
|
|
283
|
+
expiresAt: string;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export declare interface ProjectSettings {
|
|
287
|
+
googleEnabled: boolean;
|
|
288
|
+
githubEnabled: boolean;
|
|
289
|
+
emailEnabled: boolean;
|
|
290
|
+
mfaEnforced: boolean;
|
|
291
|
+
passwordMinLength: number;
|
|
292
|
+
emailVerification: boolean;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export declare interface QueryParams {
|
|
296
|
+
naturalLanguage?: string;
|
|
297
|
+
sql?: string;
|
|
298
|
+
filterRules?: FilterRule[];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export declare interface QueryResult {
|
|
302
|
+
sql: string;
|
|
303
|
+
columns: string[];
|
|
304
|
+
rows: Record<string, unknown>[];
|
|
305
|
+
rowCount: number;
|
|
306
|
+
executionMs: number;
|
|
307
|
+
chartType: string;
|
|
308
|
+
cached: boolean;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export declare class ReportClient {
|
|
312
|
+
private transport;
|
|
313
|
+
constructor(transport: Transport);
|
|
314
|
+
executeQuery(params: QueryParams): Promise<QueryResult>;
|
|
315
|
+
listQueries(params?: ListParams): Promise<OffsetPage<SavedQuery>>;
|
|
316
|
+
saveQuery(params: {
|
|
317
|
+
name: string;
|
|
318
|
+
naturalLanguage?: string;
|
|
319
|
+
generatedSql?: string;
|
|
320
|
+
chartType?: string;
|
|
321
|
+
}): Promise<SavedQuery>;
|
|
322
|
+
updateQuery(queryId: string, params: {
|
|
323
|
+
name?: string;
|
|
324
|
+
chartType?: string;
|
|
325
|
+
}): Promise<SavedQuery>;
|
|
326
|
+
deleteQuery(queryId: string): Promise<void>;
|
|
327
|
+
listDashboards(params?: ListParams): Promise<OffsetPage<Dashboard>>;
|
|
328
|
+
createDashboard(params: {
|
|
329
|
+
name: string;
|
|
330
|
+
layoutJson?: string;
|
|
331
|
+
isPublic?: boolean;
|
|
332
|
+
refreshIntervalSeconds?: number;
|
|
333
|
+
}): Promise<Dashboard>;
|
|
334
|
+
getDashboard(dashboardId: string): Promise<Dashboard>;
|
|
335
|
+
updateDashboard(dashboardId: string, params: {
|
|
336
|
+
name?: string;
|
|
337
|
+
layoutJson?: string;
|
|
338
|
+
isPublic?: boolean;
|
|
339
|
+
refreshIntervalSeconds?: number;
|
|
340
|
+
}): Promise<Dashboard>;
|
|
341
|
+
deleteDashboard(dashboardId: string): Promise<void>;
|
|
342
|
+
createEmbedToken(params: {
|
|
343
|
+
dashboardId?: string;
|
|
344
|
+
customerId?: string;
|
|
345
|
+
expiresIn?: number;
|
|
346
|
+
filterRules?: FilterRule[];
|
|
347
|
+
}): Promise<EmbedTokenResult>;
|
|
348
|
+
listEmbedTokens(): Promise<EmbedToken[]>;
|
|
349
|
+
revokeEmbedToken(tokenId: string): Promise<void>;
|
|
350
|
+
private toQueryString;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export declare class SaaSError extends Error {
|
|
354
|
+
code: number;
|
|
355
|
+
domain: 'auth' | 'billing' | 'report' | 'unknown';
|
|
356
|
+
constructor(code: number, message: string, domain?: 'auth' | 'billing' | 'report' | 'unknown');
|
|
357
|
+
get isNotFound(): boolean;
|
|
358
|
+
get isUnauthorized(): boolean;
|
|
359
|
+
get isForbidden(): boolean;
|
|
360
|
+
get isConflict(): boolean;
|
|
361
|
+
get isRateLimited(): boolean;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export declare interface SaaSEvents {
|
|
365
|
+
authStateChange: User | null;
|
|
366
|
+
error: SaaSError;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export declare interface SaaSOptions {
|
|
370
|
+
/** Publishable key for auth (end-user facing, pub_live_ prefix) */
|
|
371
|
+
publishableKey?: string;
|
|
372
|
+
/** API key for billing/report operations */
|
|
373
|
+
apiKey?: string;
|
|
374
|
+
/** Override the default API base URL */
|
|
375
|
+
baseUrl?: string;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export declare class SaaSSupport {
|
|
379
|
+
readonly auth: AuthClient;
|
|
380
|
+
readonly billing: BillingClient;
|
|
381
|
+
readonly report: ReportClient;
|
|
382
|
+
private tokenManager;
|
|
383
|
+
private emitter;
|
|
384
|
+
private loaded;
|
|
385
|
+
constructor(options: SaaSOptions);
|
|
386
|
+
load(): Promise<void>;
|
|
387
|
+
isLoaded(): boolean;
|
|
388
|
+
onError(callback: (error: SaaSError) => void): () => void;
|
|
389
|
+
destroy(): void;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export declare interface SavedQuery {
|
|
393
|
+
id: string;
|
|
394
|
+
projectId: string;
|
|
395
|
+
name: string;
|
|
396
|
+
naturalLanguage?: string;
|
|
397
|
+
generatedSql?: string;
|
|
398
|
+
chartType: string;
|
|
399
|
+
createdAt: string;
|
|
400
|
+
updatedAt: string;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export declare interface SignInResult {
|
|
404
|
+
user: User;
|
|
405
|
+
accessToken: string;
|
|
406
|
+
refreshToken: string;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export declare interface SignUpResult {
|
|
410
|
+
user: User;
|
|
411
|
+
accessToken: string;
|
|
412
|
+
refreshToken: string;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export declare interface Subscription {
|
|
416
|
+
id: string;
|
|
417
|
+
customerId: string;
|
|
418
|
+
planId: string;
|
|
419
|
+
projectId: string;
|
|
420
|
+
status: 'trialing' | 'active' | 'past_due' | 'paused' | 'canceled';
|
|
421
|
+
stripeSubscriptionId?: string;
|
|
422
|
+
cancelAtPeriodEnd: boolean;
|
|
423
|
+
trialEnd?: string;
|
|
424
|
+
currentPeriodStart: string;
|
|
425
|
+
currentPeriodEnd: string;
|
|
426
|
+
canceledAt?: string;
|
|
427
|
+
createdAt: string;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export declare interface ThemeVariables {
|
|
431
|
+
colorPrimary?: string;
|
|
432
|
+
colorBackground?: string;
|
|
433
|
+
colorText?: string;
|
|
434
|
+
colorInputBackground?: string;
|
|
435
|
+
colorInputBorder?: string;
|
|
436
|
+
colorError?: string;
|
|
437
|
+
colorSuccess?: string;
|
|
438
|
+
colorWarning?: string;
|
|
439
|
+
fontFamily?: string;
|
|
440
|
+
borderRadius?: string;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
declare class TokenManager {
|
|
444
|
+
private accessToken;
|
|
445
|
+
private refreshToken;
|
|
446
|
+
private refreshTimer;
|
|
447
|
+
private storageKey;
|
|
448
|
+
private onRefreshNeeded;
|
|
449
|
+
constructor(keyPrefix: string);
|
|
450
|
+
setRefreshCallback(cb: () => Promise<void>): void;
|
|
451
|
+
getAccessToken(): string | null;
|
|
452
|
+
getRefreshToken(): string | null;
|
|
453
|
+
hasRefreshToken(): boolean;
|
|
454
|
+
setTokens(accessToken: string, refreshToken: string): void;
|
|
455
|
+
clearTokens(): void;
|
|
456
|
+
destroy(): void;
|
|
457
|
+
private scheduleRefresh;
|
|
458
|
+
private getTokenExpiry;
|
|
459
|
+
private loadRefreshToken;
|
|
460
|
+
private saveRefreshToken;
|
|
461
|
+
private removeRefreshToken;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export declare class Transport {
|
|
465
|
+
private baseUrl;
|
|
466
|
+
private authMode;
|
|
467
|
+
constructor(baseUrl: string, authMode: AuthMode);
|
|
468
|
+
request<T>(method: string, path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
469
|
+
get<T>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
470
|
+
post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
471
|
+
patch<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
472
|
+
del<T>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
473
|
+
private getAuthHeaders;
|
|
474
|
+
private inferDomain;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export declare interface UsageSummary {
|
|
478
|
+
metric: string;
|
|
479
|
+
total: number;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export declare interface User {
|
|
483
|
+
id: string;
|
|
484
|
+
email: string;
|
|
485
|
+
provider: string;
|
|
486
|
+
emailVerified: boolean;
|
|
487
|
+
metadata: Record<string, unknown>;
|
|
488
|
+
mfaEnabled?: boolean;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export { }
|