@palbase/web 1.8.0 → 1.10.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.
Files changed (42) hide show
  1. package/dist/{analytics-facade-DfJ420F5.d.cts → analytics-facade-B7vujhPJ.d.cts} +18 -5
  2. package/dist/{analytics-facade-CgURkjpP.d.ts → analytics-facade-CHh5EGC2.d.ts} +18 -5
  3. package/dist/{chunk-AWVNDAMG.js → chunk-4ZJHHXD3.js} +36 -11
  4. package/dist/chunk-4ZJHHXD3.js.map +1 -0
  5. package/dist/chunk-PZ5AY32C.js +10 -0
  6. package/dist/chunk-PZ5AY32C.js.map +1 -0
  7. package/dist/gen/cli.cjs +1220 -0
  8. package/dist/gen/cli.cjs.map +1 -0
  9. package/dist/gen/cli.d.cts +1 -0
  10. package/dist/gen/cli.d.ts +1 -0
  11. package/dist/gen/cli.js +1198 -0
  12. package/dist/gen/cli.js.map +1 -0
  13. package/dist/index.cjs +31 -5
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +3 -3
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +2 -1
  18. package/dist/internal.cjs +32 -5
  19. package/dist/internal.cjs.map +1 -1
  20. package/dist/internal.d.cts +3 -3
  21. package/dist/internal.d.ts +3 -3
  22. package/dist/internal.js +2 -1
  23. package/dist/next/client.cjs +32 -5
  24. package/dist/next/client.cjs.map +1 -1
  25. package/dist/next/client.js +2 -1
  26. package/dist/next/client.js.map +1 -1
  27. package/dist/next/index.cjs +32 -5
  28. package/dist/next/index.cjs.map +1 -1
  29. package/dist/next/index.d.cts +2 -2
  30. package/dist/next/index.d.ts +2 -2
  31. package/dist/next/index.js +2 -1
  32. package/dist/next/index.js.map +1 -1
  33. package/dist/{pb-BwQwp411.d.cts → pb-6965XULp.d.cts} +1 -1
  34. package/dist/{pb-C1v9ErPy.d.ts → pb-ChNq987M.d.ts} +1 -1
  35. package/dist/react/index.cjs +1 -1
  36. package/dist/react/index.cjs.map +1 -1
  37. package/dist/react/index.d.cts +1 -1
  38. package/dist/react/index.d.ts +1 -1
  39. package/dist/react/index.js +2 -1
  40. package/dist/react/index.js.map +1 -1
  41. package/package.json +6 -2
  42. package/dist/chunk-AWVNDAMG.js.map +0 -1
@@ -7,7 +7,8 @@ import {
7
7
  __configure,
8
8
  endpointRefFromApiKey,
9
9
  getRuntime
10
- } from "../chunk-AWVNDAMG.js";
10
+ } from "../chunk-4ZJHHXD3.js";
11
+ import "../chunk-PZ5AY32C.js";
11
12
 
12
13
  // src/next/client.ts
13
14
  var SESSION_MAX_AGE_S = 2592e3;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/client.ts"],"sourcesContent":["/**\n * '@palbase/web/next/client' — the browser half of the Next.js adapter. This entry\n * must NEVER import 'next' (it runs in plain client bundles); the cookie jar\n * is document.cookie itself, written with the shared codec so the server\n * side (pbServer / middleware / callback) reads the same bytes.\n */\nimport { __configure, getRuntime } from '../internal.js';\nimport type { PersistedSession, SessionStorageAdapter } from '../storage.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookies,\n endpointRefFromApiKey,\n} from './cookie-codec.js';\n\n/** 30 days — the refresh-token TTL (P3 design contract). */\nconst SESSION_MAX_AGE_S = 2_592_000;\n\n// Secure is unconditional, INCLUDING http://localhost: browsers treat\n// localhost as a potentially-trustworthy origin, so document.cookie accepts\n// Secure cookies there — no dev-mode special case needed. KNOWN LIMITATION:\n// plain-http origins OTHER than localhost — e.g. LAN-IP device testing on\n// http://192.168.x.x — are NOT trustworthy, so the browser silently DROPS\n// these Secure cookie writes and the session won't persist; use https (or a\n// localhost tunnel/port-forward) for on-device testing. NOT HttpOnly by\n// design: the browser SDK must read/write the session (Supabase-paradigm\n// tradeoff, documented in the P3 plan).\nconst WRITE_ATTRS = 'Path=/; SameSite=Lax; Secure';\n\n/** Parse document.cookie (\"a=1; b=2\") into a name → raw-value map. */\nfunction cookieJar(): Map<string, string> {\n const jar = new Map<string, string>();\n for (const part of document.cookie.split(';')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const name = part.slice(0, eq).trim();\n if (name) jar.set(name, part.slice(eq + 1).trim());\n }\n return jar;\n}\n\nfunction deleteCookie(name: string): void {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=; ${WRITE_ATTRS}; Max-Age=0`;\n}\n\n/**\n * document.cookie-backed SessionStorageAdapter. `load` returns the EXTENDED\n * PersistedSession (access token + expiry ride along) so hydration adopts\n * the full session without a refresh round-trip.\n */\nexport function cookieSessionStorage(endpointRef: string): SessionStorageAdapter {\n return {\n load(): PersistedSession | null {\n if (typeof document === 'undefined') return null;\n const jar = cookieJar();\n const stored = decodeSessionCookies((name) => jar.get(name), endpointRef);\n if (!stored) return null;\n // A refresh-only save round-trips as a:'' / e:0 — normalize back to\n // the legacy shape so hydration takes the expired-trick path cleanly.\n return stored.accessToken && stored.expiresAt > 0\n ? {\n refreshToken: stored.refreshToken,\n accessToken: stored.accessToken,\n expiresAt: stored.expiresAt,\n }\n : { refreshToken: stored.refreshToken };\n },\n save(session: PersistedSession): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n // Delete every currently-present session cookie first (stale chunks of\n // a previously-larger session, or a stale base when the new write\n // chunks), then set the new cookie(s).\n for (const name of clearedSessionCookieNames(endpointRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n const { set, clear } = encodeSessionCookies(endpointRef, {\n accessToken: session.accessToken ?? '',\n refreshToken: session.refreshToken,\n expiresAt: session.expiresAt ?? 0,\n });\n for (const { name, value } of set) {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=${value}; ${WRITE_ATTRS}; Max-Age=${SESSION_MAX_AGE_S}`;\n }\n // Overflow guard (codec contract): delete one-past-the-end so a stale\n // orphan chunk behind a gap can never join a future chunk run.\n for (const name of clear) deleteCookie(name);\n },\n clear(): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n for (const name of clearedSessionCookieNames(endpointRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n },\n };\n}\n\n/**\n * One-liner for a client component/provider: re-configure the already-loaded\n * gen config (palbe.gen.ts must be imported first — throws the guided\n * notConfigured error otherwise) with cookie-backed session storage so the\n * browser and the server share the session. Calling it again simply\n * re-configures (safe, e.g. under fast refresh). When Next evaluates the\n * client component module server-side there is no document — no-op.\n */\nexport function setupPalbeNext(): void {\n if (typeof document === 'undefined') return;\n const config = getRuntime().config;\n __configure({ ...config, storage: cookieSessionStorage(endpointRefFromApiKey(config.apiKey)) });\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,IAAM,oBAAoB;AAW1B,IAAM,cAAc;AAGpB,SAAS,YAAiC;AACxC,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,QAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;AAC7C,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,QAAI,OAAO,GAAI;AACf,UAAM,OAAO,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK;AACpC,QAAI,KAAM,KAAI,IAAI,MAAM,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAoB;AAExC,WAAS,SAAS,GAAG,IAAI,MAAM,WAAW;AAC5C;AAOO,SAAS,qBAAqB,aAA4C;AAC/E,SAAO;AAAA,IACL,OAAgC;AAC9B,UAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,YAAM,MAAM,UAAU;AACtB,YAAM,SAAS,qBAAqB,CAAC,SAAS,IAAI,IAAI,IAAI,GAAG,WAAW;AACxE,UAAI,CAAC,OAAQ,QAAO;AAGpB,aAAO,OAAO,eAAe,OAAO,YAAY,IAC5C;AAAA,QACE,cAAc,OAAO;AAAA,QACrB,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,MACpB,IACA,EAAE,cAAc,OAAO,aAAa;AAAA,IAC1C;AAAA,IACA,KAAK,SAAiC;AACpC,UAAI,OAAO,aAAa,YAAa;AACrC,YAAM,MAAM,UAAU;AAItB,iBAAW,QAAQ,0BAA0B,aAAa,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC5E,qBAAa,IAAI;AAAA,MACnB;AACA,YAAM,EAAE,KAAK,MAAM,IAAI,qBAAqB,aAAa;AAAA,QACvD,aAAa,QAAQ,eAAe;AAAA,QACpC,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ,aAAa;AAAA,MAClC,CAAC;AACD,iBAAW,EAAE,MAAM,MAAM,KAAK,KAAK;AAEjC,iBAAS,SAAS,GAAG,IAAI,IAAI,KAAK,KAAK,WAAW,aAAa,iBAAiB;AAAA,MAClF;AAGA,iBAAW,QAAQ,MAAO,cAAa,IAAI;AAAA,IAC7C;AAAA,IACA,QAAc;AACZ,UAAI,OAAO,aAAa,YAAa;AACrC,YAAM,MAAM,UAAU;AACtB,iBAAW,QAAQ,0BAA0B,aAAa,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC5E,qBAAa,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,iBAAuB;AACrC,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,SAAS,WAAW,EAAE;AAC5B,cAAY,EAAE,GAAG,QAAQ,SAAS,qBAAqB,sBAAsB,OAAO,MAAM,CAAC,EAAE,CAAC;AAChG;","names":[]}
1
+ {"version":3,"sources":["../../src/next/client.ts"],"sourcesContent":["/**\n * '@palbase/web/next/client' — the browser half of the Next.js adapter. This entry\n * must NEVER import 'next' (it runs in plain client bundles); the cookie jar\n * is document.cookie itself, written with the shared codec so the server\n * side (pbServer / middleware / callback) reads the same bytes.\n */\nimport { __configure, getRuntime } from '../internal.js';\nimport type { PersistedSession, SessionStorageAdapter } from '../storage.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookies,\n endpointRefFromApiKey,\n} from './cookie-codec.js';\n\n/** 30 days — the refresh-token TTL (P3 design contract). */\nconst SESSION_MAX_AGE_S = 2_592_000;\n\n// Secure is unconditional, INCLUDING http://localhost: browsers treat\n// localhost as a potentially-trustworthy origin, so document.cookie accepts\n// Secure cookies there — no dev-mode special case needed. KNOWN LIMITATION:\n// plain-http origins OTHER than localhost — e.g. LAN-IP device testing on\n// http://192.168.x.x — are NOT trustworthy, so the browser silently DROPS\n// these Secure cookie writes and the session won't persist; use https (or a\n// localhost tunnel/port-forward) for on-device testing. NOT HttpOnly by\n// design: the browser SDK must read/write the session (Supabase-paradigm\n// tradeoff, documented in the P3 plan).\nconst WRITE_ATTRS = 'Path=/; SameSite=Lax; Secure';\n\n/** Parse document.cookie (\"a=1; b=2\") into a name → raw-value map. */\nfunction cookieJar(): Map<string, string> {\n const jar = new Map<string, string>();\n for (const part of document.cookie.split(';')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const name = part.slice(0, eq).trim();\n if (name) jar.set(name, part.slice(eq + 1).trim());\n }\n return jar;\n}\n\nfunction deleteCookie(name: string): void {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=; ${WRITE_ATTRS}; Max-Age=0`;\n}\n\n/**\n * document.cookie-backed SessionStorageAdapter. `load` returns the EXTENDED\n * PersistedSession (access token + expiry ride along) so hydration adopts\n * the full session without a refresh round-trip.\n */\nexport function cookieSessionStorage(endpointRef: string): SessionStorageAdapter {\n return {\n load(): PersistedSession | null {\n if (typeof document === 'undefined') return null;\n const jar = cookieJar();\n const stored = decodeSessionCookies((name) => jar.get(name), endpointRef);\n if (!stored) return null;\n // A refresh-only save round-trips as a:'' / e:0 — normalize back to\n // the legacy shape so hydration takes the expired-trick path cleanly.\n return stored.accessToken && stored.expiresAt > 0\n ? {\n refreshToken: stored.refreshToken,\n accessToken: stored.accessToken,\n expiresAt: stored.expiresAt,\n }\n : { refreshToken: stored.refreshToken };\n },\n save(session: PersistedSession): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n // Delete every currently-present session cookie first (stale chunks of\n // a previously-larger session, or a stale base when the new write\n // chunks), then set the new cookie(s).\n for (const name of clearedSessionCookieNames(endpointRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n const { set, clear } = encodeSessionCookies(endpointRef, {\n accessToken: session.accessToken ?? '',\n refreshToken: session.refreshToken,\n expiresAt: session.expiresAt ?? 0,\n });\n for (const { name, value } of set) {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=${value}; ${WRITE_ATTRS}; Max-Age=${SESSION_MAX_AGE_S}`;\n }\n // Overflow guard (codec contract): delete one-past-the-end so a stale\n // orphan chunk behind a gap can never join a future chunk run.\n for (const name of clear) deleteCookie(name);\n },\n clear(): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n for (const name of clearedSessionCookieNames(endpointRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n },\n };\n}\n\n/**\n * One-liner for a client component/provider: re-configure the already-loaded\n * gen config (palbe.gen.ts must be imported first — throws the guided\n * notConfigured error otherwise) with cookie-backed session storage so the\n * browser and the server share the session. Calling it again simply\n * re-configures (safe, e.g. under fast refresh). When Next evaluates the\n * client component module server-side there is no document — no-op.\n */\nexport function setupPalbeNext(): void {\n if (typeof document === 'undefined') return;\n const config = getRuntime().config;\n __configure({ ...config, storage: cookieSessionStorage(endpointRefFromApiKey(config.apiKey)) });\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,IAAM,oBAAoB;AAW1B,IAAM,cAAc;AAGpB,SAAS,YAAiC;AACxC,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,QAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;AAC7C,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,QAAI,OAAO,GAAI;AACf,UAAM,OAAO,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK;AACpC,QAAI,KAAM,KAAI,IAAI,MAAM,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAoB;AAExC,WAAS,SAAS,GAAG,IAAI,MAAM,WAAW;AAC5C;AAOO,SAAS,qBAAqB,aAA4C;AAC/E,SAAO;AAAA,IACL,OAAgC;AAC9B,UAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,YAAM,MAAM,UAAU;AACtB,YAAM,SAAS,qBAAqB,CAAC,SAAS,IAAI,IAAI,IAAI,GAAG,WAAW;AACxE,UAAI,CAAC,OAAQ,QAAO;AAGpB,aAAO,OAAO,eAAe,OAAO,YAAY,IAC5C;AAAA,QACE,cAAc,OAAO;AAAA,QACrB,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,MACpB,IACA,EAAE,cAAc,OAAO,aAAa;AAAA,IAC1C;AAAA,IACA,KAAK,SAAiC;AACpC,UAAI,OAAO,aAAa,YAAa;AACrC,YAAM,MAAM,UAAU;AAItB,iBAAW,QAAQ,0BAA0B,aAAa,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC5E,qBAAa,IAAI;AAAA,MACnB;AACA,YAAM,EAAE,KAAK,MAAM,IAAI,qBAAqB,aAAa;AAAA,QACvD,aAAa,QAAQ,eAAe;AAAA,QACpC,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ,aAAa;AAAA,MAClC,CAAC;AACD,iBAAW,EAAE,MAAM,MAAM,KAAK,KAAK;AAEjC,iBAAS,SAAS,GAAG,IAAI,IAAI,KAAK,KAAK,WAAW,aAAa,iBAAiB;AAAA,MAClF;AAGA,iBAAW,QAAQ,MAAO,cAAa,IAAI;AAAA,IAC7C;AAAA,IACA,QAAc;AACZ,UAAI,OAAO,aAAa,YAAa;AACrC,YAAM,MAAM,UAAU;AACtB,iBAAW,QAAQ,0BAA0B,aAAa,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC5E,qBAAa,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,iBAAuB;AACrC,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,SAAS,WAAW,EAAE;AAC5B,cAAY,EAAE,GAAG,QAAQ,SAAS,qBAAqB,sBAAsB,OAAO,MAAM,CAAC,EAAE,CAAC;AAChG;","names":[]}
@@ -1527,6 +1527,8 @@ var PalbeAuth = class {
1527
1527
  // suppresses AuthClient's TOKEN_REFRESHED during re-signIn
1528
1528
  signedInState = false;
1529
1529
  // dedupes AuthClient's repeated SIGNED_OUT events
1530
+ hydratingUser = false;
1531
+ // guards hydrateUser() to a single boot fetch
1530
1532
  stateListeners = /* @__PURE__ */ new Set();
1531
1533
  eventListeners = /* @__PURE__ */ new Set();
1532
1534
  userListeners = /* @__PURE__ */ new Set();
@@ -1579,13 +1581,37 @@ var PalbeAuth = class {
1579
1581
  if (changed) for (const cb of this.userListeners) this.safeInvoke(() => cb(user));
1580
1582
  return user;
1581
1583
  }
1584
+ /**
1585
+ * Restore the user after a session was rehydrated from storage (page reload).
1586
+ * Hydration in buildRuntime restores the TOKENS synchronously, but the access
1587
+ * token JWT does not carry emailVerified/createdAt, so the full AuthUser can't
1588
+ * be reconstructed offline — this fetches GET /auth/user once and announces
1589
+ * `signedIn`, so the app no longer has to `await pb.auth.refreshUser()` itself
1590
+ * on boot. Idempotent (runs once), browser-safe (no-op when not signed in or
1591
+ * a user is already cached), and never throws (a boot-time network failure
1592
+ * must not break app startup — isSignedIn stays true, the app can retry).
1593
+ */
1594
+ hydrateUser() {
1595
+ if (this.hydratingUser || this.cachedUser || !this.isSignedIn) return;
1596
+ this.hydratingUser = true;
1597
+ void this.refreshUser().then((user) => {
1598
+ if (this.isSignedIn) {
1599
+ this.signedInState = true;
1600
+ this.emitState({ status: "signedIn", user });
1601
+ }
1602
+ }).catch(() => {
1603
+ }).finally(() => {
1604
+ this.hydratingUser = false;
1605
+ });
1606
+ }
1582
1607
  // ── listeners ──────────────────────────────────────────
1583
1608
  /**
1584
1609
  * Subscribe to signed-in/signed-out state. Fires immediately with the
1585
- * current snapshot (iOS parity). NOTE: a restored session (page reload) has
1586
- * no cached user yet, so the immediate snapshot reports signedOut even when
1587
- * `isSignedIn` is true call `refreshUser()` on boot to populate the user
1588
- * and rely on `isSignedIn` for the session truth.
1610
+ * current snapshot (iOS parity). A restored session (page reload) hydrates
1611
+ * the user asynchronously via `hydrateUser()` (fired once at boot), so the
1612
+ * FIRST snapshot may report signedOut for a tick even when `isSignedIn` is
1613
+ * true; the listener then fires again with `signedIn` once the user lands.
1614
+ * Rely on `isSignedIn` for the session truth if you need it synchronously.
1589
1615
  */
1590
1616
  onAuthStateChange(callback) {
1591
1617
  this.stateListeners.add(callback);
@@ -8939,7 +8965,7 @@ function defaultSessionStorage(key) {
8939
8965
  }
8940
8966
 
8941
8967
  // src/version.ts
8942
- var VERSION = "1.8.0";
8968
+ var VERSION = "1.10.0";
8943
8969
 
8944
8970
  // src/runtime.ts
8945
8971
  function buildRuntime(config) {
@@ -9057,6 +9083,7 @@ function buildRuntime(config) {
9057
9083
  void rt.perf;
9058
9084
  if (typeof document !== "undefined") {
9059
9085
  void new PerfConfigClient().fetchConfig(rt, rt.perf);
9086
+ rt.auth.hydrateUser();
9060
9087
  }
9061
9088
  recordColdStart(rt);
9062
9089
  observeWebVitals((item) => rt.perf.record(item));