@lumencast/runtime 0.8.0 → 0.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 (99) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/animate/keyframes.js +8 -1
  3. package/dist/animate/keyframes.js.map +1 -1
  4. package/dist/app.d.ts +9 -1
  5. package/dist/app.d.ts.map +1 -1
  6. package/dist/app.js +4 -1
  7. package/dist/app.js.map +1 -1
  8. package/dist/{broadcast-Gcd-dmC7.js → broadcast-L5wm2I6J.js} +3 -3
  9. package/dist/{broadcast-Gcd-dmC7.js.map → broadcast-L5wm2I6J.js.map} +1 -1
  10. package/dist/{control-C5TfClga.js → control-eEUG7unp.js} +4 -4
  11. package/dist/{control-C5TfClga.js.map → control-eEUG7unp.js.map} +1 -1
  12. package/dist/index-Clrya_9l.js +1281 -0
  13. package/dist/index-Clrya_9l.js.map +1 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.html +1 -1
  17. package/dist/index.js +11 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/lumencast.js +17 -12
  20. package/dist/mount.d.ts.map +1 -1
  21. package/dist/mount.js +16 -0
  22. package/dist/mount.js.map +1 -1
  23. package/dist/overlay/runtime-context.d.ts +21 -0
  24. package/dist/overlay/runtime-context.d.ts.map +1 -1
  25. package/dist/overlay/runtime-context.js +8 -0
  26. package/dist/overlay/runtime-context.js.map +1 -1
  27. package/dist/render/bundle.d.ts +1 -1
  28. package/dist/render/bundle.d.ts.map +1 -1
  29. package/dist/render/bundle.js +4 -0
  30. package/dist/render/bundle.js.map +1 -1
  31. package/dist/render/keyframe-player.d.ts.map +1 -1
  32. package/dist/render/keyframe-player.js +15 -1
  33. package/dist/render/keyframe-player.js.map +1 -1
  34. package/dist/render/primitives/capture.d.ts +49 -0
  35. package/dist/render/primitives/capture.d.ts.map +1 -0
  36. package/dist/render/primitives/capture.js +203 -0
  37. package/dist/render/primitives/capture.js.map +1 -0
  38. package/dist/render/primitives/index.d.ts.map +1 -1
  39. package/dist/render/primitives/index.js +7 -0
  40. package/dist/render/primitives/index.js.map +1 -1
  41. package/dist/render/primitives/live-peer-video.d.ts +27 -0
  42. package/dist/render/primitives/live-peer-video.d.ts.map +1 -0
  43. package/dist/render/primitives/live-peer-video.js +64 -0
  44. package/dist/render/primitives/live-peer-video.js.map +1 -0
  45. package/dist/render/primitives/media.d.ts +37 -12
  46. package/dist/render/primitives/media.d.ts.map +1 -1
  47. package/dist/render/primitives/media.js +43 -17
  48. package/dist/render/primitives/media.js.map +1 -1
  49. package/dist/render/primitives/meet-peer.d.ts +31 -0
  50. package/dist/render/primitives/meet-peer.d.ts.map +1 -0
  51. package/dist/render/primitives/meet-peer.js +46 -0
  52. package/dist/render/primitives/meet-peer.js.map +1 -0
  53. package/dist/render/prop-allowlist.d.ts.map +1 -1
  54. package/dist/render/prop-allowlist.js +32 -1
  55. package/dist/render/prop-allowlist.js.map +1 -1
  56. package/dist/render/tree.js +42 -8
  57. package/dist/render/tree.js.map +1 -1
  58. package/dist/{status-pill-BaLQoIDl.js → status-pill-elORkMrh.js} +2 -2
  59. package/dist/{status-pill-BaLQoIDl.js.map → status-pill-elORkMrh.js.map} +1 -1
  60. package/dist/{test-CA30C2By.js → test-7q_KJkdX.js} +4 -4
  61. package/dist/{test-CA30C2By.js.map → test-7q_KJkdX.js.map} +1 -1
  62. package/dist/{tree-1coZ32nd.js → tree-BMxx5170.js} +773 -604
  63. package/dist/tree-BMxx5170.js.map +1 -0
  64. package/dist/types.d.ts +23 -0
  65. package/dist/types.d.ts.map +1 -1
  66. package/dist/webrtc/index.d.ts +76 -0
  67. package/dist/webrtc/index.d.ts.map +1 -0
  68. package/dist/webrtc/index.js +180 -0
  69. package/dist/webrtc/index.js.map +1 -0
  70. package/dist/webrtc/meet-viewer.d.ts +139 -0
  71. package/dist/webrtc/meet-viewer.d.ts.map +1 -0
  72. package/dist/webrtc/meet-viewer.js +379 -0
  73. package/dist/webrtc/meet-viewer.js.map +1 -0
  74. package/dist/webrtc/peer-stream-registry.d.ts +21 -0
  75. package/dist/webrtc/peer-stream-registry.d.ts.map +1 -0
  76. package/dist/webrtc/peer-stream-registry.js +77 -0
  77. package/dist/webrtc/peer-stream-registry.js.map +1 -0
  78. package/package.json +4 -4
  79. package/src/animate/keyframes.ts +8 -1
  80. package/src/app.tsx +14 -0
  81. package/src/index.ts +40 -0
  82. package/src/mount.ts +16 -0
  83. package/src/overlay/runtime-context.tsx +24 -0
  84. package/src/render/bundle.ts +19 -1
  85. package/src/render/keyframe-player.tsx +14 -1
  86. package/src/render/primitives/capture.tsx +255 -0
  87. package/src/render/primitives/index.ts +7 -0
  88. package/src/render/primitives/live-peer-video.tsx +90 -0
  89. package/src/render/primitives/media.tsx +66 -17
  90. package/src/render/primitives/meet-peer.tsx +57 -0
  91. package/src/render/prop-allowlist.ts +32 -1
  92. package/src/render/tree.tsx +44 -8
  93. package/src/types.ts +23 -0
  94. package/src/webrtc/index.ts +252 -0
  95. package/src/webrtc/meet-viewer.ts +497 -0
  96. package/src/webrtc/peer-stream-registry.ts +93 -0
  97. package/dist/index-N-VqrIxN.js +0 -885
  98. package/dist/index-N-VqrIxN.js.map +0 -1
  99. package/dist/tree-1coZ32nd.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { ErrorCode } from "@lumencast/protocol";
2
+ import type { ResolveCaptureDevice } from "./render/primitives/capture";
3
+ import type { ResolvePeerStream, SubscribePeerStream } from "./render/primitives/media";
2
4
  export type LumencastMode = "broadcast" | "control" | "test";
3
5
  export type LumencastStatus = "disconnected" | "connecting" | "live";
4
6
  export interface LumencastTokenProvider {
@@ -53,6 +55,27 @@ export interface MountOptions {
53
55
  * logs — `broadcast` builds stay console-silent. When omitted, the
54
56
  * runtime falls back to a DEV-only console.warn. */
55
57
  onDiagnostic?: (diagnostic: LumencastDiagnostic) => void;
58
+ /** ADR 004 §A1.3 — host resolver for the `x-zab.capture` primitive's ACQUIRE
59
+ * mode. Given the LOGICAL `(deviceRef, sourceKind)` from the bundle, return
60
+ * `{ deviceId }` to pin a physical device, or `null` for the host's default
61
+ * device. The runtime passes `deviceId` only as a live `getUserMedia`
62
+ * constraint — it NEVER enters the bundle or the content hash. Omit it and
63
+ * ACQUIRE uses the default device ("the cam traverses"), never throwing.
64
+ * Only consulted on a capture-capable host (e.g. the Electron preview
65
+ * webview) ; ignored on-air (CEF/Pulsar render the placeholder). */
66
+ resolveCaptureDevice?: ResolveCaptureDevice;
67
+ /** ADR 006 #4 — host resolver for the `media` primitive's LIVE mode. Given a
68
+ * LOGICAL `peerLabel` (a `meet.peer.peer_label` from the scene), return the
69
+ * live `MediaStream` of that peer, or `null` when it is not connected yet.
70
+ * Supplied by the WebRTC viewer (issue #3) ; the stream is rendered in
71
+ * `<video>.srcObject` and NEVER enters the bundle or the content hash. Omit
72
+ * it and a live `media` node renders a stream-less box, never throwing. */
73
+ resolvePeerStream?: ResolvePeerStream;
74
+ /** ADR 006 #3 — reactive variant of `resolvePeerStream` : the viewer pushes a
75
+ * peer's stream on connect and `null` on leave, so a LIVE `media` node
76
+ * re-renders when its peer joins mid-show. `createPeerViewer()` returns one.
77
+ * Preferred over `resolvePeerStream` when both are supplied. */
78
+ subscribePeerStream?: SubscribePeerStream;
56
79
  }
57
80
  export interface LumencastHandle {
58
81
  /** Tear down the WS, unmount the React tree, release timers. Idempotent. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EACA,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,eAAe,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;+BAE+B;AAC/B,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IACrE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C;;;yDAGqD;IACrD,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAExF,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,sBAAsB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EACA,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,WAAW,GACX,mBAAmB,GACnB,eAAe,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;+BAE+B;AAC/B,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IACrE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C;;;yDAGqD;IACrD,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACzD;;;;;;;yEAOqE;IACrE,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C;;;;;gFAK4E;IAC5E,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;qEAGiE;IACjE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { MeetViewer, type MeetViewerOptions } from "./meet-viewer.js";
2
+ import { type PeerStreamListener, type PeerStreamRegistry } from "./peer-stream-registry.js";
3
+ export { MeetViewer, type MeetViewerOptions, type MeetViewerDeps, type PeerInfo, type RemoteTrackEvent, } from "./meet-viewer.js";
4
+ export { createPeerStreamRegistry, type PeerStreamRegistry, type PeerStreamListener, } from "./peer-stream-registry.js";
5
+ export interface PeerViewer {
6
+ /** Join the room(s) (viewer role, no capture). */
7
+ join: () => Promise<void>;
8
+ /** Leave + tear down all peer connections (the track owner releases here). */
9
+ leave: () => void;
10
+ /** #4 contract — pass to `mount({ resolvePeerStream })`. Synchronous. */
11
+ resolvePeerStream: (peerLabel: string) => MediaStream | null;
12
+ /** Push channel for the LIVE primitive to re-render on connect/disconnect. */
13
+ subscribePeerStream: (peerLabel: string, listener: PeerStreamListener) => () => void;
14
+ /** The underlying registry, for advanced hosts. */
15
+ registry: PeerStreamRegistry;
16
+ /** Single-room only — the underlying mesh, for diagnostics. Absent in the
17
+ * multi-room viewer (it owns N meshes). */
18
+ viewer?: MeetViewer;
19
+ }
20
+ /** Feed a (possibly shared) registry from ONE viewer's lifecycle. A label is
21
+ * owned by the FIRST room that connects it (`label-collision` policy) : `claim`
22
+ * decides whether this viewer may publish/withdraw a given label, so a second
23
+ * room carrying the same `peer_label` never clobbers the first. Returns the
24
+ * viewer + a `dispose` that closes the mesh and releases this viewer's labels. */
25
+ /** Normalise a peer name / peer_label into the SAME key both sides agree on.
26
+ * The publisher announces a FREE name on the mesh (e.g. "Publisher 366"), but
27
+ * the scene's `peer_label` is slugified at LSML export (from-scene → "publisher
28
+ * _366", per source-node.ts `slugifyToLabel`). Strict `peerName === peer_label`
29
+ * therefore never matches. Applying the SAME slug to BOTH the indexing side
30
+ * (peerName) and the resolution side (peer_label) makes the map work regardless
31
+ * of format (a raw label and its slug collapse to the same key). Mirrors
32
+ * Prism `slugifyToLabel`. */
33
+ export declare function labelKey(s: string): string;
34
+ /** Build a viewer + registry for a SINGLE room and expose the #4 resolver.
35
+ * (Back-compat surface — `createMultiRoomPeerViewer` is the final model.) */
36
+ export declare function createPeerViewer(options: MeetViewerOptions): PeerViewer;
37
+ /** A single room's connection params (one mesh per entry). */
38
+ export type RoomOptions = Omit<MeetViewerOptions, "name"> & {
39
+ /** This viewer's announce name on the mesh. Defaults to "solar-viewer". */
40
+ name?: string;
41
+ };
42
+ export interface MultiRoomPeerViewerOptions {
43
+ rooms: RoomOptions[];
44
+ /** Shared deps (WS/RTCPeerConnection/MediaStream) applied to every room when a
45
+ * room entry does not override them — used to test without a browser stack. */
46
+ deps?: MeetViewerOptions["deps"];
47
+ }
48
+ export interface MultiRoomPeerViewer extends PeerViewer {
49
+ /** Reconcile the live room set : open meshes for new rooms, close meshes for
50
+ * removed ones (matched by `roomId`). Best-effort ; idempotent for an
51
+ * unchanged set. Newly opened rooms are joined immediately. */
52
+ setRooms: (rooms: RoomOptions[]) => Promise<void>;
53
+ }
54
+ /** The FINAL viewer model : join N rooms, aggregate every peer into ONE shared
55
+ * registry keyed by `peer_label`. The `meet.peer` renderer resolves a label to
56
+ * its stream regardless of which room the peer published in.
57
+ *
58
+ * LABEL COLLISION (improbable at the POC) : FIRST-CONNECTED-WINS. The room that
59
+ * first connects a `peer_label` owns it ; a second room carrying the same label
60
+ * is ignored until the owner releases it (on the owner's `peer-left`). This is
61
+ * deterministic and never flips a live source under the compositor.
62
+ *
63
+ * LIFECYCLE : one mesh per room ; `leave()` closes all. `setRooms()` reconciles
64
+ * on re-arm (close removed rooms, open new ones), matched by `roomId`. */
65
+ export declare function createMultiRoomPeerViewer(options: MultiRoomPeerViewerOptions): MultiRoomPeerViewer;
66
+ /** The shape the Prism host injects on `window.__ZAB_PEER_VIEWER__`. The FINAL
67
+ * model is the multi-room `{ rooms: [...] }` ; the legacy single-room shape is
68
+ * still accepted for back-compat (treated as a one-room array). */
69
+ export type PeerViewerInjection = MultiRoomPeerViewerOptions | (Omit<MeetViewerOptions, "name"> & {
70
+ name?: string;
71
+ });
72
+ /** Normalise either injection shape into a multi-room viewer. forge-prism passes
73
+ * `window.__ZAB_PEER_VIEWER__` straight through ; a bare single-room object is
74
+ * wrapped as `{ rooms: [it] }`. */
75
+ export declare function createPeerViewerFromInjection(injection: PeerViewerInjection): MultiRoomPeerViewer;
76
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yEAAyE;IACzE,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC;IAC7D,8EAA8E;IAC9E,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAAC;IACrF,mDAAmD;IACnD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B;gDAC4C;IAC5C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;mFAImF;AACnF;;;;;;;8BAO8B;AAC9B,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1C;AA+BD;8EAC8E;AAC9E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAevE;AAED,8DAA8D;AAC9D,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG;IAC1D,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB;oFACgF;IAChF,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,mBAAoB,SAAQ,UAAU;IACrD;;oEAEgE;IAChE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED;;;;;;;;;;2EAU2E;AAC3E,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA8ErB;AAED;;oEAEoE;AACpE,MAAM,MAAM,mBAAmB,GAC3B,0BAA0B,GAC1B,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1D;;oCAEoC;AACpC,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,mBAAmB,GAAG,mBAAmB,CAYjG"}
@@ -0,0 +1,180 @@
1
+ // WebRTC viewer — public surface (ADR 006 §3.3, issue #3).
2
+ //
3
+ // `createPeerViewer` wires a `MeetViewer` (mesh, viewer role) to a
4
+ // `PeerStreamRegistry` and returns the `resolvePeerStream` / `subscribePeerStream`
5
+ // the `media` primitive's LIVE mode (#4) consumes via `MountOptions`. This is
6
+ // the #3↔#4 bridge : the viewer receives peers, the registry maps
7
+ // `peer_label → MediaStream`, the primitive renders it in `<video srcObject>`.
8
+ //
9
+ // MULTI-ROOM (final model) : `createMultiRoomPeerViewer({ rooms: [...] })` joins
10
+ // EVERY room with its own mesh and feeds ONE shared registry, so the `meet.peer`
11
+ // renderer resolves a `peer_label` to its stream whatever room it came from.
12
+ import { MeetViewer } from "./meet-viewer.js";
13
+ import { createPeerStreamRegistry, } from "./peer-stream-registry.js";
14
+ export { MeetViewer, } from "./meet-viewer.js";
15
+ export { createPeerStreamRegistry, } from "./peer-stream-registry.js";
16
+ /** Feed a (possibly shared) registry from ONE viewer's lifecycle. A label is
17
+ * owned by the FIRST room that connects it (`label-collision` policy) : `claim`
18
+ * decides whether this viewer may publish/withdraw a given label, so a second
19
+ * room carrying the same `peer_label` never clobbers the first. Returns the
20
+ * viewer + a `dispose` that closes the mesh and releases this viewer's labels. */
21
+ /** Normalise a peer name / peer_label into the SAME key both sides agree on.
22
+ * The publisher announces a FREE name on the mesh (e.g. "Publisher 366"), but
23
+ * the scene's `peer_label` is slugified at LSML export (from-scene → "publisher
24
+ * _366", per source-node.ts `slugifyToLabel`). Strict `peerName === peer_label`
25
+ * therefore never matches. Applying the SAME slug to BOTH the indexing side
26
+ * (peerName) and the resolution side (peer_label) makes the map work regardless
27
+ * of format (a raw label and its slug collapse to the same key). Mirrors
28
+ * Prism `slugifyToLabel`. */
29
+ export function labelKey(s) {
30
+ return s
31
+ .toLowerCase()
32
+ .replace(/[^a-z0-9_-]+/g, "_")
33
+ .replace(/^[_-]+|[_-]+$/g, "");
34
+ }
35
+ function wireViewer(viewer, registry, claim) {
36
+ // Index the registry by the NORMALISED label (slug of peerName), so it matches
37
+ // the scene node's slugified `peer_label`. Never the opaque `peerId`.
38
+ viewer.on("remote-track", (e) => {
39
+ const key = labelKey(e.peerName);
40
+ if (claim.acquire(key, viewer))
41
+ registry.set(key, e.stream);
42
+ });
43
+ viewer.on("peer-left", (e) => {
44
+ const key = labelKey(e.peerName);
45
+ if (claim.acquire(key, viewer)) {
46
+ registry.remove(key);
47
+ claim.release(key, viewer);
48
+ }
49
+ });
50
+ }
51
+ /** Single-room ownership : trivially, this lone viewer owns every label. */
52
+ const SOLE_OWNER = {
53
+ acquire: () => true,
54
+ release: () => { },
55
+ };
56
+ /** Build a viewer + registry for a SINGLE room and expose the #4 resolver.
57
+ * (Back-compat surface — `createMultiRoomPeerViewer` is the final model.) */
58
+ export function createPeerViewer(options) {
59
+ const registry = createPeerStreamRegistry();
60
+ const viewer = new MeetViewer(options);
61
+ wireViewer(viewer, registry, SOLE_OWNER);
62
+ return {
63
+ join: () => viewer.join(),
64
+ leave: () => {
65
+ viewer.leave();
66
+ registry.clear();
67
+ },
68
+ resolvePeerStream: (peerLabel) => registry.resolve(labelKey(peerLabel)),
69
+ subscribePeerStream: (peerLabel, listener) => registry.subscribe(labelKey(peerLabel), listener),
70
+ registry,
71
+ viewer,
72
+ };
73
+ }
74
+ /** The FINAL viewer model : join N rooms, aggregate every peer into ONE shared
75
+ * registry keyed by `peer_label`. The `meet.peer` renderer resolves a label to
76
+ * its stream regardless of which room the peer published in.
77
+ *
78
+ * LABEL COLLISION (improbable at the POC) : FIRST-CONNECTED-WINS. The room that
79
+ * first connects a `peer_label` owns it ; a second room carrying the same label
80
+ * is ignored until the owner releases it (on the owner's `peer-left`). This is
81
+ * deterministic and never flips a live source under the compositor.
82
+ *
83
+ * LIFECYCLE : one mesh per room ; `leave()` closes all. `setRooms()` reconciles
84
+ * on re-arm (close removed rooms, open new ones), matched by `roomId`. */
85
+ export function createMultiRoomPeerViewer(options) {
86
+ const registry = createPeerStreamRegistry();
87
+ // roomId → { viewer, joined }
88
+ const meshes = new Map();
89
+ // peer_label → owning viewer (first-connected-wins).
90
+ const owners = new Map();
91
+ const claim = {
92
+ acquire: (label, viewer) => {
93
+ const owner = owners.get(label);
94
+ if (owner === undefined) {
95
+ owners.set(label, viewer);
96
+ return true;
97
+ }
98
+ return owner === viewer; // only the owning room may publish/withdraw
99
+ },
100
+ release: (label, viewer) => {
101
+ if (owners.get(label) === viewer)
102
+ owners.delete(label);
103
+ },
104
+ };
105
+ function openRoom(room) {
106
+ if (meshes.has(room.roomId))
107
+ return; // idempotent
108
+ const viewer = new MeetViewer({
109
+ name: room.name ?? "solar-viewer",
110
+ ...room,
111
+ ...(options.deps !== undefined && room.deps === undefined ? { deps: options.deps } : {}),
112
+ });
113
+ wireViewer(viewer, registry, claim);
114
+ meshes.set(room.roomId, { viewer });
115
+ }
116
+ function closeRoom(roomId) {
117
+ const mesh = meshes.get(roomId);
118
+ if (mesh === undefined)
119
+ return;
120
+ // Release every label this viewer owns BEFORE closing, so a surviving room
121
+ // can take over the label and the registry drops the gone stream.
122
+ for (const [label, owner] of [...owners.entries()]) {
123
+ if (owner === mesh.viewer) {
124
+ registry.remove(label);
125
+ owners.delete(label);
126
+ }
127
+ }
128
+ mesh.viewer.leave();
129
+ meshes.delete(roomId);
130
+ }
131
+ for (const room of options.rooms)
132
+ openRoom(room);
133
+ return {
134
+ join: async () => {
135
+ await Promise.all([...meshes.values()].map((m) => m.viewer.join()));
136
+ },
137
+ leave: () => {
138
+ for (const roomId of [...meshes.keys()])
139
+ closeRoom(roomId);
140
+ registry.clear();
141
+ },
142
+ setRooms: async (rooms) => {
143
+ const next = new Set(rooms.map((r) => r.roomId));
144
+ // Close rooms no longer present.
145
+ for (const roomId of [...meshes.keys()]) {
146
+ if (!next.has(roomId))
147
+ closeRoom(roomId);
148
+ }
149
+ // Open + join rooms newly added.
150
+ const added = [];
151
+ for (const room of rooms) {
152
+ if (!meshes.has(room.roomId)) {
153
+ openRoom(room);
154
+ const m = meshes.get(room.roomId);
155
+ if (m)
156
+ added.push(m.viewer);
157
+ }
158
+ }
159
+ await Promise.all(added.map((v) => v.join()));
160
+ },
161
+ resolvePeerStream: (peerLabel) => registry.resolve(labelKey(peerLabel)),
162
+ subscribePeerStream: (peerLabel, listener) => registry.subscribe(labelKey(peerLabel), listener),
163
+ registry,
164
+ };
165
+ }
166
+ /** Normalise either injection shape into a multi-room viewer. forge-prism passes
167
+ * `window.__ZAB_PEER_VIEWER__` straight through ; a bare single-room object is
168
+ * wrapped as `{ rooms: [it] }`. */
169
+ export function createPeerViewerFromInjection(injection) {
170
+ if ("rooms" in injection && Array.isArray(injection.rooms)) {
171
+ return createMultiRoomPeerViewer(injection);
172
+ }
173
+ // Legacy single-room shape → one-room array.
174
+ const { name, deps, ...room } = injection;
175
+ return createMultiRoomPeerViewer({
176
+ rooms: [{ ...room, ...(name !== undefined ? { name } : {}) }],
177
+ ...(deps !== undefined ? { deps } : {}),
178
+ });
179
+ }
180
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webrtc/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ export type PeerRole = "publisher" | "viewer";
2
+ export interface PeerInfo {
3
+ id: string;
4
+ /** The peer's join name — the STABLE `peer_label` (ZabCam contract #6). */
5
+ name: string;
6
+ role: PeerRole;
7
+ }
8
+ export type SignalPayload = {
9
+ kind: "sdp";
10
+ description: {
11
+ type: "offer" | "answer" | "pranswer" | "rollback";
12
+ sdp: string;
13
+ };
14
+ } | {
15
+ kind: "ice";
16
+ candidate: {
17
+ candidate: string;
18
+ sdpMid: string | null;
19
+ sdpMLineIndex: number | null;
20
+ usernameFragment?: string | null;
21
+ };
22
+ } | {
23
+ kind: "control";
24
+ event: "screen-start" | "screen-stop" | "mute" | "unmute";
25
+ };
26
+ export type ClientMessage = {
27
+ type: "join";
28
+ name: string;
29
+ role?: PeerRole;
30
+ } | {
31
+ type: "signal";
32
+ to: string;
33
+ payload: SignalPayload;
34
+ } | {
35
+ type: "leave";
36
+ };
37
+ export type ServerMessage = {
38
+ type: "joined";
39
+ peerId: string;
40
+ roomId: string;
41
+ role: PeerRole;
42
+ peers: PeerInfo[];
43
+ turn: {
44
+ urls: string[];
45
+ username: string;
46
+ credential: string;
47
+ ttl: number;
48
+ };
49
+ } | {
50
+ type: "peer-joined";
51
+ peer: PeerInfo;
52
+ } | {
53
+ type: "peer-left";
54
+ peerId: string;
55
+ } | {
56
+ type: "signal";
57
+ from: string;
58
+ payload: SignalPayload;
59
+ } | {
60
+ type: "error";
61
+ code: string;
62
+ message: string;
63
+ };
64
+ export interface RemoteTrackEvent {
65
+ peerId: string;
66
+ /** The peer's join name == its STABLE `peer_label` (Conduit invariant #6 :
67
+ * `peer_label == name == peerName`, strict string equality). This is the key
68
+ * a `meet.peer` LSML node's `peerLabel` resolves against — never `peerId`. */
69
+ peerName: string;
70
+ stream: MediaStream;
71
+ }
72
+ type EventMap = {
73
+ joined: {
74
+ peerId: string;
75
+ peers: PeerInfo[];
76
+ };
77
+ "peer-joined": PeerInfo;
78
+ "peer-left": {
79
+ peerId: string;
80
+ peerName: string;
81
+ };
82
+ "remote-track": RemoteTrackEvent;
83
+ "connection-state": {
84
+ peerId: string;
85
+ state: RTCPeerConnectionState;
86
+ };
87
+ error: {
88
+ code: string;
89
+ message: string;
90
+ };
91
+ close: {
92
+ code: number;
93
+ reason: string;
94
+ };
95
+ };
96
+ type Listener<K extends keyof EventMap> = (event: EventMap[K]) => void;
97
+ /** Minimal injectable factory for the WebSocket + RTCPeerConnection, so the
98
+ * viewer is testable without a real browser stack. Defaults to the globals. */
99
+ export interface MeetViewerDeps {
100
+ WebSocket: typeof WebSocket;
101
+ RTCPeerConnection: typeof RTCPeerConnection;
102
+ MediaStream: typeof MediaStream;
103
+ }
104
+ export interface MeetViewerOptions {
105
+ signalingUrl: string;
106
+ roomId: string;
107
+ /** Room/viewer token, sent as a query param to the signaling WS. */
108
+ token: string;
109
+ /** This viewer's announce name on the mesh (it does not publish a stream). */
110
+ name: string;
111
+ deps?: Partial<MeetViewerDeps>;
112
+ }
113
+ export declare class MeetViewer {
114
+ private readonly options;
115
+ private ws;
116
+ private remotes;
117
+ private iceServers;
118
+ private selfId;
119
+ private listeners;
120
+ private readonly deps;
121
+ constructor(options: MeetViewerOptions);
122
+ on<K extends keyof EventMap>(type: K, listener: Listener<K>): () => void;
123
+ /** Join the room as a VIEWER (recvonly). No capture, no publish. */
124
+ join(): Promise<void>;
125
+ /** Leave and tear down every peer connection + aggregated stream. As the
126
+ * track owner, this is where the streams (and the device-side tracks) end. */
127
+ leave(): void;
128
+ private openSocket;
129
+ private send;
130
+ private tearDown;
131
+ private onMessage;
132
+ private handleSignal;
133
+ private ensureRemote;
134
+ private isPolite;
135
+ private sendSignal;
136
+ private emit;
137
+ }
138
+ export {};
139
+ //# sourceMappingURL=meet-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meet-viewer.d.ts","sourceRoot":"","sources":["../../src/webrtc/meet-viewer.ts"],"names":[],"mappings":"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"}