@authon/js 0.1.6 → 0.1.8
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.js +98 -19
- package/dist/index.mjs +98 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -131,6 +131,25 @@ var ModalRenderer = class {
|
|
|
131
131
|
this.containerElement.innerHTML = "";
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
showLoading() {
|
|
135
|
+
if (!this.shadowRoot) return;
|
|
136
|
+
this.hideLoading();
|
|
137
|
+
const overlay = document.createElement("div");
|
|
138
|
+
overlay.id = "authon-loading-overlay";
|
|
139
|
+
overlay.innerHTML = `
|
|
140
|
+
<div class="loading-spinner">
|
|
141
|
+
<div class="loading-ring"></div>
|
|
142
|
+
<div class="loading-ring"></div>
|
|
143
|
+
<div class="loading-ring"></div>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="loading-text">Signing in<span class="loading-dots"><span></span><span></span><span></span></span></div>
|
|
146
|
+
`;
|
|
147
|
+
this.shadowRoot.querySelector(".modal-container")?.appendChild(overlay);
|
|
148
|
+
}
|
|
149
|
+
hideLoading() {
|
|
150
|
+
if (!this.shadowRoot) return;
|
|
151
|
+
this.shadowRoot.getElementById("authon-loading-overlay")?.remove();
|
|
152
|
+
}
|
|
134
153
|
render(view) {
|
|
135
154
|
const host = document.createElement("div");
|
|
136
155
|
host.setAttribute("data-authon-modal", "");
|
|
@@ -234,6 +253,7 @@ var ModalRenderer = class {
|
|
|
234
253
|
border-radius: var(--authon-radius);
|
|
235
254
|
padding: 32px;
|
|
236
255
|
width: 400px; max-width: 100%;
|
|
256
|
+
position: ${this.mode === "popup" ? "fixed" : "relative"};
|
|
237
257
|
${this.mode === "popup" ? `box-shadow: 0 25px 50px -12px rgba(0,0,0,${dark ? "0.5" : "0.25"}); animation: slideIn 0.3s ease;` : ""}
|
|
238
258
|
}
|
|
239
259
|
.logo { display: block; margin: 0 auto 16px; max-height: 48px; }
|
|
@@ -288,6 +308,39 @@ var ModalRenderer = class {
|
|
|
288
308
|
font-size: 11px; color: var(--authon-dim);
|
|
289
309
|
}
|
|
290
310
|
.secured-brand { font-weight: 600; color: var(--authon-muted); }
|
|
311
|
+
/* Loading overlay */
|
|
312
|
+
#authon-loading-overlay {
|
|
313
|
+
position: absolute; inset: 0; z-index: 10;
|
|
314
|
+
background: ${dark ? "rgba(15,23,42,0.92)" : "rgba(255,255,255,0.92)"};
|
|
315
|
+
backdrop-filter: blur(2px);
|
|
316
|
+
border-radius: var(--authon-radius);
|
|
317
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px;
|
|
318
|
+
animation: fadeIn 0.15s ease;
|
|
319
|
+
}
|
|
320
|
+
.loading-spinner { position: relative; width: 48px; height: 48px; }
|
|
321
|
+
.loading-ring {
|
|
322
|
+
position: absolute; inset: 0;
|
|
323
|
+
border: 2.5px solid transparent; border-top-color: var(--authon-primary-start);
|
|
324
|
+
border-radius: 50%; animation: spin 1s cubic-bezier(.55,.15,.45,.85) infinite;
|
|
325
|
+
}
|
|
326
|
+
.loading-ring:nth-child(2) {
|
|
327
|
+
inset: 5px; border-top-color: transparent; border-right-color: var(--authon-primary-end);
|
|
328
|
+
animation-duration: 1.2s; animation-direction: reverse; opacity: .7;
|
|
329
|
+
}
|
|
330
|
+
.loading-ring:nth-child(3) {
|
|
331
|
+
inset: 10px; border-top-color: transparent; border-bottom-color: var(--authon-primary-start);
|
|
332
|
+
animation-duration: .8s; opacity: .4;
|
|
333
|
+
}
|
|
334
|
+
.loading-text { font-size: 14px; font-weight: 500; color: var(--authon-muted); }
|
|
335
|
+
.loading-dots { display: inline-flex; gap: 2px; margin-left: 2px; }
|
|
336
|
+
.loading-dots span {
|
|
337
|
+
width: 3px; height: 3px; border-radius: 50%;
|
|
338
|
+
background: var(--authon-muted); animation: blink 1.4s infinite both;
|
|
339
|
+
}
|
|
340
|
+
.loading-dots span:nth-child(2) { animation-delay: .2s; }
|
|
341
|
+
.loading-dots span:nth-child(3) { animation-delay: .4s; }
|
|
342
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
343
|
+
@keyframes blink { 0%,80%,100% { opacity: .2; } 40% { opacity: 1; } }
|
|
291
344
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
292
345
|
@keyframes slideIn { from { opacity: 0; transform: translate(-50%, -48%); } to { opacity: 1; transform: translate(-50%, -50%); } }
|
|
293
346
|
${b.customCss || ""}
|
|
@@ -339,6 +392,7 @@ var ModalRenderer = class {
|
|
|
339
392
|
// src/session.ts
|
|
340
393
|
var SessionManager = class {
|
|
341
394
|
accessToken = null;
|
|
395
|
+
refreshToken = null;
|
|
342
396
|
user = null;
|
|
343
397
|
refreshTimer = null;
|
|
344
398
|
apiUrl;
|
|
@@ -355,11 +409,15 @@ var SessionManager = class {
|
|
|
355
409
|
}
|
|
356
410
|
setSession(tokens) {
|
|
357
411
|
this.accessToken = tokens.accessToken;
|
|
412
|
+
this.refreshToken = tokens.refreshToken;
|
|
358
413
|
this.user = tokens.user;
|
|
359
|
-
|
|
414
|
+
if (tokens.expiresIn && tokens.expiresIn > 0) {
|
|
415
|
+
this.scheduleRefresh(tokens.expiresIn);
|
|
416
|
+
}
|
|
360
417
|
}
|
|
361
418
|
clearSession() {
|
|
362
419
|
this.accessToken = null;
|
|
420
|
+
this.refreshToken = null;
|
|
363
421
|
this.user = null;
|
|
364
422
|
if (this.refreshTimer) {
|
|
365
423
|
clearTimeout(this.refreshTimer);
|
|
@@ -368,10 +426,14 @@ var SessionManager = class {
|
|
|
368
426
|
}
|
|
369
427
|
scheduleRefresh(expiresIn) {
|
|
370
428
|
if (this.refreshTimer) clearTimeout(this.refreshTimer);
|
|
371
|
-
const refreshIn = Math.max((expiresIn - 60) * 1e3,
|
|
429
|
+
const refreshIn = Math.max((expiresIn - 60) * 1e3, 3e4);
|
|
372
430
|
this.refreshTimer = setTimeout(() => this.refresh(), refreshIn);
|
|
373
431
|
}
|
|
374
432
|
async refresh() {
|
|
433
|
+
if (!this.refreshToken) {
|
|
434
|
+
this.clearSession();
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
375
437
|
try {
|
|
376
438
|
const res = await fetch(`${this.apiUrl}/v1/auth/token/refresh`, {
|
|
377
439
|
method: "POST",
|
|
@@ -379,7 +441,8 @@ var SessionManager = class {
|
|
|
379
441
|
"Content-Type": "application/json",
|
|
380
442
|
"x-api-key": this.publishableKey
|
|
381
443
|
},
|
|
382
|
-
credentials: "include"
|
|
444
|
+
credentials: "include",
|
|
445
|
+
body: JSON.stringify({ refreshToken: this.refreshToken })
|
|
383
446
|
});
|
|
384
447
|
if (!res.ok) {
|
|
385
448
|
this.clearSession();
|
|
@@ -532,6 +595,7 @@ var Authon = class {
|
|
|
532
595
|
const { url } = await this.apiGet(
|
|
533
596
|
`/v1/auth/oauth/${provider}/url?redirectUri=${encodeURIComponent(redirectUri)}`
|
|
534
597
|
);
|
|
598
|
+
this.modal?.showLoading();
|
|
535
599
|
const width = 500;
|
|
536
600
|
const height = 700;
|
|
537
601
|
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
@@ -541,27 +605,42 @@ var Authon = class {
|
|
|
541
605
|
"authon-oauth",
|
|
542
606
|
`width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`
|
|
543
607
|
);
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
});
|
|
555
|
-
this.session.setSession(tokens);
|
|
556
|
-
this.modal?.close();
|
|
557
|
-
this.emit("signedIn", tokens.user);
|
|
558
|
-
} catch (err) {
|
|
559
|
-
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
608
|
+
let callbackReceived = false;
|
|
609
|
+
const pollTimer = setInterval(() => {
|
|
610
|
+
if (callbackReceived) return;
|
|
611
|
+
try {
|
|
612
|
+
if (!popup || popup.closed) {
|
|
613
|
+
clearInterval(pollTimer);
|
|
614
|
+
if (!callbackReceived) {
|
|
615
|
+
window.removeEventListener("message", handler);
|
|
616
|
+
this.modal?.hideLoading();
|
|
617
|
+
}
|
|
560
618
|
}
|
|
619
|
+
} catch {
|
|
620
|
+
}
|
|
621
|
+
}, 500);
|
|
622
|
+
const handler = async (e) => {
|
|
623
|
+
if (e.data?.type !== "authon-oauth-callback") return;
|
|
624
|
+
callbackReceived = true;
|
|
625
|
+
window.removeEventListener("message", handler);
|
|
626
|
+
clearInterval(pollTimer);
|
|
627
|
+
try {
|
|
628
|
+
const tokens = await this.apiPost("/v1/auth/oauth/callback", {
|
|
629
|
+
code: e.data.code,
|
|
630
|
+
state: e.data.state,
|
|
631
|
+
provider
|
|
632
|
+
});
|
|
633
|
+
this.session.setSession(tokens);
|
|
634
|
+
this.modal?.close();
|
|
635
|
+
this.emit("signedIn", tokens.user);
|
|
636
|
+
} catch (err) {
|
|
637
|
+
this.modal?.hideLoading();
|
|
638
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
561
639
|
}
|
|
562
640
|
};
|
|
563
641
|
window.addEventListener("message", handler);
|
|
564
642
|
} catch (err) {
|
|
643
|
+
this.modal?.hideLoading();
|
|
565
644
|
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
566
645
|
}
|
|
567
646
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -104,6 +104,25 @@ var ModalRenderer = class {
|
|
|
104
104
|
this.containerElement.innerHTML = "";
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
showLoading() {
|
|
108
|
+
if (!this.shadowRoot) return;
|
|
109
|
+
this.hideLoading();
|
|
110
|
+
const overlay = document.createElement("div");
|
|
111
|
+
overlay.id = "authon-loading-overlay";
|
|
112
|
+
overlay.innerHTML = `
|
|
113
|
+
<div class="loading-spinner">
|
|
114
|
+
<div class="loading-ring"></div>
|
|
115
|
+
<div class="loading-ring"></div>
|
|
116
|
+
<div class="loading-ring"></div>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="loading-text">Signing in<span class="loading-dots"><span></span><span></span><span></span></span></div>
|
|
119
|
+
`;
|
|
120
|
+
this.shadowRoot.querySelector(".modal-container")?.appendChild(overlay);
|
|
121
|
+
}
|
|
122
|
+
hideLoading() {
|
|
123
|
+
if (!this.shadowRoot) return;
|
|
124
|
+
this.shadowRoot.getElementById("authon-loading-overlay")?.remove();
|
|
125
|
+
}
|
|
107
126
|
render(view) {
|
|
108
127
|
const host = document.createElement("div");
|
|
109
128
|
host.setAttribute("data-authon-modal", "");
|
|
@@ -207,6 +226,7 @@ var ModalRenderer = class {
|
|
|
207
226
|
border-radius: var(--authon-radius);
|
|
208
227
|
padding: 32px;
|
|
209
228
|
width: 400px; max-width: 100%;
|
|
229
|
+
position: ${this.mode === "popup" ? "fixed" : "relative"};
|
|
210
230
|
${this.mode === "popup" ? `box-shadow: 0 25px 50px -12px rgba(0,0,0,${dark ? "0.5" : "0.25"}); animation: slideIn 0.3s ease;` : ""}
|
|
211
231
|
}
|
|
212
232
|
.logo { display: block; margin: 0 auto 16px; max-height: 48px; }
|
|
@@ -261,6 +281,39 @@ var ModalRenderer = class {
|
|
|
261
281
|
font-size: 11px; color: var(--authon-dim);
|
|
262
282
|
}
|
|
263
283
|
.secured-brand { font-weight: 600; color: var(--authon-muted); }
|
|
284
|
+
/* Loading overlay */
|
|
285
|
+
#authon-loading-overlay {
|
|
286
|
+
position: absolute; inset: 0; z-index: 10;
|
|
287
|
+
background: ${dark ? "rgba(15,23,42,0.92)" : "rgba(255,255,255,0.92)"};
|
|
288
|
+
backdrop-filter: blur(2px);
|
|
289
|
+
border-radius: var(--authon-radius);
|
|
290
|
+
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px;
|
|
291
|
+
animation: fadeIn 0.15s ease;
|
|
292
|
+
}
|
|
293
|
+
.loading-spinner { position: relative; width: 48px; height: 48px; }
|
|
294
|
+
.loading-ring {
|
|
295
|
+
position: absolute; inset: 0;
|
|
296
|
+
border: 2.5px solid transparent; border-top-color: var(--authon-primary-start);
|
|
297
|
+
border-radius: 50%; animation: spin 1s cubic-bezier(.55,.15,.45,.85) infinite;
|
|
298
|
+
}
|
|
299
|
+
.loading-ring:nth-child(2) {
|
|
300
|
+
inset: 5px; border-top-color: transparent; border-right-color: var(--authon-primary-end);
|
|
301
|
+
animation-duration: 1.2s; animation-direction: reverse; opacity: .7;
|
|
302
|
+
}
|
|
303
|
+
.loading-ring:nth-child(3) {
|
|
304
|
+
inset: 10px; border-top-color: transparent; border-bottom-color: var(--authon-primary-start);
|
|
305
|
+
animation-duration: .8s; opacity: .4;
|
|
306
|
+
}
|
|
307
|
+
.loading-text { font-size: 14px; font-weight: 500; color: var(--authon-muted); }
|
|
308
|
+
.loading-dots { display: inline-flex; gap: 2px; margin-left: 2px; }
|
|
309
|
+
.loading-dots span {
|
|
310
|
+
width: 3px; height: 3px; border-radius: 50%;
|
|
311
|
+
background: var(--authon-muted); animation: blink 1.4s infinite both;
|
|
312
|
+
}
|
|
313
|
+
.loading-dots span:nth-child(2) { animation-delay: .2s; }
|
|
314
|
+
.loading-dots span:nth-child(3) { animation-delay: .4s; }
|
|
315
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
316
|
+
@keyframes blink { 0%,80%,100% { opacity: .2; } 40% { opacity: 1; } }
|
|
264
317
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
265
318
|
@keyframes slideIn { from { opacity: 0; transform: translate(-50%, -48%); } to { opacity: 1; transform: translate(-50%, -50%); } }
|
|
266
319
|
${b.customCss || ""}
|
|
@@ -312,6 +365,7 @@ var ModalRenderer = class {
|
|
|
312
365
|
// src/session.ts
|
|
313
366
|
var SessionManager = class {
|
|
314
367
|
accessToken = null;
|
|
368
|
+
refreshToken = null;
|
|
315
369
|
user = null;
|
|
316
370
|
refreshTimer = null;
|
|
317
371
|
apiUrl;
|
|
@@ -328,11 +382,15 @@ var SessionManager = class {
|
|
|
328
382
|
}
|
|
329
383
|
setSession(tokens) {
|
|
330
384
|
this.accessToken = tokens.accessToken;
|
|
385
|
+
this.refreshToken = tokens.refreshToken;
|
|
331
386
|
this.user = tokens.user;
|
|
332
|
-
|
|
387
|
+
if (tokens.expiresIn && tokens.expiresIn > 0) {
|
|
388
|
+
this.scheduleRefresh(tokens.expiresIn);
|
|
389
|
+
}
|
|
333
390
|
}
|
|
334
391
|
clearSession() {
|
|
335
392
|
this.accessToken = null;
|
|
393
|
+
this.refreshToken = null;
|
|
336
394
|
this.user = null;
|
|
337
395
|
if (this.refreshTimer) {
|
|
338
396
|
clearTimeout(this.refreshTimer);
|
|
@@ -341,10 +399,14 @@ var SessionManager = class {
|
|
|
341
399
|
}
|
|
342
400
|
scheduleRefresh(expiresIn) {
|
|
343
401
|
if (this.refreshTimer) clearTimeout(this.refreshTimer);
|
|
344
|
-
const refreshIn = Math.max((expiresIn - 60) * 1e3,
|
|
402
|
+
const refreshIn = Math.max((expiresIn - 60) * 1e3, 3e4);
|
|
345
403
|
this.refreshTimer = setTimeout(() => this.refresh(), refreshIn);
|
|
346
404
|
}
|
|
347
405
|
async refresh() {
|
|
406
|
+
if (!this.refreshToken) {
|
|
407
|
+
this.clearSession();
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
348
410
|
try {
|
|
349
411
|
const res = await fetch(`${this.apiUrl}/v1/auth/token/refresh`, {
|
|
350
412
|
method: "POST",
|
|
@@ -352,7 +414,8 @@ var SessionManager = class {
|
|
|
352
414
|
"Content-Type": "application/json",
|
|
353
415
|
"x-api-key": this.publishableKey
|
|
354
416
|
},
|
|
355
|
-
credentials: "include"
|
|
417
|
+
credentials: "include",
|
|
418
|
+
body: JSON.stringify({ refreshToken: this.refreshToken })
|
|
356
419
|
});
|
|
357
420
|
if (!res.ok) {
|
|
358
421
|
this.clearSession();
|
|
@@ -505,6 +568,7 @@ var Authon = class {
|
|
|
505
568
|
const { url } = await this.apiGet(
|
|
506
569
|
`/v1/auth/oauth/${provider}/url?redirectUri=${encodeURIComponent(redirectUri)}`
|
|
507
570
|
);
|
|
571
|
+
this.modal?.showLoading();
|
|
508
572
|
const width = 500;
|
|
509
573
|
const height = 700;
|
|
510
574
|
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
@@ -514,27 +578,42 @@ var Authon = class {
|
|
|
514
578
|
"authon-oauth",
|
|
515
579
|
`width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`
|
|
516
580
|
);
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
});
|
|
528
|
-
this.session.setSession(tokens);
|
|
529
|
-
this.modal?.close();
|
|
530
|
-
this.emit("signedIn", tokens.user);
|
|
531
|
-
} catch (err) {
|
|
532
|
-
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
581
|
+
let callbackReceived = false;
|
|
582
|
+
const pollTimer = setInterval(() => {
|
|
583
|
+
if (callbackReceived) return;
|
|
584
|
+
try {
|
|
585
|
+
if (!popup || popup.closed) {
|
|
586
|
+
clearInterval(pollTimer);
|
|
587
|
+
if (!callbackReceived) {
|
|
588
|
+
window.removeEventListener("message", handler);
|
|
589
|
+
this.modal?.hideLoading();
|
|
590
|
+
}
|
|
533
591
|
}
|
|
592
|
+
} catch {
|
|
593
|
+
}
|
|
594
|
+
}, 500);
|
|
595
|
+
const handler = async (e) => {
|
|
596
|
+
if (e.data?.type !== "authon-oauth-callback") return;
|
|
597
|
+
callbackReceived = true;
|
|
598
|
+
window.removeEventListener("message", handler);
|
|
599
|
+
clearInterval(pollTimer);
|
|
600
|
+
try {
|
|
601
|
+
const tokens = await this.apiPost("/v1/auth/oauth/callback", {
|
|
602
|
+
code: e.data.code,
|
|
603
|
+
state: e.data.state,
|
|
604
|
+
provider
|
|
605
|
+
});
|
|
606
|
+
this.session.setSession(tokens);
|
|
607
|
+
this.modal?.close();
|
|
608
|
+
this.emit("signedIn", tokens.user);
|
|
609
|
+
} catch (err) {
|
|
610
|
+
this.modal?.hideLoading();
|
|
611
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
534
612
|
}
|
|
535
613
|
};
|
|
536
614
|
window.addEventListener("message", handler);
|
|
537
615
|
} catch (err) {
|
|
616
|
+
this.modal?.hideLoading();
|
|
538
617
|
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
539
618
|
}
|
|
540
619
|
}
|