@palbase/web 1.8.0 → 1.9.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.
@@ -1771,6 +1771,7 @@ declare class PalbeAuth {
1771
1771
  private signingOut;
1772
1772
  private signingIn;
1773
1773
  private signedInState;
1774
+ private hydratingUser;
1774
1775
  private readonly stateListeners;
1775
1776
  private readonly eventListeners;
1776
1777
  private readonly userListeners;
@@ -1788,12 +1789,24 @@ declare class PalbeAuth {
1788
1789
  signOut(): Promise<void>;
1789
1790
  getUser(): Promise<AuthUser>;
1790
1791
  refreshUser(): Promise<AuthUser>;
1792
+ /**
1793
+ * Restore the user after a session was rehydrated from storage (page reload).
1794
+ * Hydration in buildRuntime restores the TOKENS synchronously, but the access
1795
+ * token JWT does not carry emailVerified/createdAt, so the full AuthUser can't
1796
+ * be reconstructed offline — this fetches GET /auth/user once and announces
1797
+ * `signedIn`, so the app no longer has to `await pb.auth.refreshUser()` itself
1798
+ * on boot. Idempotent (runs once), browser-safe (no-op when not signed in or
1799
+ * a user is already cached), and never throws (a boot-time network failure
1800
+ * must not break app startup — isSignedIn stays true, the app can retry).
1801
+ */
1802
+ hydrateUser(): void;
1791
1803
  /**
1792
1804
  * Subscribe to signed-in/signed-out state. Fires immediately with the
1793
- * current snapshot (iOS parity). NOTE: a restored session (page reload) has
1794
- * no cached user yet, so the immediate snapshot reports signedOut even when
1795
- * `isSignedIn` is true call `refreshUser()` on boot to populate the user
1796
- * and rely on `isSignedIn` for the session truth.
1805
+ * current snapshot (iOS parity). A restored session (page reload) hydrates
1806
+ * the user asynchronously via `hydrateUser()` (fired once at boot), so the
1807
+ * FIRST snapshot may report signedOut for a tick even when `isSignedIn` is
1808
+ * true; the listener then fires again with `signedIn` once the user lands.
1809
+ * Rely on `isSignedIn` for the session truth if you need it synchronously.
1797
1810
  */
1798
1811
  onAuthStateChange(callback: (state: AuthState) => void): Unsubscribe;
1799
1812
  onAuthEvent(callback: (event: AuthChangeEvent) => void): Unsubscribe;
@@ -1771,6 +1771,7 @@ declare class PalbeAuth {
1771
1771
  private signingOut;
1772
1772
  private signingIn;
1773
1773
  private signedInState;
1774
+ private hydratingUser;
1774
1775
  private readonly stateListeners;
1775
1776
  private readonly eventListeners;
1776
1777
  private readonly userListeners;
@@ -1788,12 +1789,24 @@ declare class PalbeAuth {
1788
1789
  signOut(): Promise<void>;
1789
1790
  getUser(): Promise<AuthUser>;
1790
1791
  refreshUser(): Promise<AuthUser>;
1792
+ /**
1793
+ * Restore the user after a session was rehydrated from storage (page reload).
1794
+ * Hydration in buildRuntime restores the TOKENS synchronously, but the access
1795
+ * token JWT does not carry emailVerified/createdAt, so the full AuthUser can't
1796
+ * be reconstructed offline — this fetches GET /auth/user once and announces
1797
+ * `signedIn`, so the app no longer has to `await pb.auth.refreshUser()` itself
1798
+ * on boot. Idempotent (runs once), browser-safe (no-op when not signed in or
1799
+ * a user is already cached), and never throws (a boot-time network failure
1800
+ * must not break app startup — isSignedIn stays true, the app can retry).
1801
+ */
1802
+ hydrateUser(): void;
1791
1803
  /**
1792
1804
  * Subscribe to signed-in/signed-out state. Fires immediately with the
1793
- * current snapshot (iOS parity). NOTE: a restored session (page reload) has
1794
- * no cached user yet, so the immediate snapshot reports signedOut even when
1795
- * `isSignedIn` is true call `refreshUser()` on boot to populate the user
1796
- * and rely on `isSignedIn` for the session truth.
1805
+ * current snapshot (iOS parity). A restored session (page reload) hydrates
1806
+ * the user asynchronously via `hydrateUser()` (fired once at boot), so the
1807
+ * FIRST snapshot may report signedOut for a tick even when `isSignedIn` is
1808
+ * true; the listener then fires again with `signedIn` once the user lands.
1809
+ * Rely on `isSignedIn` for the session truth if you need it synchronously.
1797
1810
  */
1798
1811
  onAuthStateChange(callback: (state: AuthState) => void): Unsubscribe;
1799
1812
  onAuthEvent(callback: (event: AuthChangeEvent) => void): Unsubscribe;
@@ -1486,6 +1486,8 @@ var PalbeAuth = class {
1486
1486
  // suppresses AuthClient's TOKEN_REFRESHED during re-signIn
1487
1487
  signedInState = false;
1488
1488
  // dedupes AuthClient's repeated SIGNED_OUT events
1489
+ hydratingUser = false;
1490
+ // guards hydrateUser() to a single boot fetch
1489
1491
  stateListeners = /* @__PURE__ */ new Set();
1490
1492
  eventListeners = /* @__PURE__ */ new Set();
1491
1493
  userListeners = /* @__PURE__ */ new Set();
@@ -1538,13 +1540,37 @@ var PalbeAuth = class {
1538
1540
  if (changed) for (const cb of this.userListeners) this.safeInvoke(() => cb(user));
1539
1541
  return user;
1540
1542
  }
1543
+ /**
1544
+ * Restore the user after a session was rehydrated from storage (page reload).
1545
+ * Hydration in buildRuntime restores the TOKENS synchronously, but the access
1546
+ * token JWT does not carry emailVerified/createdAt, so the full AuthUser can't
1547
+ * be reconstructed offline — this fetches GET /auth/user once and announces
1548
+ * `signedIn`, so the app no longer has to `await pb.auth.refreshUser()` itself
1549
+ * on boot. Idempotent (runs once), browser-safe (no-op when not signed in or
1550
+ * a user is already cached), and never throws (a boot-time network failure
1551
+ * must not break app startup — isSignedIn stays true, the app can retry).
1552
+ */
1553
+ hydrateUser() {
1554
+ if (this.hydratingUser || this.cachedUser || !this.isSignedIn) return;
1555
+ this.hydratingUser = true;
1556
+ void this.refreshUser().then((user) => {
1557
+ if (this.isSignedIn) {
1558
+ this.signedInState = true;
1559
+ this.emitState({ status: "signedIn", user });
1560
+ }
1561
+ }).catch(() => {
1562
+ }).finally(() => {
1563
+ this.hydratingUser = false;
1564
+ });
1565
+ }
1541
1566
  // ── listeners ──────────────────────────────────────────
1542
1567
  /**
1543
1568
  * Subscribe to signed-in/signed-out state. Fires immediately with the
1544
- * current snapshot (iOS parity). NOTE: a restored session (page reload) has
1545
- * no cached user yet, so the immediate snapshot reports signedOut even when
1546
- * `isSignedIn` is true call `refreshUser()` on boot to populate the user
1547
- * and rely on `isSignedIn` for the session truth.
1569
+ * current snapshot (iOS parity). A restored session (page reload) hydrates
1570
+ * the user asynchronously via `hydrateUser()` (fired once at boot), so the
1571
+ * FIRST snapshot may report signedOut for a tick even when `isSignedIn` is
1572
+ * true; the listener then fires again with `signedIn` once the user lands.
1573
+ * Rely on `isSignedIn` for the session truth if you need it synchronously.
1548
1574
  */
1549
1575
  onAuthStateChange(callback) {
1550
1576
  this.stateListeners.add(callback);
@@ -8902,7 +8928,7 @@ function defaultSessionStorage(key) {
8902
8928
  }
8903
8929
 
8904
8930
  // src/version.ts
8905
- var VERSION = "1.8.0";
8931
+ var VERSION = "1.9.0";
8906
8932
 
8907
8933
  // src/runtime.ts
8908
8934
  function buildRuntime(config) {
@@ -9020,6 +9046,7 @@ function buildRuntime(config) {
9020
9046
  void rt.perf;
9021
9047
  if (typeof document !== "undefined") {
9022
9048
  void new PerfConfigClient().fetchConfig(rt, rt.perf);
9049
+ rt.auth.hydrateUser();
9023
9050
  }
9024
9051
  recordColdStart(rt);
9025
9052
  observeWebVitals((item) => rt.perf.record(item));
@@ -9315,4 +9342,4 @@ export {
9315
9342
  pb,
9316
9343
  createBoundClient
9317
9344
  };
9318
- //# sourceMappingURL=chunk-AWVNDAMG.js.map
9345
+ //# sourceMappingURL=chunk-I3ZMB7XM.js.map