@palbase/web 2.0.1 → 4.0.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 (47) hide show
  1. package/README.md +11 -9
  2. package/dist/{analytics-facade-ChlBRcLZ.d.cts → analytics-facade-DwOtlXPP.d.cts} +13 -103
  3. package/dist/{analytics-facade-G0il4NrT.d.ts → analytics-facade-Nk6J9Ncm.d.ts} +13 -103
  4. package/dist/{chunk-VJXFABBW.js → chunk-6VGKMNXO.js} +11 -11
  5. package/dist/chunk-6VGKMNXO.js.map +1 -0
  6. package/dist/{chunk-AIPUO4QX.js → chunk-NP4NIY7A.js} +52 -48
  7. package/dist/chunk-NP4NIY7A.js.map +1 -0
  8. package/dist/chunk-S7NAY3MW.js +24 -0
  9. package/dist/chunk-S7NAY3MW.js.map +1 -0
  10. package/dist/gen/cli.cjs +32 -6
  11. package/dist/gen/cli.cjs.map +1 -1
  12. package/dist/gen/cli.js +28 -7
  13. package/dist/gen/cli.js.map +1 -1
  14. package/dist/index.cjs +25 -22
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +3 -4
  17. package/dist/index.d.ts +3 -4
  18. package/dist/index.js +2 -2
  19. package/dist/internal.cjs +55 -44
  20. package/dist/internal.cjs.map +1 -1
  21. package/dist/internal.d.cts +4 -16
  22. package/dist/internal.d.ts +4 -16
  23. package/dist/internal.js +2 -2
  24. package/dist/next/client.cjs +72 -58
  25. package/dist/next/client.cjs.map +1 -1
  26. package/dist/next/client.d.cts +1 -1
  27. package/dist/next/client.d.ts +1 -1
  28. package/dist/next/client.js +12 -10
  29. package/dist/next/client.js.map +1 -1
  30. package/dist/next/index.cjs +75 -59
  31. package/dist/next/index.cjs.map +1 -1
  32. package/dist/next/index.d.cts +10 -11
  33. package/dist/next/index.d.ts +10 -11
  34. package/dist/next/index.js +14 -13
  35. package/dist/next/index.js.map +1 -1
  36. package/dist/{pb-B_6o5p79.d.cts → pb-C9v5dEO6.d.cts} +1 -1
  37. package/dist/{pb-nPBhqhJr.d.ts → pb-FG_nV7NR.d.ts} +1 -1
  38. package/dist/react/index.cjs +1 -1
  39. package/dist/react/index.cjs.map +1 -1
  40. package/dist/react/index.d.cts +1 -2
  41. package/dist/react/index.d.ts +1 -2
  42. package/dist/react/index.js +2 -2
  43. package/package.json +3 -3
  44. package/dist/chunk-AIPUO4QX.js.map +0 -1
  45. package/dist/chunk-PZ5AY32C.js +0 -10
  46. package/dist/chunk-PZ5AY32C.js.map +0 -1
  47. package/dist/chunk-VJXFABBW.js.map +0 -1
@@ -5,7 +5,7 @@ import { S as SessionStorageAdapter } from '../storage-BPaeSG8K.cjs';
5
5
  * PersistedSession (access token + expiry ride along) so hydration adopts
6
6
  * the full session without a refresh round-trip.
7
7
  */
8
- declare function cookieSessionStorage(endpointRef: string): SessionStorageAdapter;
8
+ declare function cookieSessionStorage(environmentRef: string): SessionStorageAdapter;
9
9
  /**
10
10
  * One-liner for a client component/provider: re-configure the already-loaded
11
11
  * gen config (palbe.gen.ts must be imported first — throws the guided
@@ -5,7 +5,7 @@ import { S as SessionStorageAdapter } from '../storage-BPaeSG8K.js';
5
5
  * PersistedSession (access token + expiry ride along) so hydration adopts
6
6
  * the full session without a refresh round-trip.
7
7
  */
8
- declare function cookieSessionStorage(endpointRef: string): SessionStorageAdapter;
8
+ declare function cookieSessionStorage(environmentRef: string): SessionStorageAdapter;
9
9
  /**
10
10
  * One-liner for a client component/provider: re-configure the already-loaded
11
11
  * gen config (palbe.gen.ts must be imported first — throws the guided
@@ -2,13 +2,12 @@ import {
2
2
  clearedSessionCookieNames,
3
3
  decodeSessionCookies,
4
4
  encodeSessionCookies
5
- } from "../chunk-VJXFABBW.js";
5
+ } from "../chunk-6VGKMNXO.js";
6
6
  import {
7
7
  __configure,
8
- endpointRefFromApiKey,
9
8
  getRuntime
10
- } from "../chunk-AIPUO4QX.js";
11
- import "../chunk-PZ5AY32C.js";
9
+ } from "../chunk-NP4NIY7A.js";
10
+ import "../chunk-S7NAY3MW.js";
12
11
 
13
12
  // src/next/client.ts
14
13
  var SESSION_MAX_AGE_S = 2592e3;
@@ -26,12 +25,12 @@ function cookieJar() {
26
25
  function deleteCookie(name) {
27
26
  document.cookie = `${name}=; ${WRITE_ATTRS}; Max-Age=0`;
28
27
  }
29
- function cookieSessionStorage(endpointRef) {
28
+ function cookieSessionStorage(environmentRef) {
30
29
  return {
31
30
  load() {
32
31
  if (typeof document === "undefined") return null;
33
32
  const jar = cookieJar();
34
- const stored = decodeSessionCookies((name) => jar.get(name), endpointRef);
33
+ const stored = decodeSessionCookies((name) => jar.get(name), environmentRef);
35
34
  if (!stored) return null;
36
35
  return stored.accessToken && stored.expiresAt > 0 ? {
37
36
  refreshToken: stored.refreshToken,
@@ -42,10 +41,10 @@ function cookieSessionStorage(endpointRef) {
42
41
  save(session) {
43
42
  if (typeof document === "undefined") return;
44
43
  const jar = cookieJar();
45
- for (const name of clearedSessionCookieNames(endpointRef, (n) => jar.has(n))) {
44
+ for (const name of clearedSessionCookieNames(environmentRef, (n) => jar.has(n))) {
46
45
  deleteCookie(name);
47
46
  }
48
- const { set, clear } = encodeSessionCookies(endpointRef, {
47
+ const { set, clear } = encodeSessionCookies(environmentRef, {
49
48
  accessToken: session.accessToken ?? "",
50
49
  refreshToken: session.refreshToken,
51
50
  expiresAt: session.expiresAt ?? 0
@@ -58,7 +57,7 @@ function cookieSessionStorage(endpointRef) {
58
57
  clear() {
59
58
  if (typeof document === "undefined") return;
60
59
  const jar = cookieJar();
61
- for (const name of clearedSessionCookieNames(endpointRef, (n) => jar.has(n))) {
60
+ for (const name of clearedSessionCookieNames(environmentRef, (n) => jar.has(n))) {
62
61
  deleteCookie(name);
63
62
  }
64
63
  }
@@ -67,7 +66,10 @@ function cookieSessionStorage(endpointRef) {
67
66
  function setupPalbeNext() {
68
67
  if (typeof document === "undefined") return;
69
68
  const config = getRuntime().config;
70
- __configure({ ...config, storage: cookieSessionStorage(endpointRefFromApiKey(config.apiKey)) });
69
+ __configure({
70
+ ...config,
71
+ storage: cookieSessionStorage(config.environmentRef)
72
+ });
71
73
  }
72
74
  export {
73
75
  cookieSessionStorage,
@@ -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} 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(environmentRef: 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), environmentRef);\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(environmentRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n const { set, clear } = encodeSessionCookies(environmentRef, {\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(environmentRef, (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({\n ...config,\n storage: cookieSessionStorage(config.environmentRef),\n });\n}\n"],"mappings":";;;;;;;;;;;;AAeA,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,gBAA+C;AAClF,SAAO;AAAA,IACL,OAAgC;AAC9B,UAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,YAAM,MAAM,UAAU;AACtB,YAAM,SAAS,qBAAqB,CAAC,SAAS,IAAI,IAAI,IAAI,GAAG,cAAc;AAC3E,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,gBAAgB,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC/E,qBAAa,IAAI;AAAA,MACnB;AACA,YAAM,EAAE,KAAK,MAAM,IAAI,qBAAqB,gBAAgB;AAAA,QAC1D,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,gBAAgB,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC/E,qBAAa,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,iBAAuB;AACrC,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,SAAS,WAAW,EAAE;AAC5B,cAAY;AAAA,IACV,GAAG;AAAA,IACH,SAAS,qBAAqB,OAAO,cAAc;AAAA,EACrD,CAAC;AACH;","names":[]}
@@ -35,7 +35,7 @@ __export(next_exports, {
35
35
  decodeSessionCookies: () => decodeSessionCookies,
36
36
  encodeSessionCookies: () => encodeSessionCookies,
37
37
  encodeSessionCookiesDecoded: () => encodeSessionCookiesDecoded,
38
- endpointRefFromApiKey: () => endpointRefFromApiKey,
38
+ environmentRefFromApiKey: () => environmentRefFromApiKey,
39
39
  handleAuthCallback: () => handleAuthCallback,
40
40
  palbeMiddleware: () => palbeMiddleware,
41
41
  pbServer: () => pbServer,
@@ -57,11 +57,16 @@ function asWireAuthResult(raw) {
57
57
  }
58
58
 
59
59
  // src/api-key.ts
60
- var API_KEY_RE = /^pb_([^_]+)_[cs][A-Za-z0-9]{20}$/;
61
- function endpointRefFromApiKey(apiKey) {
60
+ var API_KEY_RE = /^pb_([a-z0-9]+)_[cs][A-Za-z0-9]{20}$/;
61
+ var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;
62
+ function environmentRefFromApiKey(apiKey) {
62
63
  const m = API_KEY_RE.exec(apiKey);
63
64
  return m ? m[1] ?? "" : "";
64
65
  }
66
+ function environmentRefFromPublishableApiKey(apiKey) {
67
+ const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);
68
+ return match ? match[1] ?? "" : "";
69
+ }
65
70
 
66
71
  // src/next/cookie-codec.ts
67
72
  var MAX_COOKIE_VALUE = 3500;
@@ -71,11 +76,11 @@ var SESSION_COOKIE_ATTRS = {
71
76
  secure: true,
72
77
  maxAge: 2592e3
73
78
  };
74
- function sessionCookieName(endpointRef) {
75
- return `palbe-session-${endpointRef}`;
79
+ function sessionCookieName(environmentRef) {
80
+ return `palbe-session-${environmentRef}`;
76
81
  }
77
- function encodeSessionCookies(endpointRef, session) {
78
- const name = sessionCookieName(endpointRef);
82
+ function encodeSessionCookies(environmentRef, session) {
83
+ const name = sessionCookieName(environmentRef);
79
84
  const value = encodeURIComponent(
80
85
  JSON.stringify({ a: session.accessToken, r: session.refreshToken, e: session.expiresAt })
81
86
  );
@@ -94,15 +99,15 @@ function encodeSessionCookies(endpointRef, session) {
94
99
  }
95
100
  return { set: chunks, clear: [`${name}.${chunks.length}`] };
96
101
  }
97
- function encodeSessionCookiesDecoded(endpointRef, session) {
98
- const { set, clear } = encodeSessionCookies(endpointRef, session);
102
+ function encodeSessionCookiesDecoded(environmentRef, session) {
103
+ const { set, clear } = encodeSessionCookies(environmentRef, session);
99
104
  return {
100
105
  set: set.map(({ name, value }) => ({ name, value: decodeURIComponent(value) })),
101
106
  clear
102
107
  };
103
108
  }
104
- function decodeSessionCookies(get, endpointRef) {
105
- const base = sessionCookieName(endpointRef);
109
+ function decodeSessionCookies(get, environmentRef) {
110
+ const base = sessionCookieName(environmentRef);
106
111
  let encoded = get(base);
107
112
  if (encoded === void 0) {
108
113
  let joined = "";
@@ -136,8 +141,8 @@ function parseStoredSession(json) {
136
141
  return null;
137
142
  }
138
143
  }
139
- function clearedSessionCookieNames(endpointRef, present) {
140
- const base = sessionCookieName(endpointRef);
144
+ function clearedSessionCookieNames(environmentRef, present) {
145
+ const base = sessionCookieName(environmentRef);
141
146
  const names = [];
142
147
  if (present(base)) names.push(base);
143
148
  for (let i = 0; ; i++) {
@@ -163,18 +168,9 @@ var PalbaseError = class extends Error {
163
168
  }
164
169
  };
165
170
  var PALBASE_DEFAULT_HOST = "api.palbase.studio";
166
- var REF_LEN = 8;
167
- var BASE62_RE = /^[0-9A-Za-z]+$/;
168
- function parseProjectRef(apiKey) {
169
- if (apiKey.length < 13) return null;
170
- if (!apiKey.startsWith("pb_")) return null;
171
- if (apiKey[11] !== "_") return null;
172
- const ref = apiKey.slice(3, 11);
173
- if (ref.length !== REF_LEN) return null;
174
- if (!BASE62_RE.test(ref)) return null;
175
- const scope = apiKey[12];
176
- if (scope !== "c") return null;
177
- return ref;
171
+ var API_KEY_RE2 = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;
172
+ function parseEnvironmentRef(apiKey) {
173
+ return API_KEY_RE2.exec(apiKey)?.[1] ?? null;
178
174
  }
179
175
  var MAX_RETRIES = 3;
180
176
  var INITIAL_BACKOFF_MS = 200;
@@ -204,8 +200,7 @@ var HttpClient = class _HttpClient {
204
200
  * with the parent at runtime — later changes on the parent propagate to
205
201
  * the scope and vice versa.
206
202
  *
207
- * Typical use: tagging admin calls with `x-palbase-project: <ref>` so the
208
- * gateway can route them to the correct project's data plane.
203
+ * Typical use: adding an Environment-routing header for an admin call.
209
204
  */
210
205
  withHeaders(extra) {
211
206
  const mergedHeaders = { ...this.options?.headers ?? {}, ...extra };
@@ -246,10 +241,10 @@ var HttpClient = class _HttpClient {
246
241
  if (this.options?.url) {
247
242
  return this.options.url;
248
243
  }
249
- if (this.apiKey && parseProjectRef(this.apiKey) === null) {
244
+ if (this.apiKey && parseEnvironmentRef(this.apiKey) === null) {
250
245
  throw new PalbaseError(
251
246
  "invalid_api_key",
252
- 'Invalid API key format. Expected pb_{ref}_{scope}{random}. For dev/staging pass `url: "https://api.dev.palbase.studio"` via options.',
247
+ 'Invalid API key format. Expected pb_{environment_ref}_c{20_base62_chars}. For dev/staging pass `url: "https://api.dev.palbase.studio"` via options.',
253
248
  0
254
249
  );
255
250
  }
@@ -262,10 +257,6 @@ var HttpClient = class _HttpClient {
262
257
  const effectiveKey = this.apiKey;
263
258
  if (effectiveKey) {
264
259
  headers["apikey"] = effectiveKey;
265
- const ref = parseProjectRef(effectiveKey);
266
- if (ref) {
267
- headers["X-Project-Ref"] = ref;
268
- }
269
260
  }
270
261
  const token = this.tokenManager?.getAccessToken();
271
262
  if (token) {
@@ -1245,7 +1236,7 @@ var AnalyticsState = class {
1245
1236
  idKey;
1246
1237
  optOutKey;
1247
1238
  constructor(rt) {
1248
- const ref = endpointRefFromApiKey(rt.config.apiKey);
1239
+ const ref = rt.config.environmentRef;
1249
1240
  this.idKey = ref ? `palbe.analytics.id.${ref}` : "palbe.analytics.id";
1250
1241
  this.optOutKey = ref ? `palbe.analytics.optout.${ref}` : "palbe.analytics.optout";
1251
1242
  rt.auth.onAuthEvent((event) => {
@@ -1793,19 +1784,29 @@ var PalbeAuth = class {
1793
1784
 
1794
1785
  // src/calls/facade.ts
1795
1786
  var import_livekit_client = require("livekit-client");
1796
- var Call = class {
1787
+ var Call = class _Call {
1797
1788
  id;
1798
1789
  _state = "connecting";
1799
1790
  _participants = /* @__PURE__ */ new Map();
1800
1791
  _listeners = /* @__PURE__ */ new Set();
1801
1792
  _room;
1802
1793
  _keyProvider;
1803
- /** @internal obtain via PalbeCalls.start() / .accept() */
1794
+ // PRIVATE constructor + `@internal` factory: the media-engine types (`Room`,
1795
+ // `ExternalE2EEKeyProvider`) appear ONLY on a private constructor and an
1796
+ // `@internal` static factory, both of which `stripInternal` (set in this
1797
+ // package's tsconfig) removes from the emitted public `.d.ts`. So no engine type
1798
+ // ever reaches the public API surface — the same "no engine type in the public
1799
+ // interface" contract the iOS SDK enforces. Consumers obtain a `Call` only
1800
+ // through `pb.calls.start()` / `.accept()`.
1804
1801
  constructor(callId, room, keyProvider) {
1805
1802
  this.id = callId;
1806
1803
  this._room = room;
1807
1804
  this._keyProvider = keyProvider;
1808
- this._wireRoomEvents();
1805
+ this._wireMediaEvents();
1806
+ }
1807
+ /** @internal — facade-only factory; stripped from the public `.d.ts`. */
1808
+ static _create(callId, room, keyProvider) {
1809
+ return new _Call(callId, room, keyProvider);
1809
1810
  }
1810
1811
  // ─── State ──────────────────────────────────────────────────────────────
1811
1812
  get state() {
@@ -1815,9 +1816,9 @@ var Call = class {
1815
1816
  get participants() {
1816
1817
  return Array.from(this._participants.values());
1817
1818
  }
1818
- get localParticipant() {
1819
- return this._room.localParticipant;
1820
- }
1819
+ // (No `localParticipant` accessor: it would return a raw media-engine participant
1820
+ // object and leak the engine type onto the public API. Local mic/camera control is
1821
+ // exposed engine-agnostically via `mute()` / `setCamera()` below.)
1821
1822
  // ─── Subscribe ──────────────────────────────────────────────────────────
1822
1823
  /**
1823
1824
  * Subscribe to call changes (state + participant updates).
@@ -1841,7 +1842,7 @@ var Call = class {
1841
1842
  /**
1842
1843
  * Set a raw frame encryption key (ArrayBuffer) for this call.
1843
1844
  * Design seam for SP-1.x web-MLS: call this with the MLS exporter secret
1844
- * to enable frame-level E2EE via ExternalE2EEKeyProvider.
1845
+ * to enable frame-level E2EE via the media engine's external key provider.
1845
1846
  *
1846
1847
  * NOTE: The room must have been opened with `e2ee` options for this to take
1847
1848
  * effect. Currently calls connect WITHOUT e2ee — see module docstring.
@@ -1851,7 +1852,7 @@ var Call = class {
1851
1852
  async setMediaKey(key) {
1852
1853
  await this._keyProvider.setKey(key);
1853
1854
  }
1854
- /** Leave the call and disconnect from the LiveKit room. */
1855
+ /** Leave the call and disconnect from the media room. */
1855
1856
  async leave() {
1856
1857
  await this._room.disconnect();
1857
1858
  this._setState("ended");
@@ -1893,7 +1894,7 @@ var Call = class {
1893
1894
  }
1894
1895
  this._emit();
1895
1896
  }
1896
- _wireRoomEvents() {
1897
+ _wireMediaEvents() {
1897
1898
  this._room.on(import_livekit_client.RoomEvent.Connected, () => {
1898
1899
  this._setState("active");
1899
1900
  }).on(
@@ -1934,9 +1935,9 @@ var PalbeCalls = class {
1934
1935
  *
1935
1936
  * @param groupId - Messaging group display-id (`grp_<uuidv7>`)
1936
1937
  * @param media - Which media tracks to publish (default: audio + video)
1937
- * @returns A `Call` in `connecting` state; transitions to `active` once LiveKit connects.
1938
+ * @returns A `Call` in `connecting` state; transitions to `active` once the media room connects.
1938
1939
  *
1939
- * @throws BackendError('network', { code: 'call_service_unavailable' }) if LiveKit SFU is down (503)
1940
+ * @throws BackendError('network', { code: 'call_service_unavailable' }) if the SFU is down (503)
1940
1941
  * @throws BackendError('forbidden', { code: 'not_group_member' }) if the caller is not a member (403)
1941
1942
  * @throws BackendError('conflict', { code: 'call_room_full' }) if the room is full (409)
1942
1943
  */
@@ -1993,7 +1994,7 @@ var PalbeCalls = class {
1993
1994
  adaptiveStream: true,
1994
1995
  dynacast: true
1995
1996
  });
1996
- const call = new Call(callId, room, keyProvider);
1997
+ const call = Call._create(callId, room, keyProvider);
1997
1998
  await room.connect(edgeUrl, token);
1998
1999
  if (media.includes("audio")) {
1999
2000
  await room.localParticipant.setMicrophoneEnabled(true);
@@ -2586,7 +2587,7 @@ var PalbeFlags = class {
2586
2587
  constructor(rt) {
2587
2588
  this.transport = new FlagsClient(rt.http);
2588
2589
  const browser = typeof document !== "undefined";
2589
- const ref = endpointRefFromApiKey(rt.config.apiKey);
2590
+ const ref = rt.config.environmentRef;
2590
2591
  const options = {
2591
2592
  auth: palbeAuthAdapter(rt.auth),
2592
2593
  ...ref ? { storageKey: `palbe.flags.${ref}` } : {},
@@ -8326,7 +8327,7 @@ var AnonTokenProvider = class {
8326
8327
  }
8327
8328
  /**
8328
8329
  * Raw fetch, deliberately NOT through HttpClient/palbeRequest: the mint
8329
- * must carry the project apikey and NEVER a Bearer (iOS keeps
8330
+ * must carry the Environment API key and NEVER a Bearer (iOS keeps
8330
8331
  * `/auth/anonymous` on the unauthenticated-path list), and HttpClient's
8331
8332
  * pre-flight would try to refresh a stale session before an anon mint —
8332
8333
  * exactly the entanglement this provider exists to avoid.
@@ -8983,10 +8984,25 @@ function defaultSessionStorage(key) {
8983
8984
  }
8984
8985
 
8985
8986
  // src/version.ts
8986
- var VERSION = "2.0.1";
8987
+ var VERSION = "4.0.0";
8987
8988
 
8988
8989
  // src/runtime.ts
8989
8990
  function buildRuntime(config) {
8991
+ const keyEnvironmentRef = environmentRefFromPublishableApiKey(config.apiKey);
8992
+ if (keyEnvironmentRef === "") {
8993
+ throw new Error("PalbeConfig.apiKey does not contain a valid publishable Environment identity");
8994
+ } else if (config.environmentRef !== keyEnvironmentRef) {
8995
+ throw new Error("PalbeConfig.environmentRef must match the Environment identity in apiKey");
8996
+ }
8997
+ let runtimeURL;
8998
+ try {
8999
+ runtimeURL = new URL(config.url);
9000
+ } catch {
9001
+ throw new Error("PalbeConfig.url must be a valid URL");
9002
+ }
9003
+ if (runtimeURL.hostname.endsWith(".palbase.studio") && runtimeURL.hostname.split(".")[0] !== config.environmentRef) {
9004
+ throw new Error("PalbeConfig.url must match environmentRef for palbase.studio");
9005
+ }
8990
9006
  const http = new HttpClient(config.apiKey, {
8991
9007
  url: config.url,
8992
9008
  headers: { "X-Client-Info": `palbe-web/${VERSION}`, ...config.headers }
@@ -8995,7 +9011,7 @@ function buildRuntime(config) {
8995
9011
  const tokenManager = new TokenManager();
8996
9012
  http.tokenManager = tokenManager;
8997
9013
  const authClient = new AuthClient(http, tokenManager);
8998
- const ref = endpointRefFromApiKey(config.apiKey);
9014
+ const ref = config.environmentRef;
8999
9015
  const storage = config.storage ?? defaultSessionStorage(ref ? `palbe.session.${ref}` : void 0);
9000
9016
  const persisted = storage.load();
9001
9017
  if (persisted) {
@@ -9449,7 +9465,7 @@ function handleAuthCallback(opts) {
9449
9465
  const wire = asWireAuthResult(raw);
9450
9466
  if (!wire) return redirect(fallback, { auth_error: "oauth_exchange_failed" });
9451
9467
  const response = redirect(safeNextPath(params.get("next"), request.nextUrl.origin) ?? fallback);
9452
- const write = encodeSessionCookiesDecoded(endpointRefFromApiKey(config.apiKey), {
9468
+ const write = encodeSessionCookiesDecoded(config.environmentRef, {
9453
9469
  accessToken: wire.access_token,
9454
9470
  refreshToken: wire.refresh_token,
9455
9471
  expiresAt: Date.now() + wire.expires_in * 1e3
@@ -9512,7 +9528,7 @@ async function palbeMiddleware(request, opts) {
9512
9528
  );
9513
9529
  const { NextResponse } = await importNextServer("palbeMiddleware");
9514
9530
  const passThrough = () => opts?.response ?? NextResponse.next({ request });
9515
- const ref = endpointRefFromApiKey(config.apiKey);
9531
+ const ref = config.environmentRef;
9516
9532
  const session = decodeSessionCookies((name) => request.cookies.get(name)?.value, ref);
9517
9533
  if (!session) return passThrough();
9518
9534
  if (session.expiresAt - Date.now() > (opts?.refreshMarginMs ?? DEFAULT_REFRESH_MARGIN_MS)) {
@@ -9582,11 +9598,11 @@ function removeCookie(store, name) {
9582
9598
  } catch {
9583
9599
  }
9584
9600
  }
9585
- function serverCookieAdapter(store, endpointRef) {
9601
+ function serverCookieAdapter(store, environmentRef) {
9586
9602
  const present = (name) => store.get(name) !== void 0;
9587
9603
  return {
9588
9604
  load() {
9589
- const stored = decodeSessionCookies((name) => store.get(name)?.value, endpointRef);
9605
+ const stored = decodeSessionCookies((name) => store.get(name)?.value, environmentRef);
9590
9606
  if (!stored) return null;
9591
9607
  return stored.accessToken && stored.expiresAt > 0 ? {
9592
9608
  refreshToken: stored.refreshToken,
@@ -9596,10 +9612,10 @@ function serverCookieAdapter(store, endpointRef) {
9596
9612
  },
9597
9613
  save(session) {
9598
9614
  if (!session.accessToken || !session.expiresAt) return;
9599
- for (const name of clearedSessionCookieNames(endpointRef, present)) {
9615
+ for (const name of clearedSessionCookieNames(environmentRef, present)) {
9600
9616
  removeCookie(store, name);
9601
9617
  }
9602
- const { set, clear } = encodeSessionCookiesDecoded(endpointRef, {
9618
+ const { set, clear } = encodeSessionCookiesDecoded(environmentRef, {
9603
9619
  accessToken: session.accessToken,
9604
9620
  refreshToken: session.refreshToken,
9605
9621
  expiresAt: session.expiresAt
@@ -9613,7 +9629,7 @@ function serverCookieAdapter(store, endpointRef) {
9613
9629
  for (const name of clear) removeCookie(store, name);
9614
9630
  },
9615
9631
  clear() {
9616
- for (const name of clearedSessionCookieNames(endpointRef, present)) {
9632
+ for (const name of clearedSessionCookieNames(environmentRef, present)) {
9617
9633
  removeCookie(store, name);
9618
9634
  }
9619
9635
  }
@@ -9624,7 +9640,7 @@ async function pbServer(opts) {
9624
9640
  "import the generated palbe.gen.ts once in app/layout.tsx \u2014 the root-layout import configures Server Components and Route Handlers too."
9625
9641
  );
9626
9642
  const store = opts?.cookies ?? await nextCookieStore();
9627
- const ref = endpointRefFromApiKey(config.apiKey);
9643
+ const ref = config.environmentRef;
9628
9644
  const rt = buildRuntime({ ...config, storage: serverCookieAdapter(store, ref) });
9629
9645
  return createBoundClient(rt);
9630
9646
  }
@@ -9635,7 +9651,7 @@ async function pbServer(opts) {
9635
9651
  decodeSessionCookies,
9636
9652
  encodeSessionCookies,
9637
9653
  encodeSessionCookiesDecoded,
9638
- endpointRefFromApiKey,
9654
+ environmentRefFromApiKey,
9639
9655
  handleAuthCallback,
9640
9656
  palbeMiddleware,
9641
9657
  pbServer,