@saas-support/react 0.7.5 → 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 +23 -231
- package/dist/index.js +204 -288
- package/dist/react.cjs +386 -348
- package/dist/react.d.ts +41 -438
- package/dist/react.js +1133 -2075
- 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,41 +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
430
|
}
|
|
431
|
-
async getOrg(
|
|
432
|
-
return this.transport.get(`/auth/orgs/${
|
|
431
|
+
async getOrg(e) {
|
|
432
|
+
return this.transport.get(`/auth/orgs/${e}`, this.authHeaders());
|
|
433
433
|
}
|
|
434
|
-
async updateOrg(
|
|
435
|
-
return this.transport.patch(`/auth/orgs/${
|
|
434
|
+
async updateOrg(e, t) {
|
|
435
|
+
return this.transport.patch(`/auth/orgs/${e}`, t, this.authHeaders());
|
|
436
436
|
}
|
|
437
|
-
async deleteOrg(
|
|
438
|
-
await this.transport.del(`/auth/orgs/${
|
|
437
|
+
async deleteOrg(e) {
|
|
438
|
+
await this.transport.del(`/auth/orgs/${e}`, this.authHeaders());
|
|
439
|
+
}
|
|
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());
|
|
448
|
+
}
|
|
449
|
+
async sendInvite(e, t, s) {
|
|
450
|
+
return this.transport.post(`/auth/orgs/${e}/invites`, { email: t, role: s }, this.authHeaders());
|
|
451
|
+
}
|
|
452
|
+
async updateMemberRole(e, t, s) {
|
|
453
|
+
await this.transport.patch(`/auth/orgs/${e}/members/${t}`, { role: s }, this.authHeaders());
|
|
445
454
|
}
|
|
446
|
-
async
|
|
447
|
-
|
|
455
|
+
async removeMember(e, t) {
|
|
456
|
+
await this.transport.del(`/auth/orgs/${e}/members/${t}`, this.authHeaders());
|
|
448
457
|
}
|
|
449
|
-
async
|
|
450
|
-
|
|
458
|
+
async acceptInvite(e) {
|
|
459
|
+
return this.transport.post(`/auth/invites/${e}/accept`, void 0, this.authHeaders());
|
|
451
460
|
}
|
|
452
|
-
async
|
|
453
|
-
|
|
461
|
+
async listInvites(e) {
|
|
462
|
+
return this.transport.get(`/auth/orgs/${e}/invites`, this.authHeaders());
|
|
454
463
|
}
|
|
455
|
-
async
|
|
456
|
-
|
|
464
|
+
async revokeInvite(e, t) {
|
|
465
|
+
await this.transport.del(`/auth/orgs/${e}/invites/${t}`, this.authHeaders());
|
|
457
466
|
}
|
|
458
|
-
async
|
|
459
|
-
return this.transport.get(
|
|
467
|
+
async listMyInvites() {
|
|
468
|
+
return this.transport.get("/auth/invites/pending", this.authHeaders());
|
|
460
469
|
}
|
|
461
|
-
async
|
|
462
|
-
|
|
470
|
+
async acceptInviteById(e) {
|
|
471
|
+
return this.transport.post(
|
|
472
|
+
`/auth/invites/${e}/accept-by-id`,
|
|
473
|
+
void 0,
|
|
474
|
+
this.authHeaders()
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
async declineInvite(e) {
|
|
478
|
+
await this.transport.del(`/auth/invites/${e}/decline`, this.authHeaders());
|
|
463
479
|
}
|
|
464
480
|
async deleteAccount() {
|
|
465
481
|
await this.transport.del("/auth/account", this.authHeaders()), this.clearSession();
|
|
@@ -474,144 +490,46 @@ class $ {
|
|
|
474
490
|
/** @internal */
|
|
475
491
|
async performRefresh() {
|
|
476
492
|
var s;
|
|
477
|
-
const
|
|
478
|
-
if (!
|
|
479
|
-
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(
|
|
480
496
|
"/auth/refresh",
|
|
481
|
-
{ refreshToken:
|
|
497
|
+
{ refreshToken: e }
|
|
482
498
|
);
|
|
483
|
-
if (this.tokenManager.setTokens(
|
|
499
|
+
if (this.tokenManager.setTokens(t.accessToken, t.refreshToken), !this.cachedUser)
|
|
484
500
|
try {
|
|
485
|
-
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);
|
|
486
502
|
} catch {
|
|
487
503
|
}
|
|
488
504
|
}
|
|
489
|
-
setSession(
|
|
490
|
-
var e;
|
|
491
|
-
(e = this.tokenManager) == null || e.setTokens(t.accessToken, t.refreshToken), this.cachedUser = t.user, this.emitter.emit("authStateChange", t.user), this.refreshUser();
|
|
492
|
-
}
|
|
493
|
-
clearSession() {
|
|
505
|
+
setSession(e) {
|
|
494
506
|
var t;
|
|
495
|
-
(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();
|
|
496
508
|
}
|
|
497
|
-
|
|
509
|
+
clearSession() {
|
|
498
510
|
var e;
|
|
499
|
-
|
|
500
|
-
return t ? { Authorization: `Bearer ${t}` } : {};
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
class v {
|
|
504
|
-
constructor(t) {
|
|
505
|
-
this.transport = t;
|
|
506
|
-
}
|
|
507
|
-
// --- Customer ---
|
|
508
|
-
async createCustomer(t) {
|
|
509
|
-
return this.transport.post("/billing/customers", t);
|
|
510
|
-
}
|
|
511
|
-
async getCustomer(t) {
|
|
512
|
-
return this.transport.get(`/billing/customers/${t}`);
|
|
513
|
-
}
|
|
514
|
-
async updateCustomer(t, e) {
|
|
515
|
-
return this.transport.patch(`/billing/customers/${t}`, e);
|
|
516
|
-
}
|
|
517
|
-
// --- Subscription ---
|
|
518
|
-
async subscribe(t, e) {
|
|
519
|
-
return this.transport.post(`/billing/customers/${t}/subscribe`, { planId: e });
|
|
520
|
-
}
|
|
521
|
-
async changePlan(t, e) {
|
|
522
|
-
return this.transport.patch(`/billing/customers/${t}/subscription`, { planId: e });
|
|
511
|
+
(e = this.tokenManager) == null || e.clearTokens(), this.cachedUser = null, this.emitter.emit("authStateChange", null);
|
|
523
512
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
async getInvoices(t) {
|
|
529
|
-
return this.transport.get(`/billing/customers/${t}/invoices`);
|
|
530
|
-
}
|
|
531
|
-
// --- Usage ---
|
|
532
|
-
async ingestUsageEvent(t) {
|
|
533
|
-
return this.transport.post("/billing/events", t);
|
|
534
|
-
}
|
|
535
|
-
async getCurrentUsage(t) {
|
|
536
|
-
return this.transport.get(`/billing/customers/${t}/usage`);
|
|
537
|
-
}
|
|
538
|
-
// --- Portal ---
|
|
539
|
-
async createPortalToken(t, e) {
|
|
540
|
-
return this.transport.post("/billing/portal-tokens", { customerId: t, expiresIn: e });
|
|
541
|
-
}
|
|
542
|
-
// --- Coupon ---
|
|
543
|
-
async applyCoupon(t, e) {
|
|
544
|
-
return this.transport.post(`/billing/customers/${t}/coupon`, { code: e });
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
class R {
|
|
548
|
-
constructor(t) {
|
|
549
|
-
this.transport = t;
|
|
550
|
-
}
|
|
551
|
-
// --- Query ---
|
|
552
|
-
async executeQuery(t) {
|
|
553
|
-
return this.transport.post("/report/query", t);
|
|
554
|
-
}
|
|
555
|
-
// --- Saved Queries ---
|
|
556
|
-
async listQueries(t) {
|
|
557
|
-
const e = t ? this.toQueryString(t) : "";
|
|
558
|
-
return this.transport.get(`/report/queries${e}`);
|
|
559
|
-
}
|
|
560
|
-
async saveQuery(t) {
|
|
561
|
-
return this.transport.post("/report/queries", t);
|
|
562
|
-
}
|
|
563
|
-
async updateQuery(t, e) {
|
|
564
|
-
return this.transport.patch(`/report/queries/${t}`, e);
|
|
565
|
-
}
|
|
566
|
-
async deleteQuery(t) {
|
|
567
|
-
await this.transport.del(`/report/queries/${t}`);
|
|
568
|
-
}
|
|
569
|
-
// --- Dashboards ---
|
|
570
|
-
async listDashboards(t) {
|
|
571
|
-
const e = t ? this.toQueryString(t) : "";
|
|
572
|
-
return this.transport.get(`/report/dashboards${e}`);
|
|
573
|
-
}
|
|
574
|
-
async createDashboard(t) {
|
|
575
|
-
return this.transport.post("/report/dashboards", t);
|
|
576
|
-
}
|
|
577
|
-
async getDashboard(t) {
|
|
578
|
-
return this.transport.get(`/report/dashboards/${t}`);
|
|
579
|
-
}
|
|
580
|
-
async updateDashboard(t, e) {
|
|
581
|
-
return this.transport.patch(`/report/dashboards/${t}`, e);
|
|
582
|
-
}
|
|
583
|
-
async deleteDashboard(t) {
|
|
584
|
-
await this.transport.del(`/report/dashboards/${t}`);
|
|
585
|
-
}
|
|
586
|
-
// --- Embed Tokens ---
|
|
587
|
-
async createEmbedToken(t) {
|
|
588
|
-
return this.transport.post("/report/embed-tokens", t);
|
|
589
|
-
}
|
|
590
|
-
async listEmbedTokens() {
|
|
591
|
-
return this.transport.get("/report/embed-tokens");
|
|
592
|
-
}
|
|
593
|
-
async revokeEmbedToken(t) {
|
|
594
|
-
await this.transport.del(`/report/embed-tokens/${t}`);
|
|
595
|
-
}
|
|
596
|
-
toQueryString(t) {
|
|
597
|
-
const e = Object.entries(t).filter(([, s]) => s != null && s !== "");
|
|
598
|
-
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}` } : {};
|
|
599
517
|
}
|
|
600
518
|
}
|
|
601
|
-
const
|
|
602
|
-
class
|
|
603
|
-
constructor(
|
|
604
|
-
if (this.tokenManager = null, this.loaded = !1, this.loadPromise = null, !
|
|
519
|
+
const H = "https://api.saas-support.com/v1";
|
|
520
|
+
class M {
|
|
521
|
+
constructor(e) {
|
|
522
|
+
if (this.tokenManager = null, this.loaded = !1, this.loadPromise = null, !e.publishableKey && !e.apiKey)
|
|
605
523
|
throw new Error("SaaSSupport: either publishableKey or apiKey is required");
|
|
606
|
-
const
|
|
607
|
-
this.emitter = new
|
|
608
|
-
const s =
|
|
609
|
-
|
|
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(
|
|
610
528
|
s ?? r,
|
|
611
529
|
this.tokenManager,
|
|
612
530
|
this.emitter,
|
|
613
|
-
|
|
614
|
-
), this.
|
|
531
|
+
t
|
|
532
|
+
), this.tokenManager && (this.tokenManager.setRefreshCallback(() => this.auth.performRefresh()), this.tokenManager.setTokensChangedCallback(() => {
|
|
615
533
|
this.tokenManager.hasRefreshToken() || this.auth.handleExternalLogout();
|
|
616
534
|
})), this.tokenManager && s && s.setUnauthorizedHandler(async () => {
|
|
617
535
|
try {
|
|
@@ -632,23 +550,21 @@ class H {
|
|
|
632
550
|
isLoaded() {
|
|
633
551
|
return this.loaded;
|
|
634
552
|
}
|
|
635
|
-
onError(
|
|
636
|
-
return this.emitter.on("error",
|
|
553
|
+
onError(e) {
|
|
554
|
+
return this.emitter.on("error", e);
|
|
637
555
|
}
|
|
638
556
|
destroy() {
|
|
639
|
-
var
|
|
640
|
-
(
|
|
557
|
+
var e;
|
|
558
|
+
(e = this.tokenManager) == null || e.destroy(), this.emitter.removeAll();
|
|
641
559
|
}
|
|
642
560
|
}
|
|
643
|
-
function
|
|
644
|
-
return "mfaRequired" in
|
|
561
|
+
function R(h) {
|
|
562
|
+
return "mfaRequired" in h && h.mfaRequired === !0;
|
|
645
563
|
}
|
|
646
564
|
export {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
p as SaaSError,
|
|
651
|
-
H as SaaSSupport,
|
|
565
|
+
v as AuthClient,
|
|
566
|
+
g as SaaSError,
|
|
567
|
+
M as SaaSSupport,
|
|
652
568
|
k as Transport,
|
|
653
|
-
|
|
569
|
+
R as isMfaRequired
|
|
654
570
|
};
|