@authon/js 0.3.4 → 0.4.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 +80 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +80 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -129,6 +129,7 @@ var ModalRenderer = class {
|
|
|
129
129
|
shadowRoot = null;
|
|
130
130
|
hostElement = null;
|
|
131
131
|
containerElement = null;
|
|
132
|
+
containerId = null;
|
|
132
133
|
mode;
|
|
133
134
|
theme;
|
|
134
135
|
branding;
|
|
@@ -171,9 +172,20 @@ var ModalRenderer = class {
|
|
|
171
172
|
this.onPasskeyClick = options.onPasskeyClick || (() => {
|
|
172
173
|
});
|
|
173
174
|
if (options.mode === "embedded" && options.containerId) {
|
|
174
|
-
this.
|
|
175
|
+
this.containerId = options.containerId;
|
|
175
176
|
}
|
|
176
177
|
}
|
|
178
|
+
resolveContainerElement() {
|
|
179
|
+
if (this.mode !== "embedded" || !this.containerId) return null;
|
|
180
|
+
const next = document.getElementById(this.containerId);
|
|
181
|
+
if (this.containerElement !== next) {
|
|
182
|
+
this.hostElement?.remove();
|
|
183
|
+
this.hostElement = null;
|
|
184
|
+
this.shadowRoot = null;
|
|
185
|
+
}
|
|
186
|
+
this.containerElement = next;
|
|
187
|
+
return next;
|
|
188
|
+
}
|
|
177
189
|
setProviders(providers) {
|
|
178
190
|
this.enabledProviders = providers;
|
|
179
191
|
}
|
|
@@ -181,6 +193,11 @@ var ModalRenderer = class {
|
|
|
181
193
|
this.branding = { ...DEFAULT_BRANDING, ...branding };
|
|
182
194
|
}
|
|
183
195
|
open(view = "signIn") {
|
|
196
|
+
this.resolveContainerElement();
|
|
197
|
+
if (this.hostElement && !this.hostElement.isConnected) {
|
|
198
|
+
this.hostElement = null;
|
|
199
|
+
this.shadowRoot = null;
|
|
200
|
+
}
|
|
184
201
|
if (this.shadowRoot && this.hostElement) {
|
|
185
202
|
this.hideOverlay();
|
|
186
203
|
this.switchView(view);
|
|
@@ -210,8 +227,9 @@ var ModalRenderer = class {
|
|
|
210
227
|
this.hostElement = null;
|
|
211
228
|
this.shadowRoot = null;
|
|
212
229
|
}
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
const liveContainer = this.resolveContainerElement();
|
|
231
|
+
if (liveContainer) {
|
|
232
|
+
liveContainer.replaceChildren();
|
|
215
233
|
}
|
|
216
234
|
this.currentOverlay = "none";
|
|
217
235
|
}
|
|
@@ -377,8 +395,14 @@ var ModalRenderer = class {
|
|
|
377
395
|
this.hostElement = host;
|
|
378
396
|
if (this.mode === "popup") {
|
|
379
397
|
document.body.appendChild(host);
|
|
380
|
-
} else
|
|
381
|
-
this.
|
|
398
|
+
} else {
|
|
399
|
+
const container = this.resolveContainerElement();
|
|
400
|
+
if (!container) {
|
|
401
|
+
this.hostElement = null;
|
|
402
|
+
throw new Error(`Authon container "#${this.containerId}" not found`);
|
|
403
|
+
}
|
|
404
|
+
container.replaceChildren();
|
|
405
|
+
container.appendChild(host);
|
|
382
406
|
}
|
|
383
407
|
this.shadowRoot = host.attachShadow({ mode: "open" });
|
|
384
408
|
this.shadowRoot.innerHTML = this.buildShell(view);
|
|
@@ -422,12 +446,10 @@ var ModalRenderer = class {
|
|
|
422
446
|
</button>`;
|
|
423
447
|
}).join("") : "";
|
|
424
448
|
const divider = showProviders && b.showDivider !== false && b.showEmailPassword !== false ? `<div class="divider"><span>or</span></div>` : "";
|
|
425
|
-
const captchaContainer = this.captchaSiteKey ? '<div id="turnstile-container" style="display:flex;justify-content:center;margin:4px 0"></div>' : "";
|
|
426
449
|
const emailForm = b.showEmailPassword !== false ? `<form class="email-form" id="email-form">
|
|
427
450
|
<input type="email" placeholder="Email address" name="email" required class="input" autocomplete="email" />
|
|
428
451
|
<input type="password" placeholder="Password" name="password" required class="input" autocomplete="${isSignUp ? "new-password" : "current-password"}" />
|
|
429
452
|
${isSignUp ? '<p class="password-hint">Must contain uppercase, lowercase, and a number (min 8 chars)</p>' : ""}
|
|
430
|
-
${captchaContainer}
|
|
431
453
|
<button type="submit" class="submit-btn">${isSignUp ? "Sign up" : "Sign in"}</button>
|
|
432
454
|
</form>` : "";
|
|
433
455
|
const hasMethodAbove = showProviders && this.enabledProviders.length > 0 || b.showEmailPassword !== false;
|
|
@@ -485,28 +507,13 @@ var ModalRenderer = class {
|
|
|
485
507
|
`;
|
|
486
508
|
}
|
|
487
509
|
renderTurnstile() {
|
|
488
|
-
if (!this.captchaSiteKey
|
|
489
|
-
const anchor = this.shadowRoot.getElementById("turnstile-container");
|
|
490
|
-
if (!anchor) return;
|
|
510
|
+
if (!this.captchaSiteKey) return;
|
|
491
511
|
const w = window;
|
|
492
|
-
const positionWrapper = () => {
|
|
493
|
-
if (!this.turnstileWrapper || !anchor.isConnected) return;
|
|
494
|
-
const rect = anchor.getBoundingClientRect();
|
|
495
|
-
Object.assign(this.turnstileWrapper.style, {
|
|
496
|
-
position: "fixed",
|
|
497
|
-
top: `${rect.top}px`,
|
|
498
|
-
left: `${rect.left}px`,
|
|
499
|
-
width: `${rect.width}px`,
|
|
500
|
-
zIndex: "2147483647",
|
|
501
|
-
display: "flex",
|
|
502
|
-
justifyContent: "center"
|
|
503
|
-
});
|
|
504
|
-
};
|
|
505
512
|
const tryRender = () => {
|
|
506
|
-
if (!w.turnstile
|
|
513
|
+
if (!w.turnstile) return;
|
|
507
514
|
this.turnstileWrapper = document.createElement("div");
|
|
515
|
+
this.turnstileWrapper.style.cssText = "position:fixed;bottom:10px;right:10px;z-index:2147483647;";
|
|
508
516
|
document.body.appendChild(this.turnstileWrapper);
|
|
509
|
-
positionWrapper();
|
|
510
517
|
this.turnstileWidgetId = w.turnstile.render(this.turnstileWrapper, {
|
|
511
518
|
sitekey: this.captchaSiteKey,
|
|
512
519
|
callback: (token) => {
|
|
@@ -519,10 +526,8 @@ var ModalRenderer = class {
|
|
|
519
526
|
this.turnstileToken = "";
|
|
520
527
|
},
|
|
521
528
|
theme: this.isDark() ? "dark" : "light",
|
|
522
|
-
|
|
529
|
+
appearance: "interaction-only"
|
|
523
530
|
});
|
|
524
|
-
window.addEventListener("scroll", positionWrapper, { passive: true });
|
|
525
|
-
window.addEventListener("resize", positionWrapper, { passive: true });
|
|
526
531
|
};
|
|
527
532
|
if (w.turnstile) {
|
|
528
533
|
tryRender();
|
|
@@ -1155,9 +1160,42 @@ var SessionManager = class {
|
|
|
1155
1160
|
refreshTimer = null;
|
|
1156
1161
|
apiUrl;
|
|
1157
1162
|
publishableKey;
|
|
1163
|
+
storageKey;
|
|
1158
1164
|
constructor(publishableKey, apiUrl) {
|
|
1159
1165
|
this.publishableKey = publishableKey;
|
|
1160
1166
|
this.apiUrl = apiUrl;
|
|
1167
|
+
this.storageKey = `authon_session_${publishableKey.slice(0, 16)}`;
|
|
1168
|
+
this.restoreFromStorage();
|
|
1169
|
+
}
|
|
1170
|
+
restoreFromStorage() {
|
|
1171
|
+
if (typeof window === "undefined") return;
|
|
1172
|
+
try {
|
|
1173
|
+
const stored = localStorage.getItem(this.storageKey);
|
|
1174
|
+
if (!stored) return;
|
|
1175
|
+
const data = JSON.parse(stored);
|
|
1176
|
+
if (data.accessToken && data.refreshToken && data.user) {
|
|
1177
|
+
this.accessToken = data.accessToken;
|
|
1178
|
+
this.refreshToken = data.refreshToken;
|
|
1179
|
+
this.user = data.user;
|
|
1180
|
+
this.scheduleRefresh(5);
|
|
1181
|
+
}
|
|
1182
|
+
} catch {
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
persistToStorage() {
|
|
1186
|
+
if (typeof window === "undefined") return;
|
|
1187
|
+
try {
|
|
1188
|
+
if (this.accessToken && this.refreshToken && this.user) {
|
|
1189
|
+
localStorage.setItem(this.storageKey, JSON.stringify({
|
|
1190
|
+
accessToken: this.accessToken,
|
|
1191
|
+
refreshToken: this.refreshToken,
|
|
1192
|
+
user: this.user
|
|
1193
|
+
}));
|
|
1194
|
+
} else {
|
|
1195
|
+
localStorage.removeItem(this.storageKey);
|
|
1196
|
+
}
|
|
1197
|
+
} catch {
|
|
1198
|
+
}
|
|
1161
1199
|
}
|
|
1162
1200
|
getToken() {
|
|
1163
1201
|
return this.accessToken;
|
|
@@ -1169,6 +1207,7 @@ var SessionManager = class {
|
|
|
1169
1207
|
this.accessToken = tokens.accessToken;
|
|
1170
1208
|
this.refreshToken = tokens.refreshToken;
|
|
1171
1209
|
this.user = tokens.user;
|
|
1210
|
+
this.persistToStorage();
|
|
1172
1211
|
if (tokens.expiresIn && tokens.expiresIn > 0) {
|
|
1173
1212
|
this.scheduleRefresh(tokens.expiresIn);
|
|
1174
1213
|
}
|
|
@@ -1180,6 +1219,7 @@ var SessionManager = class {
|
|
|
1180
1219
|
this.accessToken = null;
|
|
1181
1220
|
this.refreshToken = null;
|
|
1182
1221
|
this.user = null;
|
|
1222
|
+
this.persistToStorage();
|
|
1183
1223
|
if (this.refreshTimer) {
|
|
1184
1224
|
clearTimeout(this.refreshTimer);
|
|
1185
1225
|
this.refreshTimer = null;
|
|
@@ -1975,6 +2015,18 @@ var Authon = class {
|
|
|
1975
2015
|
await this.apiPostAuth(`/v1/auth/organizations/${orgId}/leave`, void 0, token);
|
|
1976
2016
|
}
|
|
1977
2017
|
};
|
|
2018
|
+
/** Testing utilities — only available when initialized with a pk_test_ key */
|
|
2019
|
+
get testing() {
|
|
2020
|
+
if (!this.publishableKey.startsWith("pk_test_")) return void 0;
|
|
2021
|
+
return {
|
|
2022
|
+
signIn: async (params) => {
|
|
2023
|
+
const res = await this.apiPost("/v1/auth/testing/token", params);
|
|
2024
|
+
this.session.setSession(res);
|
|
2025
|
+
this.emit("signedIn", res.user);
|
|
2026
|
+
return res.user;
|
|
2027
|
+
}
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
1978
2030
|
destroy() {
|
|
1979
2031
|
this.modal?.close();
|
|
1980
2032
|
this.session.destroy();
|