@palbase/web 2.0.0 → 3.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-ovP0pF2P.d.cts → analytics-facade-BOxQ8IP2.d.cts} +11 -10
  3. package/dist/{analytics-facade-DMtGDGfd.d.ts → analytics-facade-yfMJ69vw.d.ts} +11 -10
  4. package/dist/{chunk-V6VTX65P.js → chunk-3HVTEZ7N.js} +80 -58
  5. package/dist/chunk-3HVTEZ7N.js.map +1 -0
  6. package/dist/{chunk-VJXFABBW.js → chunk-6VGKMNXO.js} +11 -11
  7. package/dist/chunk-6VGKMNXO.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 +33 -8
  11. package/dist/gen/cli.cjs.map +1 -1
  12. package/dist/gen/cli.js +29 -9
  13. package/dist/gen/cli.js.map +1 -1
  14. package/dist/index.cjs +53 -32
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +4 -4
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +2 -2
  19. package/dist/internal.cjs +83 -54
  20. package/dist/internal.cjs.map +1 -1
  21. package/dist/internal.d.cts +4 -4
  22. package/dist/internal.d.ts +4 -4
  23. package/dist/internal.js +2 -2
  24. package/dist/next/client.cjs +100 -68
  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 +103 -69
  31. package/dist/next/index.cjs.map +1 -1
  32. package/dist/next/index.d.cts +11 -11
  33. package/dist/next/index.d.ts +11 -11
  34. package/dist/next/index.js +14 -13
  35. package/dist/next/index.js.map +1 -1
  36. package/dist/{pb-DDM_mCQB.d.cts → pb-B3h3NIPE.d.cts} +1 -1
  37. package/dist/{pb-CvpcQero.d.ts → pb-QRISxPd1.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 +2 -2
  41. package/dist/react/index.d.ts +2 -2
  42. package/dist/react/index.js +2 -2
  43. package/package.json +4 -4
  44. package/dist/chunk-PZ5AY32C.js +0 -10
  45. package/dist/chunk-PZ5AY32C.js.map +0 -1
  46. package/dist/chunk-V6VTX65P.js.map +0 -1
  47. package/dist/chunk-VJXFABBW.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
- export { f as AnalyticsProperties, g as AuthChangeEvent, h as AuthState, i as AuthSuccess, A as AuthUser, j as Call, k as CallChangeCallback, l as CallParticipant, m as CallState, C as Chat, n as ChatBackend, o as ChatDraft, p as ChatKind, b as ChatMember, c as ChatMessage, q as ChatMessageKind, r as ChatRole, s as ChatState, t as CommsPrefs, F as FlagsView, M as MagicLinkResult, u as MentionRange, v as MessageDirection, N as NotifyScope, O as OAuthExchangeResult, w as PalbeAnalytics, x as PalbeAuth, y as PalbeCalls, P as PalbeConfig, z as PalbeFlags, B as PalbeMessaging, D as PalbeOAuthConfig, E as PalbeRealtime, G as PresenceState, H as RealtimeChannel, R as RealtimeConnectionState, I as RealtimeHandler, a as RealtimePayload, J as RealtimeStatus, K as RealtimeStatusSnapshot, L as RealtimeSubscription, Q as ResolvedMention, S as ResolvedReply, T as SentReceipt, U as UnreadView, V as Unsubscribe } from './analytics-facade-ovP0pF2P.cjs';
1
+ export { f as AnalyticsProperties, g as AuthChangeEvent, h as AuthState, i as AuthSuccess, A as AuthUser, j as Call, k as CallChangeCallback, l as CallParticipant, m as CallState, C as Chat, n as ChatBackend, o as ChatDraft, p as ChatKind, b as ChatMember, c as ChatMessage, q as ChatMessageKind, r as ChatRole, s as ChatState, t as CommsPrefs, F as FlagsView, M as MagicLinkResult, u as MentionRange, v as MessageDirection, N as NotifyScope, O as OAuthExchangeResult, w as PalbeAnalytics, x as PalbeAuth, y as PalbeCalls, P as PalbeConfig, z as PalbeFlags, B as PalbeMessaging, D as PalbeOAuthConfig, E as PalbeRealtime, G as PresenceState, H as RealtimeChannel, R as RealtimeConnectionState, I as RealtimeHandler, a as RealtimePayload, J as RealtimeStatus, K as RealtimeStatusSnapshot, L as RealtimeSubscription, Q as ResolvedMention, S as ResolvedReply, T as SentReceipt, U as UnreadView, V as Unsubscribe } from './analytics-facade-BOxQ8IP2.cjs';
2
2
  export { B as BackendError, a as BackendErrorKind, F as FieldError, i as isBackendError } from './errors-fDoNdTrJ.cjs';
3
- export { C as CallOptions, P as PB, U as UploadOptions, a as UploadProgress, p as pb } from './pb-DDM_mCQB.cjs';
3
+ export { C as CallOptions, P as PB, U as UploadOptions, a as UploadProgress, p as pb } from './pb-B3h3NIPE.cjs';
4
4
  export { P as PersistedSession, S as SessionStorageAdapter, l as localStorageSessionStorage, m as memorySessionStorage } from './storage-BPaeSG8K.cjs';
5
- export { F as FlagValue } from './pooled-flags-Bwq4usn0.js';
5
+ export { F as FlagValue } from './pooled-flags-4GtDtsiu.js';
6
6
  import 'livekit-client';
7
7
 
8
8
  /* tslint:disable */
@@ -207,6 +207,6 @@ interface MlsGlue {
207
207
  */
208
208
  declare function initMls(): Promise<MlsGlue>;
209
209
 
210
- declare const VERSION = "2.0.0";
210
+ declare const VERSION = "3.0.0";
211
211
 
212
212
  export { VERSION, initMls };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { f as AnalyticsProperties, g as AuthChangeEvent, h as AuthState, i as AuthSuccess, A as AuthUser, j as Call, k as CallChangeCallback, l as CallParticipant, m as CallState, C as Chat, n as ChatBackend, o as ChatDraft, p as ChatKind, b as ChatMember, c as ChatMessage, q as ChatMessageKind, r as ChatRole, s as ChatState, t as CommsPrefs, F as FlagsView, M as MagicLinkResult, u as MentionRange, v as MessageDirection, N as NotifyScope, O as OAuthExchangeResult, w as PalbeAnalytics, x as PalbeAuth, y as PalbeCalls, P as PalbeConfig, z as PalbeFlags, B as PalbeMessaging, D as PalbeOAuthConfig, E as PalbeRealtime, G as PresenceState, H as RealtimeChannel, R as RealtimeConnectionState, I as RealtimeHandler, a as RealtimePayload, J as RealtimeStatus, K as RealtimeStatusSnapshot, L as RealtimeSubscription, Q as ResolvedMention, S as ResolvedReply, T as SentReceipt, U as UnreadView, V as Unsubscribe } from './analytics-facade-DMtGDGfd.js';
1
+ export { f as AnalyticsProperties, g as AuthChangeEvent, h as AuthState, i as AuthSuccess, A as AuthUser, j as Call, k as CallChangeCallback, l as CallParticipant, m as CallState, C as Chat, n as ChatBackend, o as ChatDraft, p as ChatKind, b as ChatMember, c as ChatMessage, q as ChatMessageKind, r as ChatRole, s as ChatState, t as CommsPrefs, F as FlagsView, M as MagicLinkResult, u as MentionRange, v as MessageDirection, N as NotifyScope, O as OAuthExchangeResult, w as PalbeAnalytics, x as PalbeAuth, y as PalbeCalls, P as PalbeConfig, z as PalbeFlags, B as PalbeMessaging, D as PalbeOAuthConfig, E as PalbeRealtime, G as PresenceState, H as RealtimeChannel, R as RealtimeConnectionState, I as RealtimeHandler, a as RealtimePayload, J as RealtimeStatus, K as RealtimeStatusSnapshot, L as RealtimeSubscription, Q as ResolvedMention, S as ResolvedReply, T as SentReceipt, U as UnreadView, V as Unsubscribe } from './analytics-facade-yfMJ69vw.js';
2
2
  export { B as BackendError, a as BackendErrorKind, F as FieldError, i as isBackendError } from './errors-fDoNdTrJ.js';
3
- export { C as CallOptions, P as PB, U as UploadOptions, a as UploadProgress, p as pb } from './pb-CvpcQero.js';
3
+ export { C as CallOptions, P as PB, U as UploadOptions, a as UploadProgress, p as pb } from './pb-QRISxPd1.js';
4
4
  export { P as PersistedSession, S as SessionStorageAdapter, l as localStorageSessionStorage, m as memorySessionStorage } from './storage-BPaeSG8K.js';
5
- export { F as FlagValue } from './pooled-flags-Bwq4usn0.js';
5
+ export { F as FlagValue } from './pooled-flags-4GtDtsiu.js';
6
6
  import 'livekit-client';
7
7
 
8
8
  /* tslint:disable */
@@ -207,6 +207,6 @@ interface MlsGlue {
207
207
  */
208
208
  declare function initMls(): Promise<MlsGlue>;
209
209
 
210
- declare const VERSION = "2.0.0";
210
+ declare const VERSION = "3.0.0";
211
211
 
212
212
  export { VERSION, initMls };
package/dist/index.js CHANGED
@@ -13,8 +13,8 @@ import {
13
13
  localStorageSessionStorage,
14
14
  memorySessionStorage,
15
15
  pb
16
- } from "./chunk-V6VTX65P.js";
17
- import "./chunk-PZ5AY32C.js";
16
+ } from "./chunk-3HVTEZ7N.js";
17
+ import "./chunk-S7NAY3MW.js";
18
18
  export {
19
19
  BackendError,
20
20
  PalbeAnalytics,
package/dist/internal.cjs CHANGED
@@ -45,18 +45,9 @@ var PalbaseError = class extends Error {
45
45
  }
46
46
  };
47
47
  var PALBASE_DEFAULT_HOST = "api.palbase.studio";
48
- var REF_LEN = 8;
49
- var BASE62_RE = /^[0-9A-Za-z]+$/;
50
- function parseProjectRef(apiKey) {
51
- if (apiKey.length < 13) return null;
52
- if (!apiKey.startsWith("pb_")) return null;
53
- if (apiKey[11] !== "_") return null;
54
- const ref = apiKey.slice(3, 11);
55
- if (ref.length !== REF_LEN) return null;
56
- if (!BASE62_RE.test(ref)) return null;
57
- const scope = apiKey[12];
58
- if (scope !== "c") return null;
59
- return ref;
48
+ var API_KEY_RE = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;
49
+ function parseEnvironmentRef(apiKey) {
50
+ return API_KEY_RE.exec(apiKey)?.[1] ?? null;
60
51
  }
61
52
  var MAX_RETRIES = 3;
62
53
  var INITIAL_BACKOFF_MS = 200;
@@ -86,8 +77,7 @@ var HttpClient = class _HttpClient {
86
77
  * with the parent at runtime — later changes on the parent propagate to
87
78
  * the scope and vice versa.
88
79
  *
89
- * Typical use: tagging admin calls with `x-palbase-project: <ref>` so the
90
- * gateway can route them to the correct project's data plane.
80
+ * Typical use: adding an Environment-routing header for an admin call.
91
81
  */
92
82
  withHeaders(extra) {
93
83
  const mergedHeaders = { ...this.options?.headers ?? {}, ...extra };
@@ -128,10 +118,10 @@ var HttpClient = class _HttpClient {
128
118
  if (this.options?.url) {
129
119
  return this.options.url;
130
120
  }
131
- if (this.apiKey && parseProjectRef(this.apiKey) === null) {
121
+ if (this.apiKey && parseEnvironmentRef(this.apiKey) === null) {
132
122
  throw new PalbaseError(
133
123
  "invalid_api_key",
134
- 'Invalid API key format. Expected pb_{ref}_{scope}{random}. For dev/staging pass `url: "https://api.dev.palbase.studio"` via options.',
124
+ 'Invalid API key format. Expected pb_{environment_ref}_c{20_base62_chars}. For dev/staging pass `url: "https://api.dev.palbase.studio"` via options.',
135
125
  0
136
126
  );
137
127
  }
@@ -144,10 +134,6 @@ var HttpClient = class _HttpClient {
144
134
  const effectiveKey = this.apiKey;
145
135
  if (effectiveKey) {
146
136
  headers["apikey"] = effectiveKey;
147
- const ref = parseProjectRef(effectiveKey);
148
- if (ref) {
149
- headers["X-Project-Ref"] = ref;
150
- }
151
137
  }
152
138
  const token = this.tokenManager?.getAccessToken();
153
139
  if (token) {
@@ -1153,13 +1139,6 @@ var AuthClient = class {
1153
1139
  }
1154
1140
  };
1155
1141
 
1156
- // src/api-key.ts
1157
- var API_KEY_RE = /^pb_([^_]+)_[cs][A-Za-z0-9]{20}$/;
1158
- function endpointRefFromApiKey(apiKey) {
1159
- const m = API_KEY_RE.exec(apiKey);
1160
- return m ? m[1] ?? "" : "";
1161
- }
1162
-
1163
1142
  // src/analytics-facade.ts
1164
1143
  var EVENT_NAME_RE = /^[a-zA-Z$][a-zA-Z0-9_.:$-]{0,63}$/;
1165
1144
  var FLUSH_AT = 20;
@@ -1217,7 +1196,7 @@ var AnalyticsState = class {
1217
1196
  idKey;
1218
1197
  optOutKey;
1219
1198
  constructor(rt) {
1220
- const ref = endpointRefFromApiKey(rt.config.apiKey);
1199
+ const ref = rt.config.environmentRef;
1221
1200
  this.idKey = ref ? `palbe.analytics.id.${ref}` : "palbe.analytics.id";
1222
1201
  this.optOutKey = ref ? `palbe.analytics.optout.${ref}` : "palbe.analytics.optout";
1223
1202
  rt.auth.onAuthEvent((event) => {
@@ -1431,6 +1410,13 @@ var PalbeAnalytics = class {
1431
1410
  }
1432
1411
  };
1433
1412
 
1413
+ // src/api-key.ts
1414
+ var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;
1415
+ function environmentRefFromPublishableApiKey(apiKey) {
1416
+ const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);
1417
+ return match ? match[1] ?? "" : "";
1418
+ }
1419
+
1434
1420
  // src/auth-wire.ts
1435
1421
  function asWireAuthResult(raw) {
1436
1422
  if (typeof raw !== "object" || raw === null) return null;
@@ -1992,6 +1978,19 @@ var PalbeCalls = class {
1992
1978
 
1993
1979
  // ../modules/flags/dist/index.js
1994
1980
  var FLAG_NAME_RE = /^[a-zA-Z0-9_-]+$/;
1981
+ function flagEnabled(value) {
1982
+ if (typeof value === "boolean") return value;
1983
+ return value != null && value !== 0 && value !== "";
1984
+ }
1985
+ function flagVariant(value) {
1986
+ return typeof value === "string" ? { name: value } : null;
1987
+ }
1988
+ function mapResponse(res, fn) {
1989
+ if (res.error || res.data == null) {
1990
+ return { ...res, data: null };
1991
+ }
1992
+ return { ...res, data: fn(res.data) };
1993
+ }
1995
1994
  var FlagsClient = class {
1996
1995
  httpClient;
1997
1996
  getCurrentUserId;
@@ -2011,10 +2010,11 @@ var FlagsClient = class {
2011
2010
  `Invalid flag name: "${flagName}". Flag names must match ${FLAG_NAME_RE.source}`
2012
2011
  );
2013
2012
  }
2014
- const params = this.buildContextParams(context);
2015
- const query = params.toString();
2016
- const path = `/v1/flags/${flagName}/enabled${query ? `?${query}` : ""}`;
2017
- return this.httpClient.request("GET", path);
2013
+ const res = await this.httpClient.request(
2014
+ "GET",
2015
+ this.mergedPath(context)
2016
+ );
2017
+ return mapResponse(res, (snap) => flagEnabled(snap.values?.[flagName]));
2018
2018
  }
2019
2019
  async getVariant(flagName, context) {
2020
2020
  if (!FLAG_NAME_RE.test(flagName)) {
@@ -2022,16 +2022,29 @@ var FlagsClient = class {
2022
2022
  `Invalid flag name: "${flagName}". Flag names must match ${FLAG_NAME_RE.source}`
2023
2023
  );
2024
2024
  }
2025
- const params = this.buildContextParams(context);
2026
- const query = params.toString();
2027
- const path = `/v1/flags/${flagName}/variant${query ? `?${query}` : ""}`;
2028
- return this.httpClient.request("GET", path);
2025
+ const res = await this.httpClient.request(
2026
+ "GET",
2027
+ this.mergedPath(context)
2028
+ );
2029
+ if (res.error || res.data == null) {
2030
+ return { ...res, data: null };
2031
+ }
2032
+ return { ...res, data: flagVariant(res.data.values?.[flagName]) };
2029
2033
  }
2030
2034
  async getAll(context) {
2031
- const params = this.buildContextParams(context);
2032
- const query = params.toString();
2033
- const path = `/v1/flags${query ? `?${query}` : ""}`;
2034
- return this.httpClient.request("GET", path);
2035
+ const res = await this.httpClient.request(
2036
+ "GET",
2037
+ this.mergedPath(context)
2038
+ );
2039
+ return mapResponse(res, (snap) => {
2040
+ const values = snap.values ?? {};
2041
+ return Object.keys(values).map((name) => {
2042
+ const value = values[name];
2043
+ const flag = { name, enabled: flagEnabled(value) };
2044
+ if (typeof value === "string") flag.variant = { name: value };
2045
+ return flag;
2046
+ });
2047
+ });
2035
2048
  }
2036
2049
  /**
2037
2050
  * Cold-start read: the full merged flag set for the current auth identity.
@@ -2130,15 +2143,16 @@ var FlagsClient = class {
2130
2143
  }
2131
2144
  };
2132
2145
  }
2133
- buildContextParams(context) {
2134
- const params = new URLSearchParams();
2135
- if (context?.userId) {
2136
- params.set("userId", context.userId);
2137
- }
2138
- if (context?.properties) {
2139
- params.set("properties", JSON.stringify(context.properties));
2140
- }
2141
- return params;
2146
+ /**
2147
+ * Resolve the merged-read path for a context. With `context.userId` present the
2148
+ * read targets that specific user's merged view (`/v1/user-flags/users/{id}`, a
2149
+ * privileged cross-user read); otherwise the current auth user's view
2150
+ * (`/v1/user-flags`). `context.properties` has no server-side targeting support
2151
+ * in the user-flags module and is ignored.
2152
+ */
2153
+ mergedPath(context) {
2154
+ const uid = context?.userId;
2155
+ return uid ? `/v1/user-flags/users/${encodeURIComponent(uid)}` : "/v1/user-flags";
2142
2156
  }
2143
2157
  };
2144
2158
  var DEFAULT_POLL_MS = 3e4;
@@ -2543,7 +2557,7 @@ var PalbeFlags = class {
2543
2557
  constructor(rt) {
2544
2558
  this.transport = new FlagsClient(rt.http);
2545
2559
  const browser = typeof document !== "undefined";
2546
- const ref = endpointRefFromApiKey(rt.config.apiKey);
2560
+ const ref = rt.config.environmentRef;
2547
2561
  const options = {
2548
2562
  auth: palbeAuthAdapter(rt.auth),
2549
2563
  ...ref ? { storageKey: `palbe.flags.${ref}` } : {},
@@ -2600,7 +2614,7 @@ var PalbeFlags = class {
2600
2614
  *
2601
2615
  * DEVIATION from iOS sync-cache parity: the platform does not propagate
2602
2616
  * variant metadata into the user-flags snapshot/delta cache, so this is an
2603
- * ASYNC transport read (`GET /v1/flags/{key}/variant`), not a cache lookup.
2617
+ * ASYNC transport read (derived from `GET /v1/user-flags`), not a cache lookup.
2604
2618
  */
2605
2619
  async getVariant(key) {
2606
2620
  let res;
@@ -8283,7 +8297,7 @@ var AnonTokenProvider = class {
8283
8297
  }
8284
8298
  /**
8285
8299
  * Raw fetch, deliberately NOT through HttpClient/palbeRequest: the mint
8286
- * must carry the project apikey and NEVER a Bearer (iOS keeps
8300
+ * must carry the Environment API key and NEVER a Bearer (iOS keeps
8287
8301
  * `/auth/anonymous` on the unauthenticated-path list), and HttpClient's
8288
8302
  * pre-flight would try to refresh a stale session before an anon mint —
8289
8303
  * exactly the entanglement this provider exists to avoid.
@@ -8940,10 +8954,25 @@ function defaultSessionStorage(key) {
8940
8954
  }
8941
8955
 
8942
8956
  // src/version.ts
8943
- var VERSION = "2.0.0";
8957
+ var VERSION = "3.0.0";
8944
8958
 
8945
8959
  // src/runtime.ts
8946
8960
  function buildRuntime(config) {
8961
+ const keyEnvironmentRef = environmentRefFromPublishableApiKey(config.apiKey);
8962
+ if (keyEnvironmentRef === "") {
8963
+ throw new Error("PalbeConfig.apiKey does not contain a valid publishable Environment identity");
8964
+ } else if (config.environmentRef !== keyEnvironmentRef) {
8965
+ throw new Error("PalbeConfig.environmentRef must match the Environment identity in apiKey");
8966
+ }
8967
+ let runtimeURL;
8968
+ try {
8969
+ runtimeURL = new URL(config.url);
8970
+ } catch {
8971
+ throw new Error("PalbeConfig.url must be a valid URL");
8972
+ }
8973
+ if (runtimeURL.hostname.endsWith(".palbase.studio") && runtimeURL.hostname.split(".")[0] !== config.environmentRef) {
8974
+ throw new Error("PalbeConfig.url must match environmentRef for palbase.studio");
8975
+ }
8947
8976
  const http = new HttpClient(config.apiKey, {
8948
8977
  url: config.url,
8949
8978
  headers: { "X-Client-Info": `palbe-web/${VERSION}`, ...config.headers }
@@ -8952,7 +8981,7 @@ function buildRuntime(config) {
8952
8981
  const tokenManager = new TokenManager();
8953
8982
  http.tokenManager = tokenManager;
8954
8983
  const authClient = new AuthClient(http, tokenManager);
8955
- const ref = endpointRefFromApiKey(config.apiKey);
8984
+ const ref = config.environmentRef;
8956
8985
  const storage = config.storage ?? defaultSessionStorage(ref ? `palbe.session.${ref}` : void 0);
8957
8986
  const persisted = storage.load();
8958
8987
  if (persisted) {