@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.js
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
class b extends Error {
|
|
2
|
+
constructor(t, e, s = "unknown") {
|
|
3
|
+
super(e), this.name = "SaaSError", this.code = t, this.domain = s;
|
|
4
|
+
}
|
|
5
|
+
get isNotFound() {
|
|
6
|
+
return this.code === 404;
|
|
7
|
+
}
|
|
8
|
+
get isUnauthorized() {
|
|
9
|
+
return this.code === 401;
|
|
10
|
+
}
|
|
11
|
+
get isForbidden() {
|
|
12
|
+
return this.code === 403;
|
|
13
|
+
}
|
|
14
|
+
get isConflict() {
|
|
15
|
+
return this.code === 409;
|
|
16
|
+
}
|
|
17
|
+
get isRateLimited() {
|
|
18
|
+
return this.code === 429;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class m {
|
|
22
|
+
constructor(t, e) {
|
|
23
|
+
this.baseUrl = t, this.authMode = e;
|
|
24
|
+
}
|
|
25
|
+
async request(t, e, s, r) {
|
|
26
|
+
const i = {
|
|
27
|
+
"Content-Type": "application/json",
|
|
28
|
+
...this.getAuthHeaders(),
|
|
29
|
+
...r
|
|
30
|
+
}, a = await (await fetch(`${this.baseUrl}${e}`, {
|
|
31
|
+
method: t,
|
|
32
|
+
headers: i,
|
|
33
|
+
body: s ? JSON.stringify(s) : void 0
|
|
34
|
+
})).json();
|
|
35
|
+
if (a.code && a.code >= 400) {
|
|
36
|
+
const d = this.inferDomain(e);
|
|
37
|
+
throw new b(a.code, a.message || "Request failed", d);
|
|
38
|
+
}
|
|
39
|
+
return a.data;
|
|
40
|
+
}
|
|
41
|
+
async get(t, e) {
|
|
42
|
+
return this.request("GET", t, void 0, e);
|
|
43
|
+
}
|
|
44
|
+
async post(t, e, s) {
|
|
45
|
+
return this.request("POST", t, e, s);
|
|
46
|
+
}
|
|
47
|
+
async patch(t, e, s) {
|
|
48
|
+
return this.request("PATCH", t, e, s);
|
|
49
|
+
}
|
|
50
|
+
async del(t, e) {
|
|
51
|
+
return this.request("DELETE", t, void 0, e);
|
|
52
|
+
}
|
|
53
|
+
getAuthHeaders() {
|
|
54
|
+
switch (this.authMode.type) {
|
|
55
|
+
case "publishableKey":
|
|
56
|
+
case "apiKey":
|
|
57
|
+
return { "X-API-Key": this.authMode.key };
|
|
58
|
+
case "portalToken":
|
|
59
|
+
case "embedToken":
|
|
60
|
+
return { Authorization: `Bearer ${this.authMode.token}` };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
inferDomain(t) {
|
|
64
|
+
return t.startsWith("/auth") ? "auth" : t.startsWith("/billing") ? "billing" : t.startsWith("/report") ? "report" : "unknown";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
class w {
|
|
68
|
+
constructor(t) {
|
|
69
|
+
this.accessToken = null, this.refreshToken = null, this.refreshTimer = null, this.onRefreshNeeded = null, this.storageKey = `ss_rt_${t.slice(0, 12)}`, this.refreshToken = this.loadRefreshToken();
|
|
70
|
+
}
|
|
71
|
+
setRefreshCallback(t) {
|
|
72
|
+
this.onRefreshNeeded = t;
|
|
73
|
+
}
|
|
74
|
+
getAccessToken() {
|
|
75
|
+
return this.accessToken;
|
|
76
|
+
}
|
|
77
|
+
getRefreshToken() {
|
|
78
|
+
return this.refreshToken;
|
|
79
|
+
}
|
|
80
|
+
hasRefreshToken() {
|
|
81
|
+
return this.refreshToken !== null;
|
|
82
|
+
}
|
|
83
|
+
setTokens(t, e) {
|
|
84
|
+
this.accessToken = t, this.refreshToken = e, this.saveRefreshToken(e), this.scheduleRefresh(t);
|
|
85
|
+
}
|
|
86
|
+
clearTokens() {
|
|
87
|
+
this.accessToken = null, this.refreshToken = null, this.removeRefreshToken(), this.refreshTimer && (clearTimeout(this.refreshTimer), this.refreshTimer = null);
|
|
88
|
+
}
|
|
89
|
+
destroy() {
|
|
90
|
+
this.refreshTimer && (clearTimeout(this.refreshTimer), this.refreshTimer = null);
|
|
91
|
+
}
|
|
92
|
+
scheduleRefresh(t) {
|
|
93
|
+
var r;
|
|
94
|
+
this.refreshTimer && clearTimeout(this.refreshTimer);
|
|
95
|
+
const e = this.getTokenExpiry(t);
|
|
96
|
+
if (!e) return;
|
|
97
|
+
const s = e * 1e3 - Date.now() - 6e4;
|
|
98
|
+
if (s <= 0) {
|
|
99
|
+
(r = this.onRefreshNeeded) == null || r.call(this);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.refreshTimer = setTimeout(() => {
|
|
103
|
+
var i;
|
|
104
|
+
(i = this.onRefreshNeeded) == null || i.call(this);
|
|
105
|
+
}, s);
|
|
106
|
+
}
|
|
107
|
+
getTokenExpiry(t) {
|
|
108
|
+
try {
|
|
109
|
+
const e = t.split(".")[1];
|
|
110
|
+
return JSON.parse(atob(e)).exp ?? null;
|
|
111
|
+
} catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
loadRefreshToken() {
|
|
116
|
+
try {
|
|
117
|
+
return localStorage.getItem(this.storageKey);
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
saveRefreshToken(t) {
|
|
123
|
+
try {
|
|
124
|
+
localStorage.setItem(this.storageKey, t);
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
removeRefreshToken() {
|
|
129
|
+
try {
|
|
130
|
+
localStorage.removeItem(this.storageKey);
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
class S {
|
|
136
|
+
constructor() {
|
|
137
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
138
|
+
}
|
|
139
|
+
on(t, e) {
|
|
140
|
+
return this.listeners.has(t) || this.listeners.set(t, /* @__PURE__ */ new Set()), this.listeners.get(t).add(e), () => {
|
|
141
|
+
var s;
|
|
142
|
+
(s = this.listeners.get(t)) == null || s.delete(e);
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
emit(t, e) {
|
|
146
|
+
var s;
|
|
147
|
+
(s = this.listeners.get(t)) == null || s.forEach((r) => r(e));
|
|
148
|
+
}
|
|
149
|
+
removeAll() {
|
|
150
|
+
this.listeners.clear();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const k = 500, T = 600, $ = 5 * 60 * 1e3;
|
|
154
|
+
class R {
|
|
155
|
+
constructor(t, e, s, r) {
|
|
156
|
+
this.cachedUser = null, this.cachedSettings = null, this.loaded = !1, this.transport = t, this.tokenManager = e, this.emitter = s, this.baseUrl = r;
|
|
157
|
+
}
|
|
158
|
+
// ---------------------------------------------------------------------------
|
|
159
|
+
// Lifecycle
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
async load() {
|
|
162
|
+
var t, e;
|
|
163
|
+
if (!this.loaded) {
|
|
164
|
+
try {
|
|
165
|
+
this.cachedSettings = await this.transport.get("/auth/settings");
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
if ((t = this.tokenManager) != null && t.hasRefreshToken())
|
|
169
|
+
try {
|
|
170
|
+
await this.performRefresh();
|
|
171
|
+
} catch {
|
|
172
|
+
(e = this.tokenManager) == null || e.clearTokens();
|
|
173
|
+
}
|
|
174
|
+
this.loaded = !0;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Core auth operations
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
async signIn(t, e) {
|
|
181
|
+
const s = await this.transport.post("/auth/login", { email: t, password: e });
|
|
182
|
+
if ("mfaRequired" in s && s.mfaRequired)
|
|
183
|
+
return s;
|
|
184
|
+
const r = s;
|
|
185
|
+
return this.setSession(r), r;
|
|
186
|
+
}
|
|
187
|
+
async signUp(t, e) {
|
|
188
|
+
const s = await this.transport.post("/auth/register", { email: t, password: e });
|
|
189
|
+
return this.setSession(s), s;
|
|
190
|
+
}
|
|
191
|
+
async signOut() {
|
|
192
|
+
var e;
|
|
193
|
+
const t = (e = this.tokenManager) == null ? void 0 : e.getRefreshToken();
|
|
194
|
+
if (t)
|
|
195
|
+
try {
|
|
196
|
+
await this.transport.post("/auth/logout", { refreshToken: t });
|
|
197
|
+
} catch {
|
|
198
|
+
}
|
|
199
|
+
this.clearSession();
|
|
200
|
+
}
|
|
201
|
+
async signInWithOAuth(t) {
|
|
202
|
+
const e = `${this.baseUrl}/auth/oauth/${t}/popup-callback`, { authUrl: s, state: r } = await this.transport.get(
|
|
203
|
+
`/auth/oauth/${t}?redirect_uri=${encodeURIComponent(e)}`
|
|
204
|
+
), i = window.screenX + (window.innerWidth - k) / 2, g = window.screenY + (window.innerHeight - T) / 2, a = window.open(
|
|
205
|
+
s,
|
|
206
|
+
"saas-support-oauth",
|
|
207
|
+
`width=${k},height=${T},left=${i},top=${g},toolbar=no,menubar=no`
|
|
208
|
+
);
|
|
209
|
+
return new Promise((d, c) => {
|
|
210
|
+
let o = !1;
|
|
211
|
+
const u = async (h) => {
|
|
212
|
+
var f;
|
|
213
|
+
if (((f = h.data) == null ? void 0 : f.type) === "saas-support:oauth-callback" && !o) {
|
|
214
|
+
if (o = !0, window.removeEventListener("message", u), clearTimeout(y), clearInterval(p), a == null || a.close(), h.data.error) {
|
|
215
|
+
c(new Error(`OAuth error: ${h.data.error}`));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
const l = await this.transport.post(
|
|
220
|
+
`/auth/oauth/${t}/callback`,
|
|
221
|
+
{ code: h.data.code, state: h.data.state || r }
|
|
222
|
+
);
|
|
223
|
+
this.setSession(l), d(l);
|
|
224
|
+
} catch (l) {
|
|
225
|
+
c(l);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
window.addEventListener("message", u);
|
|
230
|
+
const y = setTimeout(() => {
|
|
231
|
+
o || (o = !0, window.removeEventListener("message", u), clearInterval(p), a == null || a.close(), c(new Error("OAuth popup timed out")));
|
|
232
|
+
}, $), p = setInterval(() => {
|
|
233
|
+
a != null && a.closed && !o && (o = !0, clearInterval(p), clearTimeout(y), window.removeEventListener("message", u), c(new Error("OAuth popup was closed")));
|
|
234
|
+
}, 500);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
async submitMfaCode(t, e) {
|
|
238
|
+
const s = await this.transport.post("/auth/login/mfa", { mfaToken: t, code: e });
|
|
239
|
+
return this.setSession(s), s;
|
|
240
|
+
}
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
// Magic link & password reset
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
async sendMagicLink(t, e) {
|
|
245
|
+
await this.transport.post("/auth/magic-link/send", { email: t, redirectUrl: e });
|
|
246
|
+
}
|
|
247
|
+
async verifyMagicLink(t) {
|
|
248
|
+
const e = await this.transport.post("/auth/magic-link/verify", { token: t });
|
|
249
|
+
return this.setSession(e), e;
|
|
250
|
+
}
|
|
251
|
+
async sendPasswordReset(t, e) {
|
|
252
|
+
await this.transport.post("/auth/password-reset/send", { email: t, redirectUrl: e });
|
|
253
|
+
}
|
|
254
|
+
async resetPassword(t, e) {
|
|
255
|
+
await this.transport.post("/auth/password-reset/verify", { token: t, newPassword: e });
|
|
256
|
+
}
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// MFA management
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
async setupMfa() {
|
|
261
|
+
return this.transport.post("/auth/mfa/setup", void 0, this.authHeaders());
|
|
262
|
+
}
|
|
263
|
+
async verifyMfa(t) {
|
|
264
|
+
return this.transport.post("/auth/mfa/verify", { code: t }, this.authHeaders());
|
|
265
|
+
}
|
|
266
|
+
async disableMfa(t) {
|
|
267
|
+
await this.transport.post("/auth/mfa/disable", { code: t }, this.authHeaders());
|
|
268
|
+
}
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
// Token & user access
|
|
271
|
+
// ---------------------------------------------------------------------------
|
|
272
|
+
async getToken() {
|
|
273
|
+
var e, s, r;
|
|
274
|
+
const t = ((e = this.tokenManager) == null ? void 0 : e.getAccessToken()) ?? null;
|
|
275
|
+
if (t) return t;
|
|
276
|
+
if ((s = this.tokenManager) != null && s.hasRefreshToken())
|
|
277
|
+
try {
|
|
278
|
+
return await this.performRefresh(), ((r = this.tokenManager) == null ? void 0 : r.getAccessToken()) ?? null;
|
|
279
|
+
} catch {
|
|
280
|
+
return this.clearSession(), null;
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
async getUser() {
|
|
285
|
+
if (this.cachedUser) return this.cachedUser;
|
|
286
|
+
const t = await this.getToken();
|
|
287
|
+
if (!t) return null;
|
|
288
|
+
try {
|
|
289
|
+
return this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${t}` }), this.cachedUser;
|
|
290
|
+
} catch {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
getUserSync() {
|
|
295
|
+
return this.cachedUser;
|
|
296
|
+
}
|
|
297
|
+
isLoaded() {
|
|
298
|
+
return this.loaded;
|
|
299
|
+
}
|
|
300
|
+
async getSettings() {
|
|
301
|
+
if (this.cachedSettings) return this.cachedSettings;
|
|
302
|
+
try {
|
|
303
|
+
return this.cachedSettings = await this.transport.get("/auth/settings"), this.cachedSettings;
|
|
304
|
+
} catch {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
onAuthStateChange(t) {
|
|
309
|
+
return this.emitter.on("authStateChange", t);
|
|
310
|
+
}
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
// Profile
|
|
313
|
+
// ---------------------------------------------------------------------------
|
|
314
|
+
async updateProfile(t) {
|
|
315
|
+
const e = await this.transport.patch("/auth/me", { metadata: t }, this.authHeaders());
|
|
316
|
+
return this.cachedUser = e, this.emitter.emit("authStateChange", e), e;
|
|
317
|
+
}
|
|
318
|
+
// ---------------------------------------------------------------------------
|
|
319
|
+
// Organizations
|
|
320
|
+
// ---------------------------------------------------------------------------
|
|
321
|
+
async listOrgs() {
|
|
322
|
+
return this.transport.get("/auth/orgs", this.authHeaders());
|
|
323
|
+
}
|
|
324
|
+
async createOrg(t, e) {
|
|
325
|
+
return this.transport.post("/auth/orgs", { name: t, slug: e }, this.authHeaders());
|
|
326
|
+
}
|
|
327
|
+
async getOrg(t) {
|
|
328
|
+
return this.transport.get(`/auth/orgs/${t}`, this.authHeaders());
|
|
329
|
+
}
|
|
330
|
+
async updateOrg(t, e) {
|
|
331
|
+
return this.transport.patch(`/auth/orgs/${t}`, e, this.authHeaders());
|
|
332
|
+
}
|
|
333
|
+
async deleteOrg(t) {
|
|
334
|
+
await this.transport.del(`/auth/orgs/${t}`, this.authHeaders());
|
|
335
|
+
}
|
|
336
|
+
// ---------------------------------------------------------------------------
|
|
337
|
+
// Members & Invites
|
|
338
|
+
// ---------------------------------------------------------------------------
|
|
339
|
+
async listMembers(t) {
|
|
340
|
+
return this.transport.get(`/auth/orgs/${t}/members`, this.authHeaders());
|
|
341
|
+
}
|
|
342
|
+
async sendInvite(t, e, s) {
|
|
343
|
+
return this.transport.post(`/auth/orgs/${t}/invites`, { email: e, role: s }, this.authHeaders());
|
|
344
|
+
}
|
|
345
|
+
async updateMemberRole(t, e, s) {
|
|
346
|
+
await this.transport.patch(`/auth/orgs/${t}/members/${e}`, { role: s }, this.authHeaders());
|
|
347
|
+
}
|
|
348
|
+
async removeMember(t, e) {
|
|
349
|
+
await this.transport.del(`/auth/orgs/${t}/members/${e}`, this.authHeaders());
|
|
350
|
+
}
|
|
351
|
+
async acceptInvite(t) {
|
|
352
|
+
return this.transport.post(`/auth/invites/${t}/accept`, void 0, this.authHeaders());
|
|
353
|
+
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Internal
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
/** @internal */
|
|
358
|
+
async performRefresh() {
|
|
359
|
+
var s;
|
|
360
|
+
const t = (s = this.tokenManager) == null ? void 0 : s.getRefreshToken();
|
|
361
|
+
if (!t) throw new Error("No refresh token");
|
|
362
|
+
const e = await this.transport.post(
|
|
363
|
+
"/auth/refresh",
|
|
364
|
+
{ refreshToken: t }
|
|
365
|
+
);
|
|
366
|
+
if (this.tokenManager.setTokens(e.accessToken, e.refreshToken), !this.cachedUser)
|
|
367
|
+
try {
|
|
368
|
+
this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${e.accessToken}` }), this.emitter.emit("authStateChange", this.cachedUser);
|
|
369
|
+
} catch {
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
setSession(t) {
|
|
373
|
+
var e;
|
|
374
|
+
(e = this.tokenManager) == null || e.setTokens(t.accessToken, t.refreshToken), this.cachedUser = t.user, this.emitter.emit("authStateChange", t.user);
|
|
375
|
+
}
|
|
376
|
+
clearSession() {
|
|
377
|
+
var t;
|
|
378
|
+
(t = this.tokenManager) == null || t.clearTokens(), this.cachedUser = null, this.emitter.emit("authStateChange", null);
|
|
379
|
+
}
|
|
380
|
+
authHeaders() {
|
|
381
|
+
var e;
|
|
382
|
+
const t = (e = this.tokenManager) == null ? void 0 : e.getAccessToken();
|
|
383
|
+
return t ? { Authorization: `Bearer ${t}` } : {};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
class U {
|
|
387
|
+
constructor(t) {
|
|
388
|
+
this.transport = t;
|
|
389
|
+
}
|
|
390
|
+
// --- Customer ---
|
|
391
|
+
async createCustomer(t) {
|
|
392
|
+
return this.transport.post("/billing/customers", t);
|
|
393
|
+
}
|
|
394
|
+
async getCustomer(t) {
|
|
395
|
+
return this.transport.get(`/billing/customers/${t}`);
|
|
396
|
+
}
|
|
397
|
+
async updateCustomer(t, e) {
|
|
398
|
+
return this.transport.patch(`/billing/customers/${t}`, e);
|
|
399
|
+
}
|
|
400
|
+
// --- Subscription ---
|
|
401
|
+
async subscribe(t, e) {
|
|
402
|
+
return this.transport.post(`/billing/customers/${t}/subscribe`, { planId: e });
|
|
403
|
+
}
|
|
404
|
+
async changePlan(t, e) {
|
|
405
|
+
return this.transport.patch(`/billing/customers/${t}/subscription`, { planId: e });
|
|
406
|
+
}
|
|
407
|
+
async cancelSubscription(t) {
|
|
408
|
+
return this.transport.del(`/billing/customers/${t}/subscription`);
|
|
409
|
+
}
|
|
410
|
+
// --- Invoices ---
|
|
411
|
+
async getInvoices(t) {
|
|
412
|
+
return this.transport.get(`/billing/customers/${t}/invoices`);
|
|
413
|
+
}
|
|
414
|
+
// --- Usage ---
|
|
415
|
+
async ingestUsageEvent(t) {
|
|
416
|
+
return this.transport.post("/billing/events", t);
|
|
417
|
+
}
|
|
418
|
+
async getCurrentUsage(t) {
|
|
419
|
+
return this.transport.get(`/billing/customers/${t}/usage`);
|
|
420
|
+
}
|
|
421
|
+
// --- Portal ---
|
|
422
|
+
async createPortalToken(t, e) {
|
|
423
|
+
return this.transport.post("/billing/portal-tokens", { customerId: t, expiresIn: e });
|
|
424
|
+
}
|
|
425
|
+
// --- Coupon ---
|
|
426
|
+
async applyCoupon(t, e) {
|
|
427
|
+
return this.transport.post(`/billing/customers/${t}/coupon`, { code: e });
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
class M {
|
|
431
|
+
constructor(t) {
|
|
432
|
+
this.transport = t;
|
|
433
|
+
}
|
|
434
|
+
// --- Query ---
|
|
435
|
+
async executeQuery(t) {
|
|
436
|
+
return this.transport.post("/report/query", t);
|
|
437
|
+
}
|
|
438
|
+
// --- Saved Queries ---
|
|
439
|
+
async listQueries(t) {
|
|
440
|
+
const e = t ? this.toQueryString(t) : "";
|
|
441
|
+
return this.transport.get(`/report/queries${e}`);
|
|
442
|
+
}
|
|
443
|
+
async saveQuery(t) {
|
|
444
|
+
return this.transport.post("/report/queries", t);
|
|
445
|
+
}
|
|
446
|
+
async updateQuery(t, e) {
|
|
447
|
+
return this.transport.patch(`/report/queries/${t}`, e);
|
|
448
|
+
}
|
|
449
|
+
async deleteQuery(t) {
|
|
450
|
+
await this.transport.del(`/report/queries/${t}`);
|
|
451
|
+
}
|
|
452
|
+
// --- Dashboards ---
|
|
453
|
+
async listDashboards(t) {
|
|
454
|
+
const e = t ? this.toQueryString(t) : "";
|
|
455
|
+
return this.transport.get(`/report/dashboards${e}`);
|
|
456
|
+
}
|
|
457
|
+
async createDashboard(t) {
|
|
458
|
+
return this.transport.post("/report/dashboards", t);
|
|
459
|
+
}
|
|
460
|
+
async getDashboard(t) {
|
|
461
|
+
return this.transport.get(`/report/dashboards/${t}`);
|
|
462
|
+
}
|
|
463
|
+
async updateDashboard(t, e) {
|
|
464
|
+
return this.transport.patch(`/report/dashboards/${t}`, e);
|
|
465
|
+
}
|
|
466
|
+
async deleteDashboard(t) {
|
|
467
|
+
await this.transport.del(`/report/dashboards/${t}`);
|
|
468
|
+
}
|
|
469
|
+
// --- Embed Tokens ---
|
|
470
|
+
async createEmbedToken(t) {
|
|
471
|
+
return this.transport.post("/report/embed-tokens", t);
|
|
472
|
+
}
|
|
473
|
+
async listEmbedTokens() {
|
|
474
|
+
return this.transport.get("/report/embed-tokens");
|
|
475
|
+
}
|
|
476
|
+
async revokeEmbedToken(t) {
|
|
477
|
+
await this.transport.del(`/report/embed-tokens/${t}`);
|
|
478
|
+
}
|
|
479
|
+
toQueryString(t) {
|
|
480
|
+
const e = Object.entries(t).filter(([, s]) => s != null && s !== "");
|
|
481
|
+
return e.length === 0 ? "" : "?" + e.map(([s, r]) => `${s}=${encodeURIComponent(String(r))}`).join("&");
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
const v = "https://api.saas-support.com/v1";
|
|
485
|
+
class E {
|
|
486
|
+
constructor(t) {
|
|
487
|
+
if (this.tokenManager = null, this.loaded = !1, !t.publishableKey && !t.apiKey)
|
|
488
|
+
throw new Error("SaaSSupport: either publishableKey or apiKey is required");
|
|
489
|
+
const e = t.baseUrl ?? v;
|
|
490
|
+
this.emitter = new S();
|
|
491
|
+
const s = t.publishableKey ? new m(e, { type: "publishableKey", key: t.publishableKey }) : null, r = t.apiKey ? new m(e, { type: "apiKey", key: t.apiKey }) : null;
|
|
492
|
+
t.publishableKey && (this.tokenManager = new w(t.publishableKey)), this.auth = new R(
|
|
493
|
+
s ?? r,
|
|
494
|
+
this.tokenManager,
|
|
495
|
+
this.emitter,
|
|
496
|
+
e
|
|
497
|
+
), this.billing = new U(r ?? s), this.report = new M(r ?? s), this.tokenManager && this.tokenManager.setRefreshCallback(() => this.auth.performRefresh());
|
|
498
|
+
}
|
|
499
|
+
async load() {
|
|
500
|
+
this.loaded || (await this.auth.load(), this.loaded = !0);
|
|
501
|
+
}
|
|
502
|
+
isLoaded() {
|
|
503
|
+
return this.loaded;
|
|
504
|
+
}
|
|
505
|
+
onError(t) {
|
|
506
|
+
return this.emitter.on("error", t);
|
|
507
|
+
}
|
|
508
|
+
destroy() {
|
|
509
|
+
var t;
|
|
510
|
+
(t = this.tokenManager) == null || t.destroy(), this.emitter.removeAll();
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function H(n) {
|
|
514
|
+
return "mfaRequired" in n && n.mfaRequired === !0;
|
|
515
|
+
}
|
|
516
|
+
export {
|
|
517
|
+
R as AuthClient,
|
|
518
|
+
U as BillingClient,
|
|
519
|
+
M as ReportClient,
|
|
520
|
+
b as SaaSError,
|
|
521
|
+
E as SaaSSupport,
|
|
522
|
+
m as Transport,
|
|
523
|
+
H as isMfaRequired
|
|
524
|
+
};
|