@bounded-sh/client 0.0.30 → 0.0.31

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.
@@ -4429,7 +4429,8 @@ async function completeLoginFromRedirect() {
4429
4429
  }
4430
4430
  }
4431
4431
  /** Popup variant: open the hosted login in a popup; resolves with the User once the popup's
4432
- * redirect_uri page posts the code back. The redirect_uri page must call completeLoginInPopup(). */
4432
+ * redirect_uri page posts the code back. The redirect_uri page just calls the usual
4433
+ * completeLoginFromRedirect() (which auto-detects the popup) — no separate call needed. */
4433
4434
  async function loginWithPopup(opts) {
4434
4435
  if (!hasDOM())
4435
4436
  throw new Error('loginWithPopup is web-only — on React Native use loginWithRedirect()');
@@ -4445,13 +4446,16 @@ async function loginWithPopup(opts) {
4445
4446
  // not opts.redirectUri which may be undefined.
4446
4447
  const expectedOrigin = new URL(pkce.redirectUri).origin;
4447
4448
  return await new Promise((resolve, reject) => {
4449
+ let settled = false;
4450
+ let timer;
4451
+ const cleanup = () => { settled = true; clearInterval(timer); window.removeEventListener('message', onMsg); };
4448
4452
  const onMsg = async (ev) => {
4449
4453
  if (ev.origin !== expectedOrigin)
4450
4454
  return; // only trust the redirect_uri origin
4451
4455
  const d = ev.data;
4452
4456
  if (!d || d.type !== 'bounded-oidc-code' || typeof d.code !== 'string')
4453
4457
  return;
4454
- window.removeEventListener('message', onMsg);
4458
+ cleanup();
4455
4459
  try {
4456
4460
  const raw = sessionStorage.getItem(PKCE_STORE_KEY);
4457
4461
  if (!raw)
@@ -4472,11 +4476,17 @@ async function loginWithPopup(opts) {
4472
4476
  }
4473
4477
  };
4474
4478
  window.addEventListener('message', onMsg);
4475
- const timer = setInterval(() => {
4479
+ // The popup posts its code and then closes ITSELF, so a naive "popup.closed -> reject"
4480
+ // races the just-posted message and would report a spurious "Login window closed" on a
4481
+ // SUCCESSFUL login. When we see it closed, wait a beat for that pending message to settle
4482
+ // before declaring the window closed.
4483
+ timer = setInterval(() => {
4476
4484
  if (popup.closed) {
4477
4485
  clearInterval(timer);
4478
- window.removeEventListener('message', onMsg);
4479
- reject(new Error('Login window closed'));
4486
+ setTimeout(() => { if (!settled) {
4487
+ cleanup();
4488
+ reject(new Error('Login window closed'));
4489
+ } }, 500);
4480
4490
  }
4481
4491
  }, 500);
4482
4492
  });