@authon/js 0.3.5 → 0.4.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/dist/index.cjs +145 -5
- 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 +145 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -110,6 +110,13 @@ declare class Authon {
|
|
|
110
110
|
updateMemberRole: (orgId: string, memberId: string, role: string) => Promise<OrganizationMember>;
|
|
111
111
|
leave: (orgId: string) => Promise<void>;
|
|
112
112
|
};
|
|
113
|
+
/** Testing utilities — only available when initialized with a pk_test_ key */
|
|
114
|
+
get testing(): {
|
|
115
|
+
signIn(params: {
|
|
116
|
+
email: string;
|
|
117
|
+
nickname?: string;
|
|
118
|
+
}): Promise<AuthonUser>;
|
|
119
|
+
} | undefined;
|
|
113
120
|
destroy(): void;
|
|
114
121
|
private loadTurnstileScript;
|
|
115
122
|
private emit;
|
package/dist/index.d.ts
CHANGED
|
@@ -110,6 +110,13 @@ declare class Authon {
|
|
|
110
110
|
updateMemberRole: (orgId: string, memberId: string, role: string) => Promise<OrganizationMember>;
|
|
111
111
|
leave: (orgId: string) => Promise<void>;
|
|
112
112
|
};
|
|
113
|
+
/** Testing utilities — only available when initialized with a pk_test_ key */
|
|
114
|
+
get testing(): {
|
|
115
|
+
signIn(params: {
|
|
116
|
+
email: string;
|
|
117
|
+
nickname?: string;
|
|
118
|
+
}): Promise<AuthonUser>;
|
|
119
|
+
} | undefined;
|
|
113
120
|
destroy(): void;
|
|
114
121
|
private loadTurnstileScript;
|
|
115
122
|
private emit;
|
package/dist/index.js
CHANGED
|
@@ -100,6 +100,7 @@ var ModalRenderer = class {
|
|
|
100
100
|
shadowRoot = null;
|
|
101
101
|
hostElement = null;
|
|
102
102
|
containerElement = null;
|
|
103
|
+
containerId = null;
|
|
103
104
|
mode;
|
|
104
105
|
theme;
|
|
105
106
|
branding;
|
|
@@ -125,11 +126,16 @@ var ModalRenderer = class {
|
|
|
125
126
|
turnstileWidgetId = null;
|
|
126
127
|
turnstileToken = "";
|
|
127
128
|
turnstileWrapper = null;
|
|
129
|
+
// Dev Teleport (test mode)
|
|
130
|
+
isTestMode = false;
|
|
131
|
+
onDevTeleport = null;
|
|
128
132
|
constructor(options) {
|
|
129
133
|
this.mode = options.mode;
|
|
130
134
|
this.theme = options.theme || "auto";
|
|
131
135
|
this.branding = { ...DEFAULT_BRANDING, ...options.branding };
|
|
132
136
|
this.captchaSiteKey = options.captchaSiteKey || "";
|
|
137
|
+
this.isTestMode = options.isTestMode || false;
|
|
138
|
+
this.onDevTeleport = options.onDevTeleport || null;
|
|
133
139
|
this.onProviderClick = options.onProviderClick;
|
|
134
140
|
this.onEmailSubmit = options.onEmailSubmit;
|
|
135
141
|
this.onClose = options.onClose;
|
|
@@ -142,9 +148,20 @@ var ModalRenderer = class {
|
|
|
142
148
|
this.onPasskeyClick = options.onPasskeyClick || (() => {
|
|
143
149
|
});
|
|
144
150
|
if (options.mode === "embedded" && options.containerId) {
|
|
145
|
-
this.
|
|
151
|
+
this.containerId = options.containerId;
|
|
146
152
|
}
|
|
147
153
|
}
|
|
154
|
+
resolveContainerElement() {
|
|
155
|
+
if (this.mode !== "embedded" || !this.containerId) return null;
|
|
156
|
+
const next = document.getElementById(this.containerId);
|
|
157
|
+
if (this.containerElement !== next) {
|
|
158
|
+
this.hostElement?.remove();
|
|
159
|
+
this.hostElement = null;
|
|
160
|
+
this.shadowRoot = null;
|
|
161
|
+
}
|
|
162
|
+
this.containerElement = next;
|
|
163
|
+
return next;
|
|
164
|
+
}
|
|
148
165
|
setProviders(providers) {
|
|
149
166
|
this.enabledProviders = providers;
|
|
150
167
|
}
|
|
@@ -152,6 +169,11 @@ var ModalRenderer = class {
|
|
|
152
169
|
this.branding = { ...DEFAULT_BRANDING, ...branding };
|
|
153
170
|
}
|
|
154
171
|
open(view = "signIn") {
|
|
172
|
+
this.resolveContainerElement();
|
|
173
|
+
if (this.hostElement && !this.hostElement.isConnected) {
|
|
174
|
+
this.hostElement = null;
|
|
175
|
+
this.shadowRoot = null;
|
|
176
|
+
}
|
|
155
177
|
if (this.shadowRoot && this.hostElement) {
|
|
156
178
|
this.hideOverlay();
|
|
157
179
|
this.switchView(view);
|
|
@@ -181,8 +203,9 @@ var ModalRenderer = class {
|
|
|
181
203
|
this.hostElement = null;
|
|
182
204
|
this.shadowRoot = null;
|
|
183
205
|
}
|
|
184
|
-
|
|
185
|
-
|
|
206
|
+
const liveContainer = this.resolveContainerElement();
|
|
207
|
+
if (liveContainer) {
|
|
208
|
+
liveContainer.replaceChildren();
|
|
186
209
|
}
|
|
187
210
|
this.currentOverlay = "none";
|
|
188
211
|
}
|
|
@@ -348,8 +371,14 @@ var ModalRenderer = class {
|
|
|
348
371
|
this.hostElement = host;
|
|
349
372
|
if (this.mode === "popup") {
|
|
350
373
|
document.body.appendChild(host);
|
|
351
|
-
} else
|
|
352
|
-
this.
|
|
374
|
+
} else {
|
|
375
|
+
const container = this.resolveContainerElement();
|
|
376
|
+
if (!container) {
|
|
377
|
+
this.hostElement = null;
|
|
378
|
+
throw new Error(`Authon container "#${this.containerId}" not found`);
|
|
379
|
+
}
|
|
380
|
+
container.replaceChildren();
|
|
381
|
+
container.appendChild(host);
|
|
353
382
|
}
|
|
354
383
|
this.shadowRoot = host.attachShadow({ mode: "open" });
|
|
355
384
|
this.shadowRoot.innerHTML = this.buildShell(view);
|
|
@@ -450,6 +479,16 @@ var ModalRenderer = class {
|
|
|
450
479
|
${authMethods}
|
|
451
480
|
<p class="switch-view">${subtitle} <a href="#" id="switch-link">${subtitleLink}</a></p>
|
|
452
481
|
${footer}
|
|
482
|
+
${this.isTestMode ? `<div class="dev-teleport">
|
|
483
|
+
<div class="dev-teleport-label">
|
|
484
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
|
|
485
|
+
Dev Teleport
|
|
486
|
+
</div>
|
|
487
|
+
<div class="dev-teleport-row">
|
|
488
|
+
<input type="email" placeholder="test@example.com" id="dev-teleport-email" class="dev-teleport-input" value="dev@test.com" />
|
|
489
|
+
<button type="button" id="dev-teleport-btn" class="dev-teleport-btn">Go</button>
|
|
490
|
+
</div>
|
|
491
|
+
</div>` : ""}
|
|
453
492
|
${b.showSecuredBy !== false ? `<div class="secured-by">Secured by <a href="https://authon.dev" target="_blank" rel="noopener noreferrer" class="secured-link">Authon</a></div>` : ""}
|
|
454
493
|
`;
|
|
455
494
|
}
|
|
@@ -626,6 +665,34 @@ var ModalRenderer = class {
|
|
|
626
665
|
.secured-link { font-weight: 600; color: var(--authon-muted); text-decoration: none; }
|
|
627
666
|
.secured-link:hover { text-decoration: underline; }
|
|
628
667
|
|
|
668
|
+
/* Dev Teleport */
|
|
669
|
+
.dev-teleport {
|
|
670
|
+
margin-top: 12px; padding: 10px;
|
|
671
|
+
border-radius: calc(var(--authon-radius) * 0.5);
|
|
672
|
+
background: rgba(251,191,36,0.06);
|
|
673
|
+
border: 1px dashed rgba(251,191,36,0.25);
|
|
674
|
+
}
|
|
675
|
+
.dev-teleport-label {
|
|
676
|
+
display: flex; align-items: center; gap: 4px;
|
|
677
|
+
font-size: 10px; font-weight: 600; color: #fbbf24;
|
|
678
|
+
margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.05em;
|
|
679
|
+
}
|
|
680
|
+
.dev-teleport-row { display: flex; gap: 6px; }
|
|
681
|
+
.dev-teleport-input {
|
|
682
|
+
flex: 1; padding: 6px 10px; font-size: 12px;
|
|
683
|
+
border-radius: calc(var(--authon-radius) * 0.4);
|
|
684
|
+
background: rgba(0,0,0,0.2); border: 1px solid rgba(251,191,36,0.2);
|
|
685
|
+
color: #fbbf24; outline: none; font-family: ui-monospace, monospace;
|
|
686
|
+
}
|
|
687
|
+
.dev-teleport-input:focus { border-color: rgba(251,191,36,0.5); }
|
|
688
|
+
.dev-teleport-btn {
|
|
689
|
+
padding: 6px 14px; font-size: 11px; font-weight: 700;
|
|
690
|
+
border-radius: calc(var(--authon-radius) * 0.4);
|
|
691
|
+
background: rgba(251,191,36,0.15); border: 1px solid rgba(251,191,36,0.3);
|
|
692
|
+
color: #fbbf24; cursor: pointer;
|
|
693
|
+
}
|
|
694
|
+
.dev-teleport-btn:hover { background: rgba(251,191,36,0.25); }
|
|
695
|
+
|
|
629
696
|
/* Auth method buttons */
|
|
630
697
|
.auth-methods { display: flex; flex-direction: column; gap: 8px; }
|
|
631
698
|
.auth-method-btn {
|
|
@@ -1071,6 +1138,21 @@ var ModalRenderer = class {
|
|
|
1071
1138
|
});
|
|
1072
1139
|
}
|
|
1073
1140
|
this.renderTurnstile();
|
|
1141
|
+
const devTeleportBtn = this.shadowRoot.getElementById("dev-teleport-btn");
|
|
1142
|
+
const devTeleportEmail = this.shadowRoot.getElementById("dev-teleport-email");
|
|
1143
|
+
if (devTeleportBtn && devTeleportEmail && this.onDevTeleport) {
|
|
1144
|
+
const handler = this.onDevTeleport;
|
|
1145
|
+
devTeleportBtn.addEventListener("click", () => {
|
|
1146
|
+
const email = devTeleportEmail.value.trim();
|
|
1147
|
+
if (email) handler(email);
|
|
1148
|
+
});
|
|
1149
|
+
devTeleportEmail.addEventListener("keydown", (e) => {
|
|
1150
|
+
if (e.key === "Enter") {
|
|
1151
|
+
const email = devTeleportEmail.value.trim();
|
|
1152
|
+
if (email) handler(email);
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1074
1156
|
const backBtn = this.shadowRoot.getElementById("back-btn");
|
|
1075
1157
|
if (backBtn) {
|
|
1076
1158
|
backBtn.addEventListener("click", () => {
|
|
@@ -1107,9 +1189,42 @@ var SessionManager = class {
|
|
|
1107
1189
|
refreshTimer = null;
|
|
1108
1190
|
apiUrl;
|
|
1109
1191
|
publishableKey;
|
|
1192
|
+
storageKey;
|
|
1110
1193
|
constructor(publishableKey, apiUrl) {
|
|
1111
1194
|
this.publishableKey = publishableKey;
|
|
1112
1195
|
this.apiUrl = apiUrl;
|
|
1196
|
+
this.storageKey = `authon_session_${publishableKey.slice(0, 16)}`;
|
|
1197
|
+
this.restoreFromStorage();
|
|
1198
|
+
}
|
|
1199
|
+
restoreFromStorage() {
|
|
1200
|
+
if (typeof window === "undefined") return;
|
|
1201
|
+
try {
|
|
1202
|
+
const stored = localStorage.getItem(this.storageKey);
|
|
1203
|
+
if (!stored) return;
|
|
1204
|
+
const data = JSON.parse(stored);
|
|
1205
|
+
if (data.accessToken && data.refreshToken && data.user) {
|
|
1206
|
+
this.accessToken = data.accessToken;
|
|
1207
|
+
this.refreshToken = data.refreshToken;
|
|
1208
|
+
this.user = data.user;
|
|
1209
|
+
this.scheduleRefresh(5);
|
|
1210
|
+
}
|
|
1211
|
+
} catch {
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
persistToStorage() {
|
|
1215
|
+
if (typeof window === "undefined") return;
|
|
1216
|
+
try {
|
|
1217
|
+
if (this.accessToken && this.refreshToken && this.user) {
|
|
1218
|
+
localStorage.setItem(this.storageKey, JSON.stringify({
|
|
1219
|
+
accessToken: this.accessToken,
|
|
1220
|
+
refreshToken: this.refreshToken,
|
|
1221
|
+
user: this.user
|
|
1222
|
+
}));
|
|
1223
|
+
} else {
|
|
1224
|
+
localStorage.removeItem(this.storageKey);
|
|
1225
|
+
}
|
|
1226
|
+
} catch {
|
|
1227
|
+
}
|
|
1113
1228
|
}
|
|
1114
1229
|
getToken() {
|
|
1115
1230
|
return this.accessToken;
|
|
@@ -1121,6 +1236,7 @@ var SessionManager = class {
|
|
|
1121
1236
|
this.accessToken = tokens.accessToken;
|
|
1122
1237
|
this.refreshToken = tokens.refreshToken;
|
|
1123
1238
|
this.user = tokens.user;
|
|
1239
|
+
this.persistToStorage();
|
|
1124
1240
|
if (tokens.expiresIn && tokens.expiresIn > 0) {
|
|
1125
1241
|
this.scheduleRefresh(tokens.expiresIn);
|
|
1126
1242
|
}
|
|
@@ -1132,6 +1248,7 @@ var SessionManager = class {
|
|
|
1132
1248
|
this.accessToken = null;
|
|
1133
1249
|
this.refreshToken = null;
|
|
1134
1250
|
this.user = null;
|
|
1251
|
+
this.persistToStorage();
|
|
1135
1252
|
if (this.refreshTimer) {
|
|
1136
1253
|
clearTimeout(this.refreshTimer);
|
|
1137
1254
|
this.refreshTimer = null;
|
|
@@ -1927,6 +2044,18 @@ var Authon = class {
|
|
|
1927
2044
|
await this.apiPostAuth(`/v1/auth/organizations/${orgId}/leave`, void 0, token);
|
|
1928
2045
|
}
|
|
1929
2046
|
};
|
|
2047
|
+
/** Testing utilities — only available when initialized with a pk_test_ key */
|
|
2048
|
+
get testing() {
|
|
2049
|
+
if (!this.publishableKey.startsWith("pk_test_")) return void 0;
|
|
2050
|
+
return {
|
|
2051
|
+
signIn: async (params) => {
|
|
2052
|
+
const res = await this.apiPost("/v1/auth/testing/token", params);
|
|
2053
|
+
this.session.setSession(res);
|
|
2054
|
+
this.emit("signedIn", res.user);
|
|
2055
|
+
return res.user;
|
|
2056
|
+
}
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
1930
2059
|
destroy() {
|
|
1931
2060
|
this.modal?.close();
|
|
1932
2061
|
this.session.destroy();
|
|
@@ -1978,6 +2107,17 @@ var Authon = class {
|
|
|
1978
2107
|
containerId: this.config.containerId,
|
|
1979
2108
|
branding: this.branding || void 0,
|
|
1980
2109
|
captchaSiteKey: this.captchaEnabled ? this.turnstileSiteKey : void 0,
|
|
2110
|
+
isTestMode: this.publishableKey.startsWith("pk_test_"),
|
|
2111
|
+
onDevTeleport: this.publishableKey.startsWith("pk_test_") ? async (email) => {
|
|
2112
|
+
this.modal?.clearError();
|
|
2113
|
+
try {
|
|
2114
|
+
await this.testing.signIn({ email });
|
|
2115
|
+
this.modal?.close();
|
|
2116
|
+
} catch (err) {
|
|
2117
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2118
|
+
this.modal?.showError(msg || "Dev teleport failed");
|
|
2119
|
+
}
|
|
2120
|
+
} : void 0,
|
|
1981
2121
|
onProviderClick: (provider) => this.startOAuthFlow(provider),
|
|
1982
2122
|
onEmailSubmit: (email, password, isSignUp) => {
|
|
1983
2123
|
this.modal?.clearError();
|