@palbase/web 3.0.0 → 4.0.1

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 (45) hide show
  1. package/dist/_mls-wasm.cjs +32 -0
  2. package/dist/_mls-wasm.cjs.map +1 -0
  3. package/dist/_mls-wasm.js +11 -0
  4. package/dist/_mls-wasm.js.map +1 -0
  5. package/dist/{analytics-facade-BOxQ8IP2.d.cts → analytics-facade-DwOtlXPP.d.cts} +5 -87
  6. package/dist/{analytics-facade-yfMJ69vw.d.ts → analytics-facade-Nk6J9Ncm.d.ts} +5 -87
  7. package/dist/{chunk-S7NAY3MW.js → chunk-NXEPAEF5.js} +1 -8
  8. package/dist/{chunk-S7NAY3MW.js.map → chunk-NXEPAEF5.js.map} +1 -1
  9. package/dist/chunk-PZ5AY32C.js +10 -0
  10. package/dist/chunk-PZ5AY32C.js.map +1 -0
  11. package/dist/{chunk-3HVTEZ7N.js → chunk-TGDS6VMT.js} +51 -36
  12. package/dist/chunk-TGDS6VMT.js.map +1 -0
  13. package/dist/gen/cli.js +2 -1
  14. package/dist/gen/cli.js.map +1 -1
  15. package/dist/index.cjs +59 -37
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +3 -4
  18. package/dist/index.d.ts +3 -4
  19. package/dist/index.js +3 -2
  20. package/dist/internal.cjs +56 -34
  21. package/dist/internal.cjs.map +1 -1
  22. package/dist/internal.d.cts +4 -16
  23. package/dist/internal.d.ts +4 -16
  24. package/dist/internal.js +3 -2
  25. package/dist/next/client.cjs +56 -34
  26. package/dist/next/client.cjs.map +1 -1
  27. package/dist/next/client.js +3 -2
  28. package/dist/next/client.js.map +1 -1
  29. package/dist/next/index.cjs +46 -34
  30. package/dist/next/index.cjs.map +1 -1
  31. package/dist/next/index.d.cts +2 -3
  32. package/dist/next/index.d.ts +2 -3
  33. package/dist/next/index.js +3 -2
  34. package/dist/next/index.js.map +1 -1
  35. package/dist/{pb-B3h3NIPE.d.cts → pb-C9v5dEO6.d.cts} +1 -1
  36. package/dist/{pb-QRISxPd1.d.ts → pb-FG_nV7NR.d.ts} +1 -1
  37. package/dist/react/index.cjs +1 -1
  38. package/dist/react/index.cjs.map +1 -1
  39. package/dist/react/index.d.cts +1 -2
  40. package/dist/react/index.d.ts +1 -2
  41. package/dist/react/index.js +3 -2
  42. package/dist/react/index.js.map +1 -1
  43. package/package.json +9 -2
  44. package/dist/chunk-3HVTEZ7N.js.map +0 -1
  45. package/dist/pkg/palbe_mls_bg.wasm +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/messaging/wasm/asset.ts"],"sourcesContent":["import encodedWasm from './pkg/palbe_mls_bg.wasm';\n\n// Built as a private package-import target. Keeping the bytes in their own\n// lazily imported JavaScript module lets browser bundlers carry/split the MLS\n// engine without a public-path convention, while Node ESM and CJS resolve the\n// exact same package-owned bytes.\nexport default encodedWasm;\n"],"mappings":";;;;;;AAMA,IAAO,gBAAQ;","names":[]}
@@ -1,4 +1,3 @@
1
- import { Room, ExternalE2EEKeyProvider } from 'livekit-client';
2
1
  import { S as SessionStorageAdapter } from './storage-BPaeSG8K.cjs';
3
2
  import { F } from './pooled-flags-4GtDtsiu.js';
4
3
 
@@ -533,12 +532,9 @@ declare class Call {
533
532
  private readonly _listeners;
534
533
  private readonly _room;
535
534
  private readonly _keyProvider;
536
- /** @internal — obtain via PalbeCalls.start() / .accept() */
537
- constructor(callId: string, room: Room, keyProvider: ExternalE2EEKeyProvider);
538
535
  get state(): CallState;
539
536
  /** Snapshot of current remote participants (does NOT include the local participant). */
540
537
  get participants(): readonly CallParticipant[];
541
- get localParticipant(): Room['localParticipant'];
542
538
  /**
543
539
  * Subscribe to call changes (state + participant updates).
544
540
  * Returns an `Unsubscribe` function — matches the SDK's flags/auth pattern.
@@ -551,7 +547,7 @@ declare class Call {
551
547
  /**
552
548
  * Set a raw frame encryption key (ArrayBuffer) for this call.
553
549
  * Design seam for SP-1.x web-MLS: call this with the MLS exporter secret
554
- * to enable frame-level E2EE via ExternalE2EEKeyProvider.
550
+ * to enable frame-level E2EE via the media engine's external key provider.
555
551
  *
556
552
  * NOTE: The room must have been opened with `e2ee` options for this to take
557
553
  * effect. Currently calls connect WITHOUT e2ee — see module docstring.
@@ -559,13 +555,13 @@ declare class Call {
559
555
  * TODO(SP-1-web): wire this to MLS-derived key on session join.
560
556
  */
561
557
  setMediaKey(key: ArrayBuffer): Promise<void>;
562
- /** Leave the call and disconnect from the LiveKit room. */
558
+ /** Leave the call and disconnect from the media room. */
563
559
  leave(): Promise<void>;
564
560
  private _setState;
565
561
  private _emit;
566
562
  private _upsertParticipant;
567
563
  private _attachTrack;
568
- private _wireRoomEvents;
564
+ private _wireMediaEvents;
569
565
  }
570
566
  declare class PalbeCalls {
571
567
  private readonly rt;
@@ -575,9 +571,9 @@ declare class PalbeCalls {
575
571
  *
576
572
  * @param groupId - Messaging group display-id (`grp_<uuidv7>`)
577
573
  * @param media - Which media tracks to publish (default: audio + video)
578
- * @returns A `Call` in `connecting` state; transitions to `active` once LiveKit connects.
574
+ * @returns A `Call` in `connecting` state; transitions to `active` once the media room connects.
579
575
  *
580
- * @throws BackendError('network', { code: 'call_service_unavailable' }) if LiveKit SFU is down (503)
576
+ * @throws BackendError('network', { code: 'call_service_unavailable' }) if the SFU is down (503)
581
577
  * @throws BackendError('forbidden', { code: 'not_group_member' }) if the caller is not a member (403)
582
578
  * @throws BackendError('conflict', { code: 'call_room_full' }) if the room is full (409)
583
579
  */
@@ -920,19 +916,6 @@ interface MentionRange {
920
916
  length: number;
921
917
  mentionedUserId: string;
922
918
  }
923
- interface ReactionPayload {
924
- targetClientMsgId: string;
925
- emoji: string;
926
- op: 'add' | 'remove';
927
- }
928
- interface EditPayload {
929
- targetClientMsgId: string;
930
- newText: string;
931
- }
932
- interface DeletePayload {
933
- targetClientMsgId: string;
934
- scope: string;
935
- }
936
919
  /** Per-message TTL spec (decoded). senderSendTs present iff start === 'send'. */
937
920
  interface ExpirySpec {
938
921
  v: number;
@@ -941,51 +924,6 @@ interface ExpirySpec {
941
924
  senderSendTs: number | null;
942
925
  }
943
926
 
944
- /** A decoded incoming message handed to chat listeners. */
945
- interface IncomingMessage {
946
- kind: 'application' | 'commit' | 'proposal' | 'welcome';
947
- group: MessagingGroup;
948
- text: string | null;
949
- senderDeviceId: string | null;
950
- epoch: number;
951
- serverSeq: number;
952
- receivedAt: Date;
953
- /** The client-minted idempotency id from the decoded envelope (empty string for legacy/system). */
954
- clientMsgId: string;
955
- /** The decoded reply reference, if present in the envelope. */
956
- replyRef: ReplyRef | null;
957
- /**
958
- * The decoded envelope discriminator (`'text'`/`'reaction'`/`'media'`/…).
959
- * Defaults to `'text'` at every existing call site — only the reaction branch
960
- * sets `'reaction'`, so the Chat can route a reaction into its fold instead of
961
- * appending a visible bubble. Optional for forward-compat with old emitters.
962
- */
963
- envelopeType?: string;
964
- /** The decoded reaction payload, present only when `envelopeType === 'reaction'`. */
965
- reaction?: ReactionPayload | null;
966
- /** The decoded edit payload, present only when `envelopeType === 'edit'`. Lets
967
- * the Chat route an edit into its EditFold instead of appending a visible bubble. */
968
- edit?: EditPayload | null;
969
- /** The decoded delete payload, present only when `envelopeType === 'delete'`. Lets
970
- * the Chat route a delete-for-everyone tombstone into its DeleteFold instead of
971
- * appending a visible bubble. */
972
- delete?: DeletePayload | null;
973
- /** The decoded mention ranges (raw, un-normalized). Present on a `'text'` bubble
974
- * with `body_ranges` OR on an `'edit'` (the edit's replacement ranges). The Chat
975
- * normalizes + resolves roster names → `ChatMessage.mentions` (mentions T6). */
976
- bodyRanges?: MentionRange[] | null;
977
- /** The decoded `timer_set` payload, present only when `envelopeType === 'timer_set'`
978
- * (disappearing T10). Lets the Chat route a chat-default timer into its TimerFold
979
- * instead of appending a visible bubble. */
980
- timer?: {
981
- ttlSeconds: number | null;
982
- start: 'send' | 'read';
983
- } | null;
984
- /** The decoded per-message TTL spec, present only on a `'text'` bubble that carried an
985
- * `expiry` (disappearing T10). Lets the Chat arm the message's purge on first display. */
986
- expiry?: ExpirySpec | null;
987
- }
988
-
989
927
  /** The intended participants of a draft chat (held until the first send). */
990
928
  interface ChatDraft {
991
929
  mode: {
@@ -1163,16 +1101,6 @@ declare class Chat {
1163
1101
  * the SDK guarantees the DECISION, not the buzz. Mirrors iOS `Chat.onMentionElevation`.
1164
1102
  */
1165
1103
  onMentionElevation?: (message: ChatMessage) => void;
1166
- /** @internal — obtain via pb.messaging.directChat / groupChat / chat(id). */
1167
- constructor(args: {
1168
- group: MessagingGroup;
1169
- kind: ChatKind;
1170
- backend: ChatBackend;
1171
- } | {
1172
- draft: ChatDraft;
1173
- kind: ChatKind;
1174
- backend: ChatBackend;
1175
- });
1176
1104
  /** Subscribe to any change in this chat (messages/members/typing/state). */
1177
1105
  onChange(cb: () => void): Unsubscribe$1;
1178
1106
  private emit;
@@ -1212,8 +1140,6 @@ declare class Chat {
1212
1140
  private loadElevated;
1213
1141
  private hydrateHistory;
1214
1142
  private mergeHistory;
1215
- /** @internal — called by the backend's live subscription. */
1216
- ingestLive(incoming: IncomingMessage): Promise<void>;
1217
1143
  /** Normalize a decoded `IncomingMessage.expiry` / `StoredMessage.expiry` into the
1218
1144
  * `ExpirySpec` the arm path consumes (or null when absent). */
1219
1145
  private toExpirySpec;
@@ -1311,8 +1237,6 @@ declare class Chat {
1311
1237
  * history fold) is preserved. PRESERVES reactions + replyTo.
1312
1238
  */
1313
1239
  private applyEditOverlay;
1314
- /** @internal — called by the backend's conv subscription. */
1315
- applyConv(event: string, payload: Record<string, unknown>): void;
1316
1240
  private kindOf;
1317
1241
  private internalKey;
1318
1242
  private publicId;
@@ -1628,8 +1552,6 @@ declare class RealtimeChannel {
1628
1552
  /** The app-defined channel name (bare sub-topic, no "realtime:" prefix). */
1629
1553
  readonly name: string;
1630
1554
  private readonly owner;
1631
- /** @internal — obtain channels via `pb.realtime.channel(name)`. */
1632
- constructor(name: string, owner: PalbeRealtime);
1633
1555
  /**
1634
1556
  * Subscribe `handler` to `event` on this channel. Fire-and-forget: the
1635
1557
  * join rides the shared socket asynchronously. Hold the returned
@@ -1665,10 +1587,6 @@ declare class PalbeRealtime {
1665
1587
  destroy(): void;
1666
1588
  /** The observable connection status. Safe to read anywhere (reports `idle` until a socket exists). */
1667
1589
  get status(): RealtimeStatus;
1668
- /** @internal */
1669
- subscribe(topic: string, event: string, handler: RealtimeHandler): RealtimeSubscription;
1670
- /** @internal */
1671
- send(topic: string, event: string, payload: RealtimePayload): void;
1672
1590
  /** Lazily build + start the shared socket on first subscription/send. */
1673
1591
  private ensureSocket;
1674
1592
  private route;
@@ -1,4 +1,3 @@
1
- import { Room, ExternalE2EEKeyProvider } from 'livekit-client';
2
1
  import { S as SessionStorageAdapter } from './storage-BPaeSG8K.js';
3
2
  import { F } from './pooled-flags-4GtDtsiu.js';
4
3
 
@@ -533,12 +532,9 @@ declare class Call {
533
532
  private readonly _listeners;
534
533
  private readonly _room;
535
534
  private readonly _keyProvider;
536
- /** @internal — obtain via PalbeCalls.start() / .accept() */
537
- constructor(callId: string, room: Room, keyProvider: ExternalE2EEKeyProvider);
538
535
  get state(): CallState;
539
536
  /** Snapshot of current remote participants (does NOT include the local participant). */
540
537
  get participants(): readonly CallParticipant[];
541
- get localParticipant(): Room['localParticipant'];
542
538
  /**
543
539
  * Subscribe to call changes (state + participant updates).
544
540
  * Returns an `Unsubscribe` function — matches the SDK's flags/auth pattern.
@@ -551,7 +547,7 @@ declare class Call {
551
547
  /**
552
548
  * Set a raw frame encryption key (ArrayBuffer) for this call.
553
549
  * Design seam for SP-1.x web-MLS: call this with the MLS exporter secret
554
- * to enable frame-level E2EE via ExternalE2EEKeyProvider.
550
+ * to enable frame-level E2EE via the media engine's external key provider.
555
551
  *
556
552
  * NOTE: The room must have been opened with `e2ee` options for this to take
557
553
  * effect. Currently calls connect WITHOUT e2ee — see module docstring.
@@ -559,13 +555,13 @@ declare class Call {
559
555
  * TODO(SP-1-web): wire this to MLS-derived key on session join.
560
556
  */
561
557
  setMediaKey(key: ArrayBuffer): Promise<void>;
562
- /** Leave the call and disconnect from the LiveKit room. */
558
+ /** Leave the call and disconnect from the media room. */
563
559
  leave(): Promise<void>;
564
560
  private _setState;
565
561
  private _emit;
566
562
  private _upsertParticipant;
567
563
  private _attachTrack;
568
- private _wireRoomEvents;
564
+ private _wireMediaEvents;
569
565
  }
570
566
  declare class PalbeCalls {
571
567
  private readonly rt;
@@ -575,9 +571,9 @@ declare class PalbeCalls {
575
571
  *
576
572
  * @param groupId - Messaging group display-id (`grp_<uuidv7>`)
577
573
  * @param media - Which media tracks to publish (default: audio + video)
578
- * @returns A `Call` in `connecting` state; transitions to `active` once LiveKit connects.
574
+ * @returns A `Call` in `connecting` state; transitions to `active` once the media room connects.
579
575
  *
580
- * @throws BackendError('network', { code: 'call_service_unavailable' }) if LiveKit SFU is down (503)
576
+ * @throws BackendError('network', { code: 'call_service_unavailable' }) if the SFU is down (503)
581
577
  * @throws BackendError('forbidden', { code: 'not_group_member' }) if the caller is not a member (403)
582
578
  * @throws BackendError('conflict', { code: 'call_room_full' }) if the room is full (409)
583
579
  */
@@ -920,19 +916,6 @@ interface MentionRange {
920
916
  length: number;
921
917
  mentionedUserId: string;
922
918
  }
923
- interface ReactionPayload {
924
- targetClientMsgId: string;
925
- emoji: string;
926
- op: 'add' | 'remove';
927
- }
928
- interface EditPayload {
929
- targetClientMsgId: string;
930
- newText: string;
931
- }
932
- interface DeletePayload {
933
- targetClientMsgId: string;
934
- scope: string;
935
- }
936
919
  /** Per-message TTL spec (decoded). senderSendTs present iff start === 'send'. */
937
920
  interface ExpirySpec {
938
921
  v: number;
@@ -941,51 +924,6 @@ interface ExpirySpec {
941
924
  senderSendTs: number | null;
942
925
  }
943
926
 
944
- /** A decoded incoming message handed to chat listeners. */
945
- interface IncomingMessage {
946
- kind: 'application' | 'commit' | 'proposal' | 'welcome';
947
- group: MessagingGroup;
948
- text: string | null;
949
- senderDeviceId: string | null;
950
- epoch: number;
951
- serverSeq: number;
952
- receivedAt: Date;
953
- /** The client-minted idempotency id from the decoded envelope (empty string for legacy/system). */
954
- clientMsgId: string;
955
- /** The decoded reply reference, if present in the envelope. */
956
- replyRef: ReplyRef | null;
957
- /**
958
- * The decoded envelope discriminator (`'text'`/`'reaction'`/`'media'`/…).
959
- * Defaults to `'text'` at every existing call site — only the reaction branch
960
- * sets `'reaction'`, so the Chat can route a reaction into its fold instead of
961
- * appending a visible bubble. Optional for forward-compat with old emitters.
962
- */
963
- envelopeType?: string;
964
- /** The decoded reaction payload, present only when `envelopeType === 'reaction'`. */
965
- reaction?: ReactionPayload | null;
966
- /** The decoded edit payload, present only when `envelopeType === 'edit'`. Lets
967
- * the Chat route an edit into its EditFold instead of appending a visible bubble. */
968
- edit?: EditPayload | null;
969
- /** The decoded delete payload, present only when `envelopeType === 'delete'`. Lets
970
- * the Chat route a delete-for-everyone tombstone into its DeleteFold instead of
971
- * appending a visible bubble. */
972
- delete?: DeletePayload | null;
973
- /** The decoded mention ranges (raw, un-normalized). Present on a `'text'` bubble
974
- * with `body_ranges` OR on an `'edit'` (the edit's replacement ranges). The Chat
975
- * normalizes + resolves roster names → `ChatMessage.mentions` (mentions T6). */
976
- bodyRanges?: MentionRange[] | null;
977
- /** The decoded `timer_set` payload, present only when `envelopeType === 'timer_set'`
978
- * (disappearing T10). Lets the Chat route a chat-default timer into its TimerFold
979
- * instead of appending a visible bubble. */
980
- timer?: {
981
- ttlSeconds: number | null;
982
- start: 'send' | 'read';
983
- } | null;
984
- /** The decoded per-message TTL spec, present only on a `'text'` bubble that carried an
985
- * `expiry` (disappearing T10). Lets the Chat arm the message's purge on first display. */
986
- expiry?: ExpirySpec | null;
987
- }
988
-
989
927
  /** The intended participants of a draft chat (held until the first send). */
990
928
  interface ChatDraft {
991
929
  mode: {
@@ -1163,16 +1101,6 @@ declare class Chat {
1163
1101
  * the SDK guarantees the DECISION, not the buzz. Mirrors iOS `Chat.onMentionElevation`.
1164
1102
  */
1165
1103
  onMentionElevation?: (message: ChatMessage) => void;
1166
- /** @internal — obtain via pb.messaging.directChat / groupChat / chat(id). */
1167
- constructor(args: {
1168
- group: MessagingGroup;
1169
- kind: ChatKind;
1170
- backend: ChatBackend;
1171
- } | {
1172
- draft: ChatDraft;
1173
- kind: ChatKind;
1174
- backend: ChatBackend;
1175
- });
1176
1104
  /** Subscribe to any change in this chat (messages/members/typing/state). */
1177
1105
  onChange(cb: () => void): Unsubscribe$1;
1178
1106
  private emit;
@@ -1212,8 +1140,6 @@ declare class Chat {
1212
1140
  private loadElevated;
1213
1141
  private hydrateHistory;
1214
1142
  private mergeHistory;
1215
- /** @internal — called by the backend's live subscription. */
1216
- ingestLive(incoming: IncomingMessage): Promise<void>;
1217
1143
  /** Normalize a decoded `IncomingMessage.expiry` / `StoredMessage.expiry` into the
1218
1144
  * `ExpirySpec` the arm path consumes (or null when absent). */
1219
1145
  private toExpirySpec;
@@ -1311,8 +1237,6 @@ declare class Chat {
1311
1237
  * history fold) is preserved. PRESERVES reactions + replyTo.
1312
1238
  */
1313
1239
  private applyEditOverlay;
1314
- /** @internal — called by the backend's conv subscription. */
1315
- applyConv(event: string, payload: Record<string, unknown>): void;
1316
1240
  private kindOf;
1317
1241
  private internalKey;
1318
1242
  private publicId;
@@ -1628,8 +1552,6 @@ declare class RealtimeChannel {
1628
1552
  /** The app-defined channel name (bare sub-topic, no "realtime:" prefix). */
1629
1553
  readonly name: string;
1630
1554
  private readonly owner;
1631
- /** @internal — obtain channels via `pb.realtime.channel(name)`. */
1632
- constructor(name: string, owner: PalbeRealtime);
1633
1555
  /**
1634
1556
  * Subscribe `handler` to `event` on this channel. Fire-and-forget: the
1635
1557
  * join rides the shared socket asynchronously. Hold the returned
@@ -1665,10 +1587,6 @@ declare class PalbeRealtime {
1665
1587
  destroy(): void;
1666
1588
  /** The observable connection status. Safe to read anywhere (reports `idle` until a socket exists). */
1667
1589
  get status(): RealtimeStatus;
1668
- /** @internal */
1669
- subscribe(topic: string, event: string, handler: RealtimeHandler): RealtimeSubscription;
1670
- /** @internal */
1671
- send(topic: string, event: string, payload: RealtimePayload): void;
1672
1590
  /** Lazily build + start the shared socket on first subscription/send. */
1673
1591
  private ensureSocket;
1674
1592
  private route;
@@ -1,9 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
6
-
7
1
  // src/api-key.ts
8
2
  var API_KEY_RE = /^pb_([a-z0-9]+)_[cs][A-Za-z0-9]{20}$/;
9
3
  var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;
@@ -17,8 +11,7 @@ function environmentRefFromPublishableApiKey(apiKey) {
17
11
  }
18
12
 
19
13
  export {
20
- __export,
21
14
  environmentRefFromApiKey,
22
15
  environmentRefFromPublishableApiKey
23
16
  };
24
- //# sourceMappingURL=chunk-S7NAY3MW.js.map
17
+ //# sourceMappingURL=chunk-NXEPAEF5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api-key.ts"],"sourcesContent":["/**\n * `pb_<environmentRef>_<scope><random>` → environmentRef ('' if malformed).\n * Utility for callers that only have a raw key. App-bound runtime storage and\n * palbe/next cookie naming use the explicit `PalbeConfig.environmentRef` emitted\n * by `palbe-gen`.\n *\n * The key is shape-validated (prefix `pb`, non-empty environmentRef, and a\n * `<scope><20-base62-random>` secret segment where scope ∈ {c,s}) before a ref\n * is returned. A structurally-invalid key returns '' so session storage stays\n * UNSCOPED rather than getting bound to a partially-parsed ref — a loose parse\n * (e.g. `pb_victim_cXX`) must not scope persisted sessions to `victim` and\n * hydrate a session belonging to a different, real key. The backend remains the\n * authority that rejects a bad key on the first request; this keeps the client's\n * local session-storage scoping honest. (Audit finding apikey-ref-mismatch.)\n */\nconst API_KEY_RE = /^pb_([a-z0-9]+)_[cs][A-Za-z0-9]{20}$/;\nconst PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;\n\nexport function environmentRefFromApiKey(apiKey: string): string {\n const m = API_KEY_RE.exec(apiKey);\n return m ? (m[1] ?? '') : '';\n}\n\n/** Internal app-runtime parser: browser config accepts publishable keys only. */\nexport function environmentRefFromPublishableApiKey(apiKey: string): string {\n const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);\n return match ? (match[1] ?? '') : '';\n}\n"],"mappings":";;;;;;;AAeA,IAAM,aAAa;AACnB,IAAM,yBAAyB;AAExB,SAAS,yBAAyB,QAAwB;AAC/D,QAAM,IAAI,WAAW,KAAK,MAAM;AAChC,SAAO,IAAK,EAAE,CAAC,KAAK,KAAM;AAC5B;AAGO,SAAS,oCAAoC,QAAwB;AAC1E,QAAM,QAAQ,uBAAuB,KAAK,MAAM;AAChD,SAAO,QAAS,MAAM,CAAC,KAAK,KAAM;AACpC;","names":[]}
1
+ {"version":3,"sources":["../src/api-key.ts"],"sourcesContent":["/**\n * `pb_<environmentRef>_<scope><random>` → environmentRef ('' if malformed).\n * Utility for callers that only have a raw key. App-bound runtime storage and\n * palbe/next cookie naming use the explicit `PalbeConfig.environmentRef` emitted\n * by `palbe-gen`.\n *\n * The key is shape-validated (prefix `pb`, non-empty environmentRef, and a\n * `<scope><20-base62-random>` secret segment where scope ∈ {c,s}) before a ref\n * is returned. A structurally-invalid key returns '' so session storage stays\n * UNSCOPED rather than getting bound to a partially-parsed ref — a loose parse\n * (e.g. `pb_victim_cXX`) must not scope persisted sessions to `victim` and\n * hydrate a session belonging to a different, real key. The backend remains the\n * authority that rejects a bad key on the first request; this keeps the client's\n * local session-storage scoping honest. (Audit finding apikey-ref-mismatch.)\n */\nconst API_KEY_RE = /^pb_([a-z0-9]+)_[cs][A-Za-z0-9]{20}$/;\nconst PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]+)_c[A-Za-z0-9]{20}$/;\n\nexport function environmentRefFromApiKey(apiKey: string): string {\n const m = API_KEY_RE.exec(apiKey);\n return m ? (m[1] ?? '') : '';\n}\n\n/** Internal app-runtime parser: browser config accepts publishable keys only. */\nexport function environmentRefFromPublishableApiKey(apiKey: string): string {\n const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);\n return match ? (match[1] ?? '') : '';\n}\n"],"mappings":";AAeA,IAAM,aAAa;AACnB,IAAM,yBAAyB;AAExB,SAAS,yBAAyB,QAAwB;AAC/D,QAAM,IAAI,WAAW,KAAK,MAAM;AAChC,SAAO,IAAK,EAAE,CAAC,KAAK,KAAM;AAC5B;AAGO,SAAS,oCAAoC,QAAwB;AAC1E,QAAM,QAAQ,uBAAuB,KAAK,MAAM;AAChD,SAAO,QAAS,MAAM,CAAC,KAAK,KAAM;AACpC;","names":[]}
@@ -0,0 +1,10 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export {
8
+ __export
9
+ };
10
+ //# sourceMappingURL=chunk-PZ5AY32C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,7 +1,9 @@
1
1
  import {
2
- __export,
3
2
  environmentRefFromPublishableApiKey
4
- } from "./chunk-S7NAY3MW.js";
3
+ } from "./chunk-NXEPAEF5.js";
4
+ import {
5
+ __export
6
+ } from "./chunk-PZ5AY32C.js";
5
7
 
6
8
  // ../core/dist/index.js
7
9
  var CACHE_TTL_MS = 5 * 60 * 1e3;
@@ -1735,19 +1737,29 @@ import {
1735
1737
  RoomEvent,
1736
1738
  Track
1737
1739
  } from "livekit-client";
1738
- var Call = class {
1740
+ var Call = class _Call {
1739
1741
  id;
1740
1742
  _state = "connecting";
1741
1743
  _participants = /* @__PURE__ */ new Map();
1742
1744
  _listeners = /* @__PURE__ */ new Set();
1743
1745
  _room;
1744
1746
  _keyProvider;
1745
- /** @internal obtain via PalbeCalls.start() / .accept() */
1747
+ // PRIVATE constructor + `@internal` factory: the media-engine types (`Room`,
1748
+ // `ExternalE2EEKeyProvider`) appear ONLY on a private constructor and an
1749
+ // `@internal` static factory, both of which `stripInternal` (set in this
1750
+ // package's tsconfig) removes from the emitted public `.d.ts`. So no engine type
1751
+ // ever reaches the public API surface — the same "no engine type in the public
1752
+ // interface" contract the iOS SDK enforces. Consumers obtain a `Call` only
1753
+ // through `pb.calls.start()` / `.accept()`.
1746
1754
  constructor(callId, room, keyProvider) {
1747
1755
  this.id = callId;
1748
1756
  this._room = room;
1749
1757
  this._keyProvider = keyProvider;
1750
- this._wireRoomEvents();
1758
+ this._wireMediaEvents();
1759
+ }
1760
+ /** @internal — facade-only factory; stripped from the public `.d.ts`. */
1761
+ static _create(callId, room, keyProvider) {
1762
+ return new _Call(callId, room, keyProvider);
1751
1763
  }
1752
1764
  // ─── State ──────────────────────────────────────────────────────────────
1753
1765
  get state() {
@@ -1757,9 +1769,9 @@ var Call = class {
1757
1769
  get participants() {
1758
1770
  return Array.from(this._participants.values());
1759
1771
  }
1760
- get localParticipant() {
1761
- return this._room.localParticipant;
1762
- }
1772
+ // (No `localParticipant` accessor: it would return a raw media-engine participant
1773
+ // object and leak the engine type onto the public API. Local mic/camera control is
1774
+ // exposed engine-agnostically via `mute()` / `setCamera()` below.)
1763
1775
  // ─── Subscribe ──────────────────────────────────────────────────────────
1764
1776
  /**
1765
1777
  * Subscribe to call changes (state + participant updates).
@@ -1783,7 +1795,7 @@ var Call = class {
1783
1795
  /**
1784
1796
  * Set a raw frame encryption key (ArrayBuffer) for this call.
1785
1797
  * Design seam for SP-1.x web-MLS: call this with the MLS exporter secret
1786
- * to enable frame-level E2EE via ExternalE2EEKeyProvider.
1798
+ * to enable frame-level E2EE via the media engine's external key provider.
1787
1799
  *
1788
1800
  * NOTE: The room must have been opened with `e2ee` options for this to take
1789
1801
  * effect. Currently calls connect WITHOUT e2ee — see module docstring.
@@ -1793,7 +1805,7 @@ var Call = class {
1793
1805
  async setMediaKey(key) {
1794
1806
  await this._keyProvider.setKey(key);
1795
1807
  }
1796
- /** Leave the call and disconnect from the LiveKit room. */
1808
+ /** Leave the call and disconnect from the media room. */
1797
1809
  async leave() {
1798
1810
  await this._room.disconnect();
1799
1811
  this._setState("ended");
@@ -1835,7 +1847,7 @@ var Call = class {
1835
1847
  }
1836
1848
  this._emit();
1837
1849
  }
1838
- _wireRoomEvents() {
1850
+ _wireMediaEvents() {
1839
1851
  this._room.on(RoomEvent.Connected, () => {
1840
1852
  this._setState("active");
1841
1853
  }).on(
@@ -1876,9 +1888,9 @@ var PalbeCalls = class {
1876
1888
  *
1877
1889
  * @param groupId - Messaging group display-id (`grp_<uuidv7>`)
1878
1890
  * @param media - Which media tracks to publish (default: audio + video)
1879
- * @returns A `Call` in `connecting` state; transitions to `active` once LiveKit connects.
1891
+ * @returns A `Call` in `connecting` state; transitions to `active` once the media room connects.
1880
1892
  *
1881
- * @throws BackendError('network', { code: 'call_service_unavailable' }) if LiveKit SFU is down (503)
1893
+ * @throws BackendError('network', { code: 'call_service_unavailable' }) if the SFU is down (503)
1882
1894
  * @throws BackendError('forbidden', { code: 'not_group_member' }) if the caller is not a member (403)
1883
1895
  * @throws BackendError('conflict', { code: 'call_room_full' }) if the room is full (409)
1884
1896
  */
@@ -1935,7 +1947,7 @@ var PalbeCalls = class {
1935
1947
  adaptiveStream: true,
1936
1948
  dynacast: true
1937
1949
  });
1938
- const call = new Call(callId, room, keyProvider);
1950
+ const call = Call._create(callId, room, keyProvider);
1939
1951
  await room.connect(edgeUrl, token);
1940
1952
  if (media.includes("audio")) {
1941
1953
  await room.localParticipant.setMicrophoneEnabled(true);
@@ -6422,26 +6434,25 @@ var GLUE_MODULE = "./palbe_mls_bg.js";
6422
6434
  var SNIPPET_MODULE = "./snippets/mls-rs-core-f99cdecbb456b09c/inline0.js";
6423
6435
  var inflight = null;
6424
6436
  var ready = null;
6425
- async function loadWasmModule() {
6426
- const wasmUrl = new URL("./pkg/palbe_mls_bg.wasm", import.meta.url);
6427
- if (wasmUrl.protocol === "file:") {
6428
- const fsSpecifier = ["node", "fs/promises"].join(":");
6429
- const { readFile } = await import(
6430
- /* webpackIgnore: true */
6431
- fsSpecifier
6432
- );
6433
- const bytes = await readFile(wasmUrl);
6434
- return WebAssembly.compile(bytes);
6437
+ function decodeBase64(encoded) {
6438
+ if (typeof encoded !== "string" || encoded.length === 0 || typeof globalThis.atob !== "function") {
6439
+ throw new Error("palbe-mls WASM asset is invalid");
6435
6440
  }
6436
- const response = await fetch(wasmUrl);
6437
- if (typeof WebAssembly.compileStreaming === "function") {
6438
- try {
6439
- return await WebAssembly.compileStreaming(Promise.resolve(response));
6440
- } catch {
6441
- }
6441
+ let binary;
6442
+ try {
6443
+ binary = globalThis.atob(encoded);
6444
+ } catch {
6445
+ throw new Error("palbe-mls WASM asset is invalid");
6446
+ }
6447
+ const bytes = new Uint8Array(binary.length);
6448
+ for (let index = 0; index < binary.length; index += 1) {
6449
+ bytes[index] = binary.charCodeAt(index);
6442
6450
  }
6443
- const buffer = await response.arrayBuffer();
6444
- return WebAssembly.compile(buffer);
6451
+ return bytes.buffer;
6452
+ }
6453
+ async function loadWasmModule() {
6454
+ const asset = await import("#palbase-mls-wasm");
6455
+ return WebAssembly.compile(decodeBase64(asset.default));
6445
6456
  }
6446
6457
  function buildImports() {
6447
6458
  return {
@@ -6452,7 +6463,7 @@ function buildImports() {
6452
6463
  function initMls() {
6453
6464
  if (ready) return Promise.resolve(ready);
6454
6465
  if (inflight) return inflight;
6455
- inflight = (async () => {
6466
+ const attempt = (async () => {
6456
6467
  const module2 = await loadWasmModule();
6457
6468
  const instance = await WebAssembly.instantiate(module2, buildImports());
6458
6469
  const setWasm = __wbg_set_wasm;
@@ -6471,7 +6482,11 @@ function initMls() {
6471
6482
  ready = g;
6472
6483
  return g;
6473
6484
  })();
6474
- return inflight;
6485
+ inflight = attempt;
6486
+ void attempt.catch(() => {
6487
+ if (inflight === attempt) inflight = null;
6488
+ });
6489
+ return attempt;
6475
6490
  }
6476
6491
  function requireMls() {
6477
6492
  if (!ready) {
@@ -8924,7 +8939,7 @@ function defaultSessionStorage(key) {
8924
8939
  }
8925
8940
 
8926
8941
  // src/version.ts
8927
- var VERSION = "3.0.0";
8942
+ var VERSION = "4.0.1";
8928
8943
 
8929
8944
  // src/runtime.ts
8930
8945
  function buildRuntime(config) {
@@ -9351,4 +9366,4 @@ export {
9351
9366
  pb,
9352
9367
  createBoundClient
9353
9368
  };
9354
- //# sourceMappingURL=chunk-3HVTEZ7N.js.map
9369
+ //# sourceMappingURL=chunk-TGDS6VMT.js.map