@authon/js 0.3.5 → 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 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.containerElement = document.getElementById(options.containerId);
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
- if (this.containerElement) {
214
- this.containerElement.innerHTML = "";
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 if (this.containerElement) {
381
- this.containerElement.appendChild(host);
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);
@@ -1136,9 +1160,42 @@ var SessionManager = class {
1136
1160
  refreshTimer = null;
1137
1161
  apiUrl;
1138
1162
  publishableKey;
1163
+ storageKey;
1139
1164
  constructor(publishableKey, apiUrl) {
1140
1165
  this.publishableKey = publishableKey;
1141
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
+ }
1142
1199
  }
1143
1200
  getToken() {
1144
1201
  return this.accessToken;
@@ -1150,6 +1207,7 @@ var SessionManager = class {
1150
1207
  this.accessToken = tokens.accessToken;
1151
1208
  this.refreshToken = tokens.refreshToken;
1152
1209
  this.user = tokens.user;
1210
+ this.persistToStorage();
1153
1211
  if (tokens.expiresIn && tokens.expiresIn > 0) {
1154
1212
  this.scheduleRefresh(tokens.expiresIn);
1155
1213
  }
@@ -1161,6 +1219,7 @@ var SessionManager = class {
1161
1219
  this.accessToken = null;
1162
1220
  this.refreshToken = null;
1163
1221
  this.user = null;
1222
+ this.persistToStorage();
1164
1223
  if (this.refreshTimer) {
1165
1224
  clearTimeout(this.refreshTimer);
1166
1225
  this.refreshTimer = null;
@@ -1956,6 +2015,18 @@ var Authon = class {
1956
2015
  await this.apiPostAuth(`/v1/auth/organizations/${orgId}/leave`, void 0, token);
1957
2016
  }
1958
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
+ }
1959
2030
  destroy() {
1960
2031
  this.modal?.close();
1961
2032
  this.session.destroy();