@saas-support/react 0.7.6 → 0.8.1
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 +139 -490
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +8 -231
- package/dist/index.js +192 -289
- package/dist/react.cjs +366 -348
- package/dist/react.d.ts +17 -442
- package/dist/react.js +1064 -2126
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
class
|
|
2
|
-
constructor(
|
|
3
|
-
super(
|
|
1
|
+
class g extends Error {
|
|
2
|
+
constructor(e, t, s = "unknown") {
|
|
3
|
+
super(t), this.name = "SaaSError", this.code = e, this.domain = s;
|
|
4
4
|
}
|
|
5
5
|
get isNotFound() {
|
|
6
6
|
return this.code === 404;
|
|
@@ -19,21 +19,21 @@ class p extends Error {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
class k {
|
|
22
|
-
constructor(
|
|
23
|
-
this.onUnauthorized = null, this.baseUrl =
|
|
22
|
+
constructor(e, t) {
|
|
23
|
+
this.onUnauthorized = null, this.baseUrl = e, this.authMode = t;
|
|
24
24
|
}
|
|
25
25
|
/** Register a handler that refreshes tokens and returns a new access token, or null. */
|
|
26
|
-
setUnauthorizedHandler(
|
|
27
|
-
this.onUnauthorized =
|
|
26
|
+
setUnauthorizedHandler(e) {
|
|
27
|
+
this.onUnauthorized = e;
|
|
28
28
|
}
|
|
29
|
-
async request(
|
|
29
|
+
async request(e, t, s, r) {
|
|
30
30
|
try {
|
|
31
|
-
return await this.doRequest(
|
|
31
|
+
return await this.doRequest(e, t, s, r);
|
|
32
32
|
} catch (i) {
|
|
33
|
-
if (i instanceof
|
|
33
|
+
if (i instanceof g && i.isUnauthorized && this.onUnauthorized && (r != null && r.Authorization)) {
|
|
34
34
|
const n = await this.onUnauthorized();
|
|
35
35
|
if (n)
|
|
36
|
-
return this.doRequest(
|
|
36
|
+
return this.doRequest(e, t, s, {
|
|
37
37
|
...r,
|
|
38
38
|
Authorization: `Bearer ${n}`
|
|
39
39
|
});
|
|
@@ -41,26 +41,26 @@ class k {
|
|
|
41
41
|
throw i;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
async get(
|
|
45
|
-
return this.request("GET",
|
|
44
|
+
async get(e, t) {
|
|
45
|
+
return this.request("GET", e, void 0, t);
|
|
46
46
|
}
|
|
47
|
-
async post(
|
|
48
|
-
return this.request("POST",
|
|
47
|
+
async post(e, t, s) {
|
|
48
|
+
return this.request("POST", e, t, s);
|
|
49
49
|
}
|
|
50
|
-
async patch(
|
|
51
|
-
return this.request("PATCH",
|
|
50
|
+
async patch(e, t, s) {
|
|
51
|
+
return this.request("PATCH", e, t, s);
|
|
52
52
|
}
|
|
53
|
-
async del(
|
|
54
|
-
return this.request("DELETE",
|
|
53
|
+
async del(e, t) {
|
|
54
|
+
return this.request("DELETE", e, void 0, t);
|
|
55
55
|
}
|
|
56
|
-
async uploadBinary(
|
|
56
|
+
async uploadBinary(e, t, s) {
|
|
57
57
|
try {
|
|
58
|
-
return await this.doUploadBinary(
|
|
58
|
+
return await this.doUploadBinary(e, t, s);
|
|
59
59
|
} catch (r) {
|
|
60
|
-
if (r instanceof
|
|
60
|
+
if (r instanceof g && r.isUnauthorized && this.onUnauthorized && (s != null && s.Authorization)) {
|
|
61
61
|
const i = await this.onUnauthorized();
|
|
62
62
|
if (i)
|
|
63
|
-
return this.doUploadBinary(
|
|
63
|
+
return this.doUploadBinary(e, t, {
|
|
64
64
|
...s,
|
|
65
65
|
Authorization: `Bearer ${i}`
|
|
66
66
|
});
|
|
@@ -68,35 +68,35 @@ class k {
|
|
|
68
68
|
throw r;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
async doUploadBinary(
|
|
71
|
+
async doUploadBinary(e, t, s) {
|
|
72
72
|
const r = {
|
|
73
73
|
"Content-Type": "application/octet-stream",
|
|
74
74
|
...this.getAuthHeaders(),
|
|
75
75
|
...s
|
|
76
|
-
}, i = await fetch(`${this.baseUrl}${
|
|
76
|
+
}, i = await fetch(`${this.baseUrl}${e}`, {
|
|
77
77
|
method: "POST",
|
|
78
78
|
headers: r,
|
|
79
|
-
body:
|
|
79
|
+
body: t
|
|
80
80
|
}), n = await i.json();
|
|
81
81
|
if (!i.ok || n.isOk === !1 || n.code && n.code >= 400) {
|
|
82
|
-
const a = this.inferDomain(
|
|
83
|
-
throw new
|
|
82
|
+
const a = this.inferDomain(e), c = n.code || i.status;
|
|
83
|
+
throw new g(c, n.message || "Upload failed", a);
|
|
84
84
|
}
|
|
85
85
|
return n.data;
|
|
86
86
|
}
|
|
87
|
-
async doRequest(
|
|
87
|
+
async doRequest(e, t, s, r) {
|
|
88
88
|
const i = {
|
|
89
89
|
"Content-Type": "application/json",
|
|
90
90
|
...this.getAuthHeaders(),
|
|
91
91
|
...r
|
|
92
|
-
}, n = await fetch(`${this.baseUrl}${
|
|
93
|
-
method:
|
|
92
|
+
}, n = await fetch(`${this.baseUrl}${t}`, {
|
|
93
|
+
method: e,
|
|
94
94
|
headers: i,
|
|
95
95
|
body: s ? JSON.stringify(s) : void 0
|
|
96
96
|
}), a = await n.json();
|
|
97
97
|
if (!n.ok || a.isOk === !1 || a.code && a.code >= 400) {
|
|
98
|
-
const
|
|
99
|
-
throw new
|
|
98
|
+
const c = this.inferDomain(t), o = a.code || n.status;
|
|
99
|
+
throw new g(o, a.message || "Request failed", c);
|
|
100
100
|
}
|
|
101
101
|
return a.data;
|
|
102
102
|
}
|
|
@@ -110,19 +110,19 @@ class k {
|
|
|
110
110
|
return { Authorization: `Bearer ${this.authMode.token}` };
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
inferDomain(
|
|
114
|
-
return
|
|
113
|
+
inferDomain(e) {
|
|
114
|
+
return e.startsWith("/auth") ? "auth" : e.startsWith("/billing") ? "billing" : e.startsWith("/report") ? "report" : "unknown";
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
-
class
|
|
118
|
-
constructor(
|
|
119
|
-
this.accessToken = null, this.refreshToken = null, this.refreshTimer = null, this.refreshInFlight = null, this.onRefreshNeeded = null, this.onTokensChanged = null, this.boundHandleStorage = null, this.storageKey = `ss_rt_${
|
|
117
|
+
class U {
|
|
118
|
+
constructor(e) {
|
|
119
|
+
this.accessToken = null, this.refreshToken = null, this.refreshTimer = null, this.refreshInFlight = null, this.onRefreshNeeded = null, this.onTokensChanged = null, this.boundHandleStorage = null, this.storageKey = `ss_rt_${e.slice(0, 12)}`, this.refreshToken = this.loadRefreshToken(), typeof window < "u" && (this.boundHandleStorage = this.handleStorageEvent.bind(this), window.addEventListener("storage", this.boundHandleStorage));
|
|
120
120
|
}
|
|
121
|
-
setRefreshCallback(
|
|
122
|
-
this.onRefreshNeeded =
|
|
121
|
+
setRefreshCallback(e) {
|
|
122
|
+
this.onRefreshNeeded = e;
|
|
123
123
|
}
|
|
124
|
-
setTokensChangedCallback(
|
|
125
|
-
this.onTokensChanged =
|
|
124
|
+
setTokensChangedCallback(e) {
|
|
125
|
+
this.onTokensChanged = e;
|
|
126
126
|
}
|
|
127
127
|
getAccessToken() {
|
|
128
128
|
return this.accessToken;
|
|
@@ -133,8 +133,8 @@ class b {
|
|
|
133
133
|
hasRefreshToken() {
|
|
134
134
|
return this.refreshToken !== null;
|
|
135
135
|
}
|
|
136
|
-
setTokens(
|
|
137
|
-
this.accessToken =
|
|
136
|
+
setTokens(e, t) {
|
|
137
|
+
this.accessToken = e, this.refreshToken = t, this.saveRefreshToken(t), this.scheduleRefresh(e);
|
|
138
138
|
}
|
|
139
139
|
clearTokens() {
|
|
140
140
|
this.accessToken = null, this.refreshToken = null, this.removeRefreshToken(), this.refreshTimer && (clearTimeout(this.refreshTimer), this.refreshTimer = null);
|
|
@@ -157,16 +157,16 @@ class b {
|
|
|
157
157
|
typeof navigator < "u" && "locks" in navigator ? await navigator.locks.request(
|
|
158
158
|
`ss_refresh_lock_${this.storageKey}`,
|
|
159
159
|
async () => {
|
|
160
|
-
const
|
|
161
|
-
|
|
160
|
+
const e = this.loadRefreshToken();
|
|
161
|
+
e && e !== this.refreshToken && (this.refreshToken = e), await this.onRefreshNeeded();
|
|
162
162
|
}
|
|
163
163
|
) : await this.onRefreshNeeded();
|
|
164
164
|
}
|
|
165
|
-
scheduleRefresh(
|
|
165
|
+
scheduleRefresh(e) {
|
|
166
166
|
this.refreshTimer && clearTimeout(this.refreshTimer);
|
|
167
|
-
const
|
|
168
|
-
if (!
|
|
169
|
-
const s =
|
|
167
|
+
const t = this.getTokenExpiry(e);
|
|
168
|
+
if (!t) return;
|
|
169
|
+
const s = t * 1e3 - Date.now() - 6e4;
|
|
170
170
|
if (s <= 0) {
|
|
171
171
|
this.refreshOnce().catch(() => {
|
|
172
172
|
});
|
|
@@ -177,20 +177,20 @@ class b {
|
|
|
177
177
|
});
|
|
178
178
|
}, s);
|
|
179
179
|
}
|
|
180
|
-
handleStorageEvent(
|
|
181
|
-
var
|
|
182
|
-
if (
|
|
183
|
-
if (
|
|
184
|
-
this.accessToken = null, this.refreshToken = null, this.refreshTimer && (clearTimeout(this.refreshTimer), this.refreshTimer = null), (
|
|
180
|
+
handleStorageEvent(e) {
|
|
181
|
+
var t;
|
|
182
|
+
if (e.key === this.storageKey) {
|
|
183
|
+
if (e.newValue === null) {
|
|
184
|
+
this.accessToken = null, this.refreshToken = null, this.refreshTimer && (clearTimeout(this.refreshTimer), this.refreshTimer = null), (t = this.onTokensChanged) == null || t.call(this);
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
187
|
-
|
|
187
|
+
e.newValue !== this.refreshToken && (this.refreshToken = e.newValue, this.accessToken = null, this.refreshTimer && (clearTimeout(this.refreshTimer), this.refreshTimer = null));
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
-
getTokenExpiry(
|
|
190
|
+
getTokenExpiry(e) {
|
|
191
191
|
try {
|
|
192
|
-
const
|
|
193
|
-
return JSON.parse(atob(
|
|
192
|
+
const t = e.split(".")[1];
|
|
193
|
+
return JSON.parse(atob(t)).exp ?? null;
|
|
194
194
|
} catch {
|
|
195
195
|
return null;
|
|
196
196
|
}
|
|
@@ -202,9 +202,9 @@ class b {
|
|
|
202
202
|
return null;
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
|
-
saveRefreshToken(
|
|
205
|
+
saveRefreshToken(e) {
|
|
206
206
|
try {
|
|
207
|
-
localStorage.setItem(this.storageKey,
|
|
207
|
+
localStorage.setItem(this.storageKey, e);
|
|
208
208
|
} catch {
|
|
209
209
|
}
|
|
210
210
|
}
|
|
@@ -215,28 +215,28 @@ class b {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
-
class
|
|
218
|
+
class S {
|
|
219
219
|
constructor() {
|
|
220
220
|
this.listeners = /* @__PURE__ */ new Map();
|
|
221
221
|
}
|
|
222
|
-
on(
|
|
223
|
-
return this.listeners.has(
|
|
222
|
+
on(e, t) {
|
|
223
|
+
return this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(t), () => {
|
|
224
224
|
var s;
|
|
225
|
-
(s = this.listeners.get(
|
|
225
|
+
(s = this.listeners.get(e)) == null || s.delete(t);
|
|
226
226
|
};
|
|
227
227
|
}
|
|
228
|
-
emit(
|
|
228
|
+
emit(e, t) {
|
|
229
229
|
var s;
|
|
230
|
-
(s = this.listeners.get(
|
|
230
|
+
(s = this.listeners.get(e)) == null || s.forEach((r) => r(t));
|
|
231
231
|
}
|
|
232
232
|
removeAll() {
|
|
233
233
|
this.listeners.clear();
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
|
-
const w = 500, T = 600,
|
|
237
|
-
class
|
|
238
|
-
constructor(
|
|
239
|
-
this.cachedUser = null, this.cachedSettings = null, this.loaded = !1, this.loadPromise = null, this.transport =
|
|
236
|
+
const w = 500, T = 600, b = 5 * 60 * 1e3;
|
|
237
|
+
class v {
|
|
238
|
+
constructor(e, t, s, r) {
|
|
239
|
+
this.cachedUser = null, this.cachedSettings = null, this.loaded = !1, this.loadPromise = null, this.transport = e, this.tokenManager = t, this.emitter = s, this.baseUrl = r;
|
|
240
240
|
}
|
|
241
241
|
// ---------------------------------------------------------------------------
|
|
242
242
|
// Lifecycle
|
|
@@ -248,99 +248,99 @@ class $ {
|
|
|
248
248
|
}), this.loadPromise);
|
|
249
249
|
}
|
|
250
250
|
async doLoad() {
|
|
251
|
-
var
|
|
251
|
+
var e, t;
|
|
252
252
|
try {
|
|
253
253
|
this.cachedSettings = await this.transport.get("/auth/settings");
|
|
254
254
|
} catch (s) {
|
|
255
255
|
console.warn("[SaaS Support] Failed to load project settings:", s);
|
|
256
256
|
}
|
|
257
|
-
if ((
|
|
257
|
+
if ((e = this.tokenManager) != null && e.hasRefreshToken())
|
|
258
258
|
try {
|
|
259
259
|
await this.tokenManager.refreshOnce();
|
|
260
260
|
} catch {
|
|
261
|
-
(
|
|
261
|
+
(t = this.tokenManager) == null || t.clearTokens();
|
|
262
262
|
}
|
|
263
263
|
this.loaded = !0;
|
|
264
264
|
}
|
|
265
265
|
// ---------------------------------------------------------------------------
|
|
266
266
|
// Core auth operations
|
|
267
267
|
// ---------------------------------------------------------------------------
|
|
268
|
-
async signIn(
|
|
269
|
-
const s = await this.transport.post("/auth/login", { email:
|
|
268
|
+
async signIn(e, t) {
|
|
269
|
+
const s = await this.transport.post("/auth/login", { email: e, password: t });
|
|
270
270
|
if ("mfaRequired" in s && s.mfaRequired)
|
|
271
271
|
return s;
|
|
272
272
|
const r = s;
|
|
273
273
|
return this.setSession(r), r;
|
|
274
274
|
}
|
|
275
|
-
async signUp(
|
|
276
|
-
const s = await this.transport.post("/auth/register", { email:
|
|
275
|
+
async signUp(e, t) {
|
|
276
|
+
const s = await this.transport.post("/auth/register", { email: e, password: t });
|
|
277
277
|
return this.setSession(s), s;
|
|
278
278
|
}
|
|
279
279
|
async signOut() {
|
|
280
|
-
var
|
|
281
|
-
const
|
|
282
|
-
if (
|
|
280
|
+
var t;
|
|
281
|
+
const e = (t = this.tokenManager) == null ? void 0 : t.getRefreshToken();
|
|
282
|
+
if (e)
|
|
283
283
|
try {
|
|
284
|
-
await this.transport.post("/auth/logout", { refreshToken:
|
|
284
|
+
await this.transport.post("/auth/logout", { refreshToken: e });
|
|
285
285
|
} catch {
|
|
286
286
|
}
|
|
287
287
|
this.clearSession();
|
|
288
288
|
}
|
|
289
|
-
async signInWithOAuth(
|
|
290
|
-
const
|
|
291
|
-
`/auth/oauth/${
|
|
289
|
+
async signInWithOAuth(e) {
|
|
290
|
+
const t = `${this.baseUrl}/auth/oauth/${e}/popup-callback`, { authUrl: s, state: r } = await this.transport.get(
|
|
291
|
+
`/auth/oauth/${e}?redirect_uri=${encodeURIComponent(t)}`
|
|
292
292
|
), i = window.screenX + (window.innerWidth - w) / 2, n = window.screenY + (window.innerHeight - T) / 2, a = window.open(
|
|
293
293
|
s,
|
|
294
294
|
"saas-support-oauth",
|
|
295
295
|
`width=${w},height=${T},left=${i},top=${n},toolbar=no,menubar=no`
|
|
296
296
|
);
|
|
297
|
-
return new Promise((
|
|
298
|
-
let
|
|
297
|
+
return new Promise((c, o) => {
|
|
298
|
+
let u = !1;
|
|
299
299
|
const d = async (l) => {
|
|
300
300
|
var m;
|
|
301
|
-
if (((m = l.data) == null ? void 0 : m.type) === "saas-support:oauth-callback" && !
|
|
302
|
-
if (
|
|
303
|
-
|
|
301
|
+
if (((m = l.data) == null ? void 0 : m.type) === "saas-support:oauth-callback" && !u) {
|
|
302
|
+
if (u = !0, window.removeEventListener("message", d), clearTimeout(y), clearInterval(p), a == null || a.close(), l.data.error) {
|
|
303
|
+
o(new Error(`OAuth error: ${l.data.error}`));
|
|
304
304
|
return;
|
|
305
305
|
}
|
|
306
306
|
try {
|
|
307
|
-
const
|
|
308
|
-
`/auth/oauth/${
|
|
307
|
+
const f = await this.transport.post(
|
|
308
|
+
`/auth/oauth/${e}/callback`,
|
|
309
309
|
{ code: l.data.code, state: l.data.state || r }
|
|
310
310
|
);
|
|
311
|
-
this.setSession(
|
|
312
|
-
} catch (
|
|
313
|
-
|
|
311
|
+
this.setSession(f), c(f);
|
|
312
|
+
} catch (f) {
|
|
313
|
+
o(f);
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
};
|
|
317
317
|
window.addEventListener("message", d);
|
|
318
318
|
const y = setTimeout(() => {
|
|
319
|
-
|
|
320
|
-
},
|
|
321
|
-
a != null && a.closed && !
|
|
319
|
+
u || (u = !0, window.removeEventListener("message", d), clearInterval(p), a == null || a.close(), o(new Error("OAuth popup timed out")));
|
|
320
|
+
}, b), p = setInterval(() => {
|
|
321
|
+
a != null && a.closed && !u && (u = !0, clearInterval(p), clearTimeout(y), window.removeEventListener("message", d), o(new Error("OAuth popup was closed")));
|
|
322
322
|
}, 500);
|
|
323
323
|
});
|
|
324
324
|
}
|
|
325
|
-
async submitMfaCode(
|
|
326
|
-
const s = await this.transport.post("/auth/login/mfa", { mfaToken:
|
|
325
|
+
async submitMfaCode(e, t) {
|
|
326
|
+
const s = await this.transport.post("/auth/login/mfa", { mfaToken: e, code: t });
|
|
327
327
|
return this.setSession(s), s;
|
|
328
328
|
}
|
|
329
329
|
// ---------------------------------------------------------------------------
|
|
330
330
|
// Magic link & password reset
|
|
331
331
|
// ---------------------------------------------------------------------------
|
|
332
|
-
async sendMagicLink(
|
|
333
|
-
await this.transport.post("/auth/magic-link/send", { email:
|
|
332
|
+
async sendMagicLink(e, t) {
|
|
333
|
+
await this.transport.post("/auth/magic-link/send", { email: e, redirectUrl: t });
|
|
334
334
|
}
|
|
335
|
-
async verifyMagicLink(
|
|
336
|
-
const
|
|
337
|
-
return this.setSession(
|
|
335
|
+
async verifyMagicLink(e) {
|
|
336
|
+
const t = await this.transport.post("/auth/magic-link/verify", { token: e });
|
|
337
|
+
return this.setSession(t), t;
|
|
338
338
|
}
|
|
339
|
-
async sendPasswordReset(
|
|
340
|
-
await this.transport.post("/auth/password-reset/send", { email:
|
|
339
|
+
async sendPasswordReset(e, t) {
|
|
340
|
+
await this.transport.post("/auth/password-reset/send", { email: e, redirectUrl: t });
|
|
341
341
|
}
|
|
342
|
-
async resetPassword(
|
|
343
|
-
await this.transport.post("/auth/password-reset/verify", { token:
|
|
342
|
+
async resetPassword(e, t) {
|
|
343
|
+
await this.transport.post("/auth/password-reset/verify", { token: e, newPassword: t });
|
|
344
344
|
}
|
|
345
345
|
// ---------------------------------------------------------------------------
|
|
346
346
|
// MFA management
|
|
@@ -348,19 +348,19 @@ class $ {
|
|
|
348
348
|
async setupMfa() {
|
|
349
349
|
return this.transport.post("/auth/mfa/setup", void 0, this.authHeaders());
|
|
350
350
|
}
|
|
351
|
-
async verifyMfa(
|
|
352
|
-
return this.transport.post("/auth/mfa/verify", { code:
|
|
351
|
+
async verifyMfa(e) {
|
|
352
|
+
return this.transport.post("/auth/mfa/verify", { code: e }, this.authHeaders());
|
|
353
353
|
}
|
|
354
|
-
async disableMfa(
|
|
355
|
-
await this.transport.post("/auth/mfa/disable", { code:
|
|
354
|
+
async disableMfa(e) {
|
|
355
|
+
await this.transport.post("/auth/mfa/disable", { code: e }, this.authHeaders());
|
|
356
356
|
}
|
|
357
357
|
// ---------------------------------------------------------------------------
|
|
358
358
|
// Token & user access
|
|
359
359
|
// ---------------------------------------------------------------------------
|
|
360
360
|
async getToken() {
|
|
361
|
-
var
|
|
362
|
-
const
|
|
363
|
-
if (
|
|
361
|
+
var t, s, r;
|
|
362
|
+
const e = ((t = this.tokenManager) == null ? void 0 : t.getAccessToken()) ?? null;
|
|
363
|
+
if (e) return e;
|
|
364
364
|
if ((s = this.tokenManager) != null && s.hasRefreshToken())
|
|
365
365
|
try {
|
|
366
366
|
return await this.tokenManager.refreshOnce(), ((r = this.tokenManager) == null ? void 0 : r.getAccessToken()) ?? null;
|
|
@@ -371,19 +371,19 @@ class $ {
|
|
|
371
371
|
}
|
|
372
372
|
async getUser() {
|
|
373
373
|
if (this.cachedUser) return this.cachedUser;
|
|
374
|
-
const
|
|
375
|
-
if (!
|
|
374
|
+
const e = await this.getToken();
|
|
375
|
+
if (!e) return null;
|
|
376
376
|
try {
|
|
377
|
-
return this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${
|
|
377
|
+
return this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${e}` }), this.cachedUser;
|
|
378
378
|
} catch {
|
|
379
379
|
return null;
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
382
|
async refreshUser() {
|
|
383
|
-
const
|
|
384
|
-
if (!
|
|
383
|
+
const e = await this.getToken();
|
|
384
|
+
if (!e) return this.cachedUser;
|
|
385
385
|
try {
|
|
386
|
-
return this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${
|
|
386
|
+
return this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${e}` }), this.emitter.emit("authStateChange", this.cachedUser), this.cachedUser;
|
|
387
387
|
} catch {
|
|
388
388
|
return this.cachedUser;
|
|
389
389
|
}
|
|
@@ -402,22 +402,22 @@ class $ {
|
|
|
402
402
|
return null;
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
|
-
onAuthStateChange(
|
|
406
|
-
return this.emitter.on("authStateChange",
|
|
405
|
+
onAuthStateChange(e) {
|
|
406
|
+
return this.emitter.on("authStateChange", e);
|
|
407
407
|
}
|
|
408
408
|
// ---------------------------------------------------------------------------
|
|
409
409
|
// Profile
|
|
410
410
|
// ---------------------------------------------------------------------------
|
|
411
|
-
async updateProfile(
|
|
412
|
-
const
|
|
413
|
-
return this.cachedUser =
|
|
411
|
+
async updateProfile(e) {
|
|
412
|
+
const t = await this.transport.patch("/auth/me", e, this.authHeaders());
|
|
413
|
+
return this.cachedUser = t, this.emitter.emit("authStateChange", t), t;
|
|
414
414
|
}
|
|
415
|
-
async uploadAvatar(
|
|
416
|
-
const
|
|
417
|
-
return this.cachedUser && (this.cachedUser = { ...this.cachedUser, avatarUrl:
|
|
415
|
+
async uploadAvatar(e) {
|
|
416
|
+
const t = await this.transport.uploadBinary("/auth/avatar", e, this.authHeaders());
|
|
417
|
+
return this.cachedUser && (this.cachedUser = { ...this.cachedUser, avatarUrl: t.avatarUrl }, this.emitter.emit("authStateChange", this.cachedUser)), t;
|
|
418
418
|
}
|
|
419
|
-
async changePassword(
|
|
420
|
-
await this.transport.post("/auth/change-password", { currentPassword:
|
|
419
|
+
async changePassword(e, t) {
|
|
420
|
+
await this.transport.post("/auth/change-password", { currentPassword: e, newPassword: t }, this.authHeaders());
|
|
421
421
|
}
|
|
422
422
|
// ---------------------------------------------------------------------------
|
|
423
423
|
// Organizations
|
|
@@ -425,54 +425,57 @@ class $ {
|
|
|
425
425
|
async listOrgs() {
|
|
426
426
|
return this.transport.get("/auth/orgs", this.authHeaders());
|
|
427
427
|
}
|
|
428
|
-
async createOrg(
|
|
429
|
-
return this.transport.post("/auth/orgs", { name:
|
|
428
|
+
async createOrg(e, t) {
|
|
429
|
+
return this.transport.post("/auth/orgs", { name: e, slug: t }, this.authHeaders());
|
|
430
|
+
}
|
|
431
|
+
async getOrg(e) {
|
|
432
|
+
return this.transport.get(`/auth/orgs/${e}`, this.authHeaders());
|
|
430
433
|
}
|
|
431
|
-
async
|
|
432
|
-
return this.transport.
|
|
434
|
+
async updateOrg(e, t) {
|
|
435
|
+
return this.transport.patch(`/auth/orgs/${e}`, t, this.authHeaders());
|
|
433
436
|
}
|
|
434
|
-
async
|
|
435
|
-
|
|
437
|
+
async deleteOrg(e) {
|
|
438
|
+
await this.transport.del(`/auth/orgs/${e}`, this.authHeaders());
|
|
436
439
|
}
|
|
437
|
-
async
|
|
438
|
-
|
|
440
|
+
async uploadOrgAvatar(e, t) {
|
|
441
|
+
return this.transport.uploadBinary(`/auth/orgs/${e}/avatar`, t, this.authHeaders());
|
|
439
442
|
}
|
|
440
443
|
// ---------------------------------------------------------------------------
|
|
441
444
|
// Members & Invites
|
|
442
445
|
// ---------------------------------------------------------------------------
|
|
443
|
-
async listMembers(
|
|
444
|
-
return this.transport.get(`/auth/orgs/${
|
|
446
|
+
async listMembers(e) {
|
|
447
|
+
return this.transport.get(`/auth/orgs/${e}/members`, this.authHeaders());
|
|
445
448
|
}
|
|
446
|
-
async sendInvite(
|
|
447
|
-
return this.transport.post(`/auth/orgs/${
|
|
449
|
+
async sendInvite(e, t, s) {
|
|
450
|
+
return this.transport.post(`/auth/orgs/${e}/invites`, { email: t, role: s }, this.authHeaders());
|
|
448
451
|
}
|
|
449
|
-
async updateMemberRole(
|
|
450
|
-
await this.transport.patch(`/auth/orgs/${
|
|
452
|
+
async updateMemberRole(e, t, s) {
|
|
453
|
+
await this.transport.patch(`/auth/orgs/${e}/members/${t}`, { role: s }, this.authHeaders());
|
|
451
454
|
}
|
|
452
|
-
async removeMember(
|
|
453
|
-
await this.transport.del(`/auth/orgs/${
|
|
455
|
+
async removeMember(e, t) {
|
|
456
|
+
await this.transport.del(`/auth/orgs/${e}/members/${t}`, this.authHeaders());
|
|
454
457
|
}
|
|
455
|
-
async acceptInvite(
|
|
456
|
-
return this.transport.post(`/auth/invites/${
|
|
458
|
+
async acceptInvite(e) {
|
|
459
|
+
return this.transport.post(`/auth/invites/${e}/accept`, void 0, this.authHeaders());
|
|
457
460
|
}
|
|
458
|
-
async listInvites(
|
|
459
|
-
return this.transport.get(`/auth/orgs/${
|
|
461
|
+
async listInvites(e) {
|
|
462
|
+
return this.transport.get(`/auth/orgs/${e}/invites`, this.authHeaders());
|
|
460
463
|
}
|
|
461
|
-
async revokeInvite(
|
|
462
|
-
await this.transport.del(`/auth/orgs/${
|
|
464
|
+
async revokeInvite(e, t) {
|
|
465
|
+
await this.transport.del(`/auth/orgs/${e}/invites/${t}`, this.authHeaders());
|
|
463
466
|
}
|
|
464
467
|
async listMyInvites() {
|
|
465
468
|
return this.transport.get("/auth/invites/pending", this.authHeaders());
|
|
466
469
|
}
|
|
467
|
-
async acceptInviteById(
|
|
470
|
+
async acceptInviteById(e) {
|
|
468
471
|
return this.transport.post(
|
|
469
|
-
`/auth/invites/${
|
|
472
|
+
`/auth/invites/${e}/accept-by-id`,
|
|
470
473
|
void 0,
|
|
471
474
|
this.authHeaders()
|
|
472
475
|
);
|
|
473
476
|
}
|
|
474
|
-
async declineInvite(
|
|
475
|
-
await this.transport.del(`/auth/invites/${
|
|
477
|
+
async declineInvite(e) {
|
|
478
|
+
await this.transport.del(`/auth/invites/${e}/decline`, this.authHeaders());
|
|
476
479
|
}
|
|
477
480
|
async deleteAccount() {
|
|
478
481
|
await this.transport.del("/auth/account", this.authHeaders()), this.clearSession();
|
|
@@ -487,144 +490,46 @@ class $ {
|
|
|
487
490
|
/** @internal */
|
|
488
491
|
async performRefresh() {
|
|
489
492
|
var s;
|
|
490
|
-
const
|
|
491
|
-
if (!
|
|
492
|
-
const
|
|
493
|
+
const e = (s = this.tokenManager) == null ? void 0 : s.getRefreshToken();
|
|
494
|
+
if (!e) throw new Error("No refresh token");
|
|
495
|
+
const t = await this.transport.post(
|
|
493
496
|
"/auth/refresh",
|
|
494
|
-
{ refreshToken:
|
|
497
|
+
{ refreshToken: e }
|
|
495
498
|
);
|
|
496
|
-
if (this.tokenManager.setTokens(
|
|
499
|
+
if (this.tokenManager.setTokens(t.accessToken, t.refreshToken), !this.cachedUser)
|
|
497
500
|
try {
|
|
498
|
-
this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${
|
|
501
|
+
this.cachedUser = await this.transport.get("/auth/me", { Authorization: `Bearer ${t.accessToken}` }), this.emitter.emit("authStateChange", this.cachedUser);
|
|
499
502
|
} catch {
|
|
500
503
|
}
|
|
501
504
|
}
|
|
502
|
-
setSession(
|
|
503
|
-
var e;
|
|
504
|
-
(e = this.tokenManager) == null || e.setTokens(t.accessToken, t.refreshToken), this.cachedUser = t.user, this.emitter.emit("authStateChange", t.user), this.refreshUser();
|
|
505
|
-
}
|
|
506
|
-
clearSession() {
|
|
505
|
+
setSession(e) {
|
|
507
506
|
var t;
|
|
508
|
-
(t = this.tokenManager) == null || t.
|
|
507
|
+
(t = this.tokenManager) == null || t.setTokens(e.accessToken, e.refreshToken), this.cachedUser = e.user, this.emitter.emit("authStateChange", e.user), this.refreshUser();
|
|
509
508
|
}
|
|
510
|
-
|
|
509
|
+
clearSession() {
|
|
511
510
|
var e;
|
|
512
|
-
|
|
513
|
-
return t ? { Authorization: `Bearer ${t}` } : {};
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
class v {
|
|
517
|
-
constructor(t) {
|
|
518
|
-
this.transport = t;
|
|
519
|
-
}
|
|
520
|
-
// --- Customer ---
|
|
521
|
-
async createCustomer(t) {
|
|
522
|
-
return this.transport.post("/billing/customers", t);
|
|
523
|
-
}
|
|
524
|
-
async getCustomer(t) {
|
|
525
|
-
return this.transport.get(`/billing/customers/${t}`);
|
|
526
|
-
}
|
|
527
|
-
async updateCustomer(t, e) {
|
|
528
|
-
return this.transport.patch(`/billing/customers/${t}`, e);
|
|
529
|
-
}
|
|
530
|
-
// --- Subscription ---
|
|
531
|
-
async subscribe(t, e) {
|
|
532
|
-
return this.transport.post(`/billing/customers/${t}/subscribe`, { planId: e });
|
|
533
|
-
}
|
|
534
|
-
async changePlan(t, e) {
|
|
535
|
-
return this.transport.patch(`/billing/customers/${t}/subscription`, { planId: e });
|
|
536
|
-
}
|
|
537
|
-
async cancelSubscription(t) {
|
|
538
|
-
return this.transport.del(`/billing/customers/${t}/subscription`);
|
|
539
|
-
}
|
|
540
|
-
// --- Invoices ---
|
|
541
|
-
async getInvoices(t) {
|
|
542
|
-
return this.transport.get(`/billing/customers/${t}/invoices`);
|
|
511
|
+
(e = this.tokenManager) == null || e.clearTokens(), this.cachedUser = null, this.emitter.emit("authStateChange", null);
|
|
543
512
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
async getCurrentUsage(t) {
|
|
549
|
-
return this.transport.get(`/billing/customers/${t}/usage`);
|
|
550
|
-
}
|
|
551
|
-
// --- Portal ---
|
|
552
|
-
async createPortalToken(t, e) {
|
|
553
|
-
return this.transport.post("/billing/portal-tokens", { customerId: t, expiresIn: e });
|
|
554
|
-
}
|
|
555
|
-
// --- Coupon ---
|
|
556
|
-
async applyCoupon(t, e) {
|
|
557
|
-
return this.transport.post(`/billing/customers/${t}/coupon`, { code: e });
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
class R {
|
|
561
|
-
constructor(t) {
|
|
562
|
-
this.transport = t;
|
|
563
|
-
}
|
|
564
|
-
// --- Query ---
|
|
565
|
-
async executeQuery(t) {
|
|
566
|
-
return this.transport.post("/report/query", t);
|
|
567
|
-
}
|
|
568
|
-
// --- Saved Queries ---
|
|
569
|
-
async listQueries(t) {
|
|
570
|
-
const e = t ? this.toQueryString(t) : "";
|
|
571
|
-
return this.transport.get(`/report/queries${e}`);
|
|
572
|
-
}
|
|
573
|
-
async saveQuery(t) {
|
|
574
|
-
return this.transport.post("/report/queries", t);
|
|
575
|
-
}
|
|
576
|
-
async updateQuery(t, e) {
|
|
577
|
-
return this.transport.patch(`/report/queries/${t}`, e);
|
|
578
|
-
}
|
|
579
|
-
async deleteQuery(t) {
|
|
580
|
-
await this.transport.del(`/report/queries/${t}`);
|
|
581
|
-
}
|
|
582
|
-
// --- Dashboards ---
|
|
583
|
-
async listDashboards(t) {
|
|
584
|
-
const e = t ? this.toQueryString(t) : "";
|
|
585
|
-
return this.transport.get(`/report/dashboards${e}`);
|
|
586
|
-
}
|
|
587
|
-
async createDashboard(t) {
|
|
588
|
-
return this.transport.post("/report/dashboards", t);
|
|
589
|
-
}
|
|
590
|
-
async getDashboard(t) {
|
|
591
|
-
return this.transport.get(`/report/dashboards/${t}`);
|
|
592
|
-
}
|
|
593
|
-
async updateDashboard(t, e) {
|
|
594
|
-
return this.transport.patch(`/report/dashboards/${t}`, e);
|
|
595
|
-
}
|
|
596
|
-
async deleteDashboard(t) {
|
|
597
|
-
await this.transport.del(`/report/dashboards/${t}`);
|
|
598
|
-
}
|
|
599
|
-
// --- Embed Tokens ---
|
|
600
|
-
async createEmbedToken(t) {
|
|
601
|
-
return this.transport.post("/report/embed-tokens", t);
|
|
602
|
-
}
|
|
603
|
-
async listEmbedTokens() {
|
|
604
|
-
return this.transport.get("/report/embed-tokens");
|
|
605
|
-
}
|
|
606
|
-
async revokeEmbedToken(t) {
|
|
607
|
-
await this.transport.del(`/report/embed-tokens/${t}`);
|
|
608
|
-
}
|
|
609
|
-
toQueryString(t) {
|
|
610
|
-
const e = Object.entries(t).filter(([, s]) => s != null && s !== "");
|
|
611
|
-
return e.length === 0 ? "" : "?" + e.map(([s, r]) => `${s}=${encodeURIComponent(String(r))}`).join("&");
|
|
513
|
+
authHeaders() {
|
|
514
|
+
var t;
|
|
515
|
+
const e = (t = this.tokenManager) == null ? void 0 : t.getAccessToken();
|
|
516
|
+
return e ? { Authorization: `Bearer ${e}` } : {};
|
|
612
517
|
}
|
|
613
518
|
}
|
|
614
519
|
const H = "https://api.saas-support.com/v1";
|
|
615
520
|
class M {
|
|
616
|
-
constructor(
|
|
617
|
-
if (this.tokenManager = null, this.loaded = !1, this.loadPromise = null, !
|
|
521
|
+
constructor(e) {
|
|
522
|
+
if (this.tokenManager = null, this.loaded = !1, this.loadPromise = null, !e.publishableKey && !e.apiKey)
|
|
618
523
|
throw new Error("SaaSSupport: either publishableKey or apiKey is required");
|
|
619
|
-
const
|
|
620
|
-
this.emitter = new
|
|
621
|
-
const s =
|
|
622
|
-
|
|
524
|
+
const t = e.baseUrl ?? H;
|
|
525
|
+
this.emitter = new S();
|
|
526
|
+
const s = e.publishableKey ? new k(t, { type: "publishableKey", key: e.publishableKey }) : null, r = e.apiKey ? new k(t, { type: "apiKey", key: e.apiKey }) : null;
|
|
527
|
+
e.publishableKey && (this.tokenManager = new U(e.publishableKey)), this.auth = new v(
|
|
623
528
|
s ?? r,
|
|
624
529
|
this.tokenManager,
|
|
625
530
|
this.emitter,
|
|
626
|
-
|
|
627
|
-
), this.
|
|
531
|
+
t
|
|
532
|
+
), this.tokenManager && (this.tokenManager.setRefreshCallback(() => this.auth.performRefresh()), this.tokenManager.setTokensChangedCallback(() => {
|
|
628
533
|
this.tokenManager.hasRefreshToken() || this.auth.handleExternalLogout();
|
|
629
534
|
})), this.tokenManager && s && s.setUnauthorizedHandler(async () => {
|
|
630
535
|
try {
|
|
@@ -645,23 +550,21 @@ class M {
|
|
|
645
550
|
isLoaded() {
|
|
646
551
|
return this.loaded;
|
|
647
552
|
}
|
|
648
|
-
onError(
|
|
649
|
-
return this.emitter.on("error",
|
|
553
|
+
onError(e) {
|
|
554
|
+
return this.emitter.on("error", e);
|
|
650
555
|
}
|
|
651
556
|
destroy() {
|
|
652
|
-
var
|
|
653
|
-
(
|
|
557
|
+
var e;
|
|
558
|
+
(e = this.tokenManager) == null || e.destroy(), this.emitter.removeAll();
|
|
654
559
|
}
|
|
655
560
|
}
|
|
656
|
-
function
|
|
657
|
-
return "mfaRequired" in
|
|
561
|
+
function R(h) {
|
|
562
|
+
return "mfaRequired" in h && h.mfaRequired === !0;
|
|
658
563
|
}
|
|
659
564
|
export {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
R as ReportClient,
|
|
663
|
-
p as SaaSError,
|
|
565
|
+
v as AuthClient,
|
|
566
|
+
g as SaaSError,
|
|
664
567
|
M as SaaSSupport,
|
|
665
568
|
k as Transport,
|
|
666
|
-
|
|
569
|
+
R as isMfaRequired
|
|
667
570
|
};
|