@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.
@@ -4449,7 +4449,8 @@ async function completeLoginFromRedirect() {
4449
4449
  }
4450
4450
  }
4451
4451
  /** Popup variant: open the hosted login in a popup; resolves with the User once the popup's
4452
- * redirect_uri page posts the code back. The redirect_uri page must call completeLoginInPopup(). */
4452
+ * redirect_uri page posts the code back. The redirect_uri page just calls the usual
4453
+ * completeLoginFromRedirect() (which auto-detects the popup) — no separate call needed. */
4453
4454
  async function loginWithPopup(opts) {
4454
4455
  if (!hasDOM())
4455
4456
  throw new Error('loginWithPopup is web-only — on React Native use loginWithRedirect()');
@@ -4465,13 +4466,16 @@ async function loginWithPopup(opts) {
4465
4466
  // not opts.redirectUri which may be undefined.
4466
4467
  const expectedOrigin = new URL(pkce.redirectUri).origin;
4467
4468
  return await new Promise((resolve, reject) => {
4469
+ let settled = false;
4470
+ let timer;
4471
+ const cleanup = () => { settled = true; clearInterval(timer); window.removeEventListener('message', onMsg); };
4468
4472
  const onMsg = async (ev) => {
4469
4473
  if (ev.origin !== expectedOrigin)
4470
4474
  return; // only trust the redirect_uri origin
4471
4475
  const d = ev.data;
4472
4476
  if (!d || d.type !== 'bounded-oidc-code' || typeof d.code !== 'string')
4473
4477
  return;
4474
- window.removeEventListener('message', onMsg);
4478
+ cleanup();
4475
4479
  try {
4476
4480
  const raw = sessionStorage.getItem(PKCE_STORE_KEY);
4477
4481
  if (!raw)
@@ -4492,11 +4496,17 @@ async function loginWithPopup(opts) {
4492
4496
  }
4493
4497
  };
4494
4498
  window.addEventListener('message', onMsg);
4495
- const timer = setInterval(() => {
4499
+ // The popup posts its code and then closes ITSELF, so a naive "popup.closed -> reject"
4500
+ // races the just-posted message and would report a spurious "Login window closed" on a
4501
+ // SUCCESSFUL login. When we see it closed, wait a beat for that pending message to settle
4502
+ // before declaring the window closed.
4503
+ timer = setInterval(() => {
4496
4504
  if (popup.closed) {
4497
4505
  clearInterval(timer);
4498
- window.removeEventListener('message', onMsg);
4499
- reject(new Error('Login window closed'));
4506
+ setTimeout(() => { if (!settled) {
4507
+ cleanup();
4508
+ reject(new Error('Login window closed'));
4509
+ } }, 500);
4500
4510
  }
4501
4511
  }, 500);
4502
4512
  });