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