From 8c0e9e2fd965b3934d387ecf497f01b6ba274256 Mon Sep 17 00:00:00 2001
From: Izan Gil <66965250+SrIzan10@users.noreply.github.com>
Date: Fri, 17 Jan 2025 19:34:55 +0100
Subject: [PATCH] feat: very barebones stream viewer
---
package.json | 3 +
src/app/(protected)/[username]/page.tsx | 8 +
.../api/livekit/broadcasterToken/route.ts | 25 +++
.../api/livekit/viewerToken/route.ts | 29 +++
src/components/app/Livestream/Livestream.tsx | 107 +++++++++++
src/lib/services/livekit.ts | 13 ++
yarn.lock | 179 +++++++++++++++++-
7 files changed, 361 insertions(+), 3 deletions(-)
create mode 100644 src/app/(protected)/[username]/page.tsx
create mode 100644 src/app/(protected)/api/livekit/broadcasterToken/route.ts
create mode 100644 src/app/(protected)/api/livekit/viewerToken/route.ts
create mode 100644 src/components/app/Livestream/Livestream.tsx
create mode 100644 src/lib/services/livekit.ts
diff --git a/package.json b/package.json
index 4801b59..05b6728 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
},
"dependencies": {
"@hookform/resolvers": "^3.9.1",
+ "@livekit/components-react": "^2.7.0",
"@lucia-auth/adapter-prisma": "^4.0.1",
"@node-rs/argon2": "^2.0.2",
"@prisma/client": "^6.0.1",
@@ -24,6 +25,8 @@
"arctic": "^3.1.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.0",
+ "livekit-client": "^2.8.0",
+ "livekit-server-sdk": "^2.9.7",
"lucia": "^3.2.2",
"lucide-react": "^0.368.0",
"next": "^15.1.2",
diff --git a/src/app/(protected)/[username]/page.tsx b/src/app/(protected)/[username]/page.tsx
new file mode 100644
index 0000000..de54a65
--- /dev/null
+++ b/src/app/(protected)/[username]/page.tsx
@@ -0,0 +1,8 @@
+import LiveStream from "@/components/app/Livestream/Livestream";
+
+export default async function Page({ params }: { params: Promise<{ username: string }> }) {
+ const { username } = await params;
+ return (
+
+ );
+}
diff --git a/src/app/(protected)/api/livekit/broadcasterToken/route.ts b/src/app/(protected)/api/livekit/broadcasterToken/route.ts
new file mode 100644
index 0000000..d248867
--- /dev/null
+++ b/src/app/(protected)/api/livekit/broadcasterToken/route.ts
@@ -0,0 +1,25 @@
+import { ingressClient, roomService } from '@/lib/services/livekit';
+import { IngressInput } from 'livekit-server-sdk';
+
+export async function GET(request: Request) {
+ const { searchParams } = new URL(request.url);
+ const room = searchParams.get('room');
+
+ if (!room) {
+ return new Response('Missing room', { status: 400 });
+ }
+
+ await roomService.createRoom({
+ name: room,
+ })
+ const ingress = await ingressClient.createIngress(
+ IngressInput.RTMP_INPUT,
+ {
+ name: room,
+ roomName: room,
+ participantIdentity: 'streamer',
+ }
+ )
+
+ return Response.json({ key: ingress.streamKey });
+}
\ No newline at end of file
diff --git a/src/app/(protected)/api/livekit/viewerToken/route.ts b/src/app/(protected)/api/livekit/viewerToken/route.ts
new file mode 100644
index 0000000..ce8e4a4
--- /dev/null
+++ b/src/app/(protected)/api/livekit/viewerToken/route.ts
@@ -0,0 +1,29 @@
+import { validateRequest } from '@/lib/auth';
+import { AccessToken } from 'livekit-server-sdk';
+import { NextRequest } from 'next/server';
+
+export async function GET(request: NextRequest) {
+ const { user } = await validateRequest();
+ const room = request.nextUrl.searchParams.get('room');
+ if (!room) {
+ return new Response('Room is required', { status: 400 });
+ }
+ if (!user) {
+ return new Response('Unauthorized', { status: 401 });
+ }
+
+ const at = new AccessToken(process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_SECRET, {
+ identity: user.id,
+ ttl: 3600,
+ });
+
+ at.addGrant({
+ room,
+ roomJoin: true,
+ canPublish: false,
+ canSubscribe: true,
+ canPublishData: false,
+ });
+
+ return Response.json({ token: await at.toJwt() });
+}
diff --git a/src/components/app/Livestream/Livestream.tsx b/src/components/app/Livestream/Livestream.tsx
new file mode 100644
index 0000000..ed5586d
--- /dev/null
+++ b/src/components/app/Livestream/Livestream.tsx
@@ -0,0 +1,107 @@
+'use client';
+
+import {
+ LiveKitRoom,
+ useTracks,
+ VideoTrack,
+ TrackRefContext,
+ useConnectionState,
+ useParticipants,
+ AudioTrack,
+ StartAudio,
+} from '@livekit/components-react';
+import { getTrackReferenceId } from '@livekit/components-core';
+import { Track } from 'livekit-client';
+import { LoaderCircleIcon } from 'lucide-react';
+import { useEffect, useState } from 'react';
+
+export default function LiveStream({ username }: { username: string }) {
+ const [token, setToken] = useState('');
+
+ useEffect(() => {
+ fetch(`/api/livekit/viewerToken?room=${username}`)
+ .then((res) => res.json())
+ .then((data) => setToken(data.token));
+ }, [username]);
+
+ if (!token) return
Loading...
;
+
+ return (
+
+
+
+ );
+}
+
+function StreamView() {
+ const tracks = useTracks([
+ Track.Source.Camera,
+ Track.Source.Microphone,
+ Track.Source.ScreenShare,
+ Track.Source.ScreenShareAudio,
+ ]);
+ const participants = useParticipants();
+ const connectionState = useConnectionState();
+ const [isConnecting, setIsConnecting] = useState(true);
+
+ const broadcasterTracks = tracks.filter((track) => track.participant.identity === 'streamer');
+
+ // very hacky but works
+ useEffect(() => {
+ if (connectionState === 'connected') {
+ const timer = setTimeout(() => setIsConnecting(false), 2000);
+ return () => clearTimeout(timer);
+ }
+ }, [connectionState]);
+ useEffect(() => {
+ console.log('participants', participants);
+ }, [participants]);
+
+ if (connectionState === 'connecting' || isConnecting) {
+ return (
+
+
+
+
Connecting to stream...
+
+
+ );
+ }
+ if (connectionState === 'disconnected') {
+ return (
+
+
Connection lost. Trying to reconnect...
+
+ );
+ }
+
+ if (!broadcasterTracks.length) {
+ return (
+
+
Stream is currently offline
+
+ );
+ }
+
+ const trackRef = broadcasterTracks[0];
+
+ return (
+
+
+
+
+ {broadcasterTracks.map((trackRef) => (
+
+ ))}
+
+
+ );
+}
diff --git a/src/lib/services/livekit.ts b/src/lib/services/livekit.ts
new file mode 100644
index 0000000..066ed61
--- /dev/null
+++ b/src/lib/services/livekit.ts
@@ -0,0 +1,13 @@
+import { IngressClient, RoomServiceClient } from 'livekit-server-sdk';
+
+export const roomService = new RoomServiceClient(
+ process.env.NEXT_PUBLIC_LIVEKIT_URL!,
+ process.env.LIVEKIT_API_KEY,
+ process.env.LIVEKIT_SECRET
+);
+
+export const ingressClient = new IngressClient(
+ process.env.NEXT_PUBLIC_LIVEKIT_URL!,
+ process.env.LIVEKIT_API_KEY,
+ process.env.LIVEKIT_SECRET
+);
diff --git a/yarn.lock b/yarn.lock
index 59723cd..1241f8d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -229,6 +229,11 @@
"@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.25.9"
+"@bufbuild/protobuf@^1.10.0", "@bufbuild/protobuf@^1.7.2":
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.10.0.tgz#1a67ac889c2d464a3492b3e54c38f80517963b16"
+ integrity sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==
+
"@emnapi/core@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.3.1.tgz#9c62d185372d1bddc94682b87f376e03dfac3f16"
@@ -290,6 +295,14 @@
dependencies:
"@floating-ui/utils" "^0.2.9"
+"@floating-ui/dom@1.6.11":
+ version "1.6.11"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.11.tgz#8631857838d34ee5712339eb7cbdfb8ad34da723"
+ integrity sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==
+ dependencies:
+ "@floating-ui/core" "^1.6.0"
+ "@floating-ui/utils" "^0.2.8"
+
"@floating-ui/dom@^1.0.0":
version "1.6.13"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34"
@@ -305,7 +318,7 @@
dependencies:
"@floating-ui/dom" "^1.0.0"
-"@floating-ui/utils@^0.2.9":
+"@floating-ui/utils@^0.2.8", "@floating-ui/utils@^0.2.9":
version "0.2.9"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429"
integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
@@ -491,6 +504,43 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
+"@livekit/components-core@0.12.0":
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/@livekit/components-core/-/components-core-0.12.0.tgz#fb339b3bc81bc7a34b78256fe45f41b8867c3e33"
+ integrity sha512-nF3yd0R9NYUb85/VGJoAYV4GrydTWifrRUvZ4l9vDGJtRsI5yxNjlLM8p9tq2Qe1CU7bgv/Idb6lbKyIWNKT0w==
+ dependencies:
+ "@floating-ui/dom" "1.6.11"
+ loglevel "1.9.1"
+ rxjs "7.8.1"
+
+"@livekit/components-react@^2.7.0":
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/@livekit/components-react/-/components-react-2.7.0.tgz#6d7e2ec1155841c1f7d89072c9e156a5cf857c7a"
+ integrity sha512-My7FktLPo+TQGutkrC3nyAWECO+MUrUdW4qpfgOOdAeBLjhULgoxMY34Dmw676frFvtPZavDdt33Kn3lf8Ub1Q==
+ dependencies:
+ "@livekit/components-core" "0.12.0"
+ clsx "2.1.1"
+ usehooks-ts "3.1.0"
+
+"@livekit/mutex@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@livekit/mutex/-/mutex-1.1.1.tgz#72492b611d55be8130ba2271b7a436d94b1bc6d4"
+ integrity sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==
+
+"@livekit/protocol@1.30.0":
+ version "1.30.0"
+ resolved "https://registry.yarnpkg.com/@livekit/protocol/-/protocol-1.30.0.tgz#c79e98aca2a822f9bd217d016c6efd0f472f206f"
+ integrity sha512-SDI9ShVKj8N3oOSinr8inaxD3FXgmgoJlqN35uU/Yx1sdoDeQbzAuBFox7bYjM+VhnZ1V22ivIDjAsKr00H+XQ==
+ dependencies:
+ "@bufbuild/protobuf" "^1.10.0"
+
+"@livekit/protocol@^1.30.0":
+ version "1.31.0"
+ resolved "https://registry.yarnpkg.com/@livekit/protocol/-/protocol-1.31.0.tgz#a8344a46b9e914a846cd0a2218f28635e7768b05"
+ integrity sha512-3uoMY1JUqDuoFtAlgjHLKZ9KBfqDBbBRq1GwPKB1hMiH1RVyPOV5TG7XVE4wm/vdAgUKgawtX2anZPJBIi6QQA==
+ dependencies:
+ "@bufbuild/protobuf" "^1.10.0"
+
"@lucia-auth/adapter-prisma@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@lucia-auth/adapter-prisma/-/adapter-prisma-4.0.1.tgz#8f8aa95bf0ac266fd2fb8ac3dc6dd9faec53342f"
@@ -1455,6 +1505,21 @@ camelcase-css@^2.0.1:
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+camelcase-keys@^9.0.0:
+ version "9.1.3"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-9.1.3.tgz#6367b2f9ec5724af541f58f0dcfee9b200022e5c"
+ integrity sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==
+ dependencies:
+ camelcase "^8.0.0"
+ map-obj "5.0.0"
+ quick-lru "^6.1.1"
+ type-fest "^4.3.2"
+
+camelcase@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-8.0.0.tgz#c0d36d418753fb6ad9c5e0437579745c1c14a534"
+ integrity sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==
+
caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001688:
version "1.0.30001692"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz#4585729d95e6b95be5b439da6ab55250cd125bf9"
@@ -1517,7 +1582,7 @@ clone@^1.0.2:
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
-clsx@^2.1.0, clsx@^2.1.1:
+clsx@2.1.1, clsx@^2.1.0, clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
@@ -2126,6 +2191,11 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+events@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
execa@^7.0.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9"
@@ -2797,6 +2867,11 @@ jiti@^1.21.6:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9"
integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==
+jose@^5.1.2:
+ version "5.9.6"
+ resolved "https://registry.yarnpkg.com/jose/-/jose-5.9.6.tgz#77f1f901d88ebdc405e57cce08d2a91f47521883"
+ integrity sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -2912,6 +2987,31 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+livekit-client@^2.8.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/livekit-client/-/livekit-client-2.8.0.tgz#76e0c39b0f1ec231a6747fa91c4631604e666c80"
+ integrity sha512-8/IXhacAFYdXMU1wFyc8/MSGCzHr02Hn9T5o3MX19TR03RHSaBKBF2xK8fQFINBmpcYkiMAnQL0P6K3nfcifQA==
+ dependencies:
+ "@livekit/mutex" "1.1.1"
+ "@livekit/protocol" "1.30.0"
+ events "^3.3.0"
+ loglevel "^1.8.0"
+ sdp-transform "^2.14.1"
+ ts-debounce "^4.0.0"
+ tslib "2.8.1"
+ typed-emitter "^2.1.0"
+ webrtc-adapter "^9.0.0"
+
+livekit-server-sdk@^2.9.7:
+ version "2.9.7"
+ resolved "https://registry.yarnpkg.com/livekit-server-sdk/-/livekit-server-sdk-2.9.7.tgz#b782b04611ee7878e1946aecbb494e25302a3abc"
+ integrity sha512-uIkFOaqBCJnVgYOidZdanPWQH5G0LMxe0+Qp5zbx7MZCkJ7lGiju//yonfEvFofriJBKACjMq/KQHBex96QpeA==
+ dependencies:
+ "@bufbuild/protobuf" "^1.7.2"
+ "@livekit/protocol" "^1.30.0"
+ camelcase-keys "^9.0.0"
+ jose "^5.1.2"
+
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
@@ -2924,6 +3024,11 @@ lodash._reinterpolate@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==
+lodash.debounce@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
+
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -2952,6 +3057,16 @@ log-symbols@^5.1.0:
chalk "^5.0.0"
is-unicode-supported "^1.1.0"
+loglevel@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7"
+ integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==
+
+loglevel@^1.8.0:
+ version "1.9.2"
+ resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.2.tgz#c2e028d6c757720107df4e64508530db6621ba08"
+ integrity sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==
+
loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@@ -2984,6 +3099,11 @@ lucide-react@^0.368.0:
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.368.0.tgz#3c0ee63f4f7d30ae63b621b2b8f04f9e409ee6e7"
integrity sha512-soryVrCjheZs8rbXKdINw9B8iPi5OajBJZMJ1HORig89ljcOcEokKKAgGbg3QWxSXel7JwHOfDFUdDHAKyUAMw==
+map-obj@5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-5.0.0.tgz#126c98596b63927d7360f287cccc67177aa1938b"
+ integrity sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==
+
math-intrinsics@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
@@ -3470,6 +3590,11 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+quick-lru@^6.1.1:
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-6.1.2.tgz#e9a90524108629be35287d0b864e7ad6ceb3659e"
+ integrity sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==
+
react-dom@19:
version "19.0.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57"
@@ -3634,6 +3759,13 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
+rxjs@7.8.1, rxjs@^7.5.2:
+ version "7.8.1"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
+ integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
+ dependencies:
+ tslib "^2.1.0"
+
safe-array-concat@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3"
@@ -3672,6 +3804,16 @@ scheduler@^0.25.0:
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015"
integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==
+sdp-transform@^2.14.1:
+ version "2.15.0"
+ resolved "https://registry.yarnpkg.com/sdp-transform/-/sdp-transform-2.15.0.tgz#79d37a2481916f36a0534e07b32ceaa87f71df42"
+ integrity sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==
+
+sdp@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/sdp/-/sdp-3.2.0.tgz#8961420552b36663b4d13ddba6f478d1461896a5"
+ integrity sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==
+
semver@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
@@ -4135,6 +4277,11 @@ ts-api-utils@^2.0.0:
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.0.tgz#b9d7d5f7ec9f736f4d0f09758b8607979044a900"
integrity sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==
+ts-debounce@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/ts-debounce/-/ts-debounce-4.0.0.tgz#33440ef64fab53793c3d546a8ca6ae539ec15841"
+ integrity sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==
+
ts-interface-checker@^0.1.9:
version "0.1.13"
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
@@ -4167,7 +4314,7 @@ tsconfig-paths@^4.2.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
-tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0:
+tslib@2.8.1, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -4184,6 +4331,11 @@ type-fest@^0.20.2:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+type-fest@^4.3.2:
+ version "4.32.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.32.0.tgz#55bacdd6f2cf1392b7e9cde894e9b1d726807e97"
+ integrity sha512-rfgpoi08xagF3JSdtJlCwMq9DGNDE0IMh3Mkpc1wUypg9vPi786AiqeBBKcqvIkq42azsBM85N490fyZjeUftw==
+
typed-array-buffer@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536"
@@ -4229,6 +4381,13 @@ typed-array-length@^1.0.7:
possible-typed-array-names "^1.0.0"
reflect.getprototypeof "^1.0.6"
+typed-emitter@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-2.1.0.tgz#ca78e3d8ef1476f228f548d62e04e3d4d3fd77fb"
+ integrity sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==
+ optionalDependencies:
+ rxjs "^7.5.2"
+
typescript@^5:
version "5.7.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e"
@@ -4284,6 +4443,13 @@ use-sidecar@^1.1.2:
detect-node-es "^1.1.0"
tslib "^2.0.0"
+usehooks-ts@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-3.1.0.tgz#156119f36efc85f1b1952616c02580f140950eca"
+ integrity sha512-bBIa7yUyPhE1BCc0GmR96VU/15l/9gP1Ch5mYdLcFBaFGQsdmXkvjV0TtOqW1yUd6VjIwDunm+flSciCQXujiw==
+ dependencies:
+ lodash.debounce "^4.0.8"
+
util-deprecate@^1.0.1, util-deprecate@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -4301,6 +4467,13 @@ web-streams-polyfill@^3.0.3:
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
+webrtc-adapter@^9.0.0:
+ version "9.0.1"
+ resolved "https://registry.yarnpkg.com/webrtc-adapter/-/webrtc-adapter-9.0.1.tgz#d4efa22ca9604cb2c8cdb9e492815ba37acfa0b2"
+ integrity sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==
+ dependencies:
+ sdp "^3.2.0"
+
which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e"