From 15c52349ac69a2d903150ac1048dda5d33c1575f Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Fri, 22 Nov 2024 23:47:29 -0800 Subject: [PATCH 01/13] Add route for creating streams --- apps/web/package.json | 1 + .../(docs)/docs/api-reference/js-sdk/page.mdx | 1 + .../docs/api-reference/js-sdk/v1.0.5/page.mdx | 5 + apps/web/src/app/api/desktop/stream/route.ts | 46 +++++++ pnpm-lock.yaml | 116 +++++++++++++++++- 5 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 apps/web/src/app/(docs)/docs/api-reference/js-sdk/v1.0.5/page.mdx create mode 100644 apps/web/src/app/api/desktop/stream/route.ts diff --git a/apps/web/package.json b/apps/web/package.json index 40344d7cc..4c46128f7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,6 +18,7 @@ "@headlessui/tailwindcss": "^0.2.0", "@mdx-js/loader": "^2.1.5", "@mdx-js/react": "^2.1.5", + "@mux/mux-node": "^9.0.1", "@next/mdx": "^14.2.5", "@nivo/line": "^0.87.0", "@radix-ui/react-alert-dialog": "^1.0.5", diff --git a/apps/web/src/app/(docs)/docs/api-reference/js-sdk/page.mdx b/apps/web/src/app/(docs)/docs/api-reference/js-sdk/page.mdx index 10f6b374a..4c579f40c 100644 --- a/apps/web/src/app/(docs)/docs/api-reference/js-sdk/page.mdx +++ b/apps/web/src/app/(docs)/docs/api-reference/js-sdk/page.mdx @@ -3,6 +3,7 @@ [v1.0.2] [v1.0.3] [v1.0.4] + [v1.0.5] # js-sdk diff --git a/apps/web/src/app/(docs)/docs/api-reference/js-sdk/v1.0.5/page.mdx b/apps/web/src/app/(docs)/docs/api-reference/js-sdk/v1.0.5/page.mdx new file mode 100644 index 000000000..61e14ae2f --- /dev/null +++ b/apps/web/src/app/(docs)/docs/api-reference/js-sdk/v1.0.5/page.mdx @@ -0,0 +1,5 @@ +# JS-SDK v1.0.5 + +- [Errors](./v1.0.5/errors) +- [Filesystem](./v1.0.5/filesystem) +- [Sandbox](./v1.0.5/sandbox) \ No newline at end of file diff --git a/apps/web/src/app/api/desktop/stream/route.ts b/apps/web/src/app/api/desktop/stream/route.ts new file mode 100644 index 000000000..8c0b73306 --- /dev/null +++ b/apps/web/src/app/api/desktop/stream/route.ts @@ -0,0 +1,46 @@ +import Mux from '@mux/mux-node' +import { NextResponse } from 'next/server' + +import { createClient } from '@supabase/supabase-js' + +const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! +const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY! + +const supabase = createClient(supabaseUrl, supabaseServiceKey) + +const mux = new Mux({ + tokenId: process.env.MUX_TOKEN_ID, + tokenSecret: process.env.MUX_TOKEN_SECRET +}) + +export async function POST(request: Request) { + // TODO: UseG apiKey + // const apiKey = request.headers.get('X-API-Key') + const { sandboxId } = await request.json() + console.log('sandboxId', sandboxId) + + // if (!apiKey) { + // return NextResponse.json({ error: 'Missing X-API-Key' }, { status: 400 }) + // } + + if (!sandboxId) { + return NextResponse.json({ error: 'Missing sandboxId' }, { status: 400 }) + } + + const liveStream = await mux.video.liveStreams.create({ + latency_mode: 'low', + reconnect_window: 60, + playback_policy: ['public'], + new_asset_settings: { playback_policy: ['public'] }, + }) + + if (!liveStream.playback_ids?.[0]?.id) { + return NextResponse.json({ error: 'Failed to create live stream' }, { status: 500 }) + } + + await supabase + .from('sandbox_streams') + .insert([{ sandbox_id: sandboxId, playback_id: liveStream.playback_ids[0].id }]) + + return NextResponse.json({ streamKey: liveStream.stream_key, playbackId: liveStream.playback_ids[0].id }, { status: 201 }) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a547a05d7..f04772721 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@mdx-js/react': specifier: ^2.1.5 version: 2.3.0(react@18.2.0) + '@mux/mux-node': + specifier: ^9.0.1 + version: 9.0.1(encoding@0.1.13) '@next/mdx': specifier: ^14.2.5 version: 14.2.5(@mdx-js/loader@2.3.0(webpack@5.88.2))(@mdx-js/react@2.3.0(react@18.2.0)) @@ -395,7 +398,7 @@ importers: version: 2.1.2(@types/node@18.18.6)(@vitest/browser@2.1.2)(msw@2.4.10(typescript@5.5.3))(terser@5.20.0) vitest-browser-react: specifier: ^0.0.1 - version: 0.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(@vitest/browser@2.1.2(@vitest/spy@2.1.2)(bufferutil@4.0.8)(playwright@1.48.0)(typescript@5.5.3)(utf-8-validate@6.0.3)(vite@5.4.8(@types/node@18.18.6)(terser@5.20.0))(vitest@2.1.2))(react-dom@18.2.0(react@18.3.1))(react@18.3.1)(vitest@2.1.2(@types/node@18.18.6)(@vitest/browser@2.1.2)(msw@2.4.10(typescript@5.5.3))(terser@5.20.0)) + version: 0.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(@vitest/browser@2.1.2)(react-dom@18.2.0(react@18.3.1))(react@18.3.1)(vitest@2.1.2) packages/python-sdk: {} @@ -1355,6 +1358,9 @@ packages: resolution: {integrity: sha512-SSnyl/4ni/2ViHKkiZb8eajA/eN1DNFaHjhGiLUdZvDz6PKF4COSf/17xqSz64nOo2Ia29SA6B2KNCsyCbVmaQ==} engines: {node: '>=18'} + '@mux/mux-node@9.0.1': + resolution: {integrity: sha512-+wSqwCkb3/RplJkhd35R44+Ov1pQTzXDJSCLF8yxBRodUL2uqG/ajCSix+miIiPNY+v/tx0rJ9+t6dxe2ZR/Dg==} + '@next/env@14.2.5': resolution: {integrity: sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA==} @@ -2706,6 +2712,9 @@ packages: '@types/mysql@2.15.22': resolution: {integrity: sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==} + '@types/node-fetch@2.6.12': + resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} @@ -3080,6 +3089,10 @@ packages: abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + acorn-import-assertions@1.9.0: resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} deprecated: package has been renamed to acorn-import-attributes @@ -3254,6 +3267,9 @@ packages: asynciterator.prototype@1.0.0: resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.15: resolution: {integrity: sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==} engines: {node: ^10 || ^12 || >=14} @@ -3600,6 +3616,10 @@ packages: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -3869,6 +3889,10 @@ packages: delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -4229,6 +4253,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -4361,10 +4389,21 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + form-data-encoder@2.1.4: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + fp-and-or@0.1.4: resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==} engines: {node: '>=10'} @@ -5775,6 +5814,10 @@ packages: node-addon-api@6.1.0: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -7678,6 +7721,10 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + web-vitals@4.2.2: resolution: {integrity: sha512-nYfoOqb4EmElljyXU2qdeE76KsvoHdftQKY4DzA9Aw8DervCg2bG634pHLrJ/d6+B4mE3nWTSJv8Mo7B2mbZkw==} @@ -8971,6 +9018,19 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 + '@mux/mux-node@9.0.1(encoding@0.1.13)': + dependencies: + '@types/node': 18.18.6 + '@types/node-fetch': 2.6.12 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + jose: 4.14.6 + node-fetch: 2.7.0(encoding@0.1.13) + transitivePeerDependencies: + - encoding + '@next/env@14.2.5': {} '@next/eslint-plugin-next@14.2.5': @@ -10615,6 +10675,11 @@ snapshots: dependencies: '@types/node': 18.18.6 + '@types/node-fetch@2.6.12': + dependencies: + '@types/node': 18.18.6 + form-data: 4.0.1 + '@types/node@12.20.55': {} '@types/node@18.18.6': {} @@ -11108,6 +11173,10 @@ snapshots: abbrev@1.1.1: {} + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + acorn-import-assertions@1.9.0(acorn@8.11.3): dependencies: acorn: 8.11.3 @@ -11303,6 +11372,8 @@ snapshots: dependencies: has-symbols: 1.0.3 + asynckit@0.4.0: {} + autoprefixer@10.4.15(postcss@8.4.31): dependencies: browserslist: 4.21.10 @@ -11683,6 +11754,10 @@ snapshots: color-convert: 2.0.1 color-string: 1.9.1 + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + comma-separated-tokens@2.0.3: {} command-exists@1.2.9: {} @@ -11929,6 +12004,8 @@ snapshots: dependencies: robust-predicates: 3.0.2 + delayed-stream@1.0.0: {} + delegates@1.0.0: {} dequal@2.0.3: {} @@ -12271,7 +12348,7 @@ snapshots: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.57.1 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1) eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint@8.57.1) fast-glob: 3.3.1 get-tsconfig: 4.7.0 @@ -12283,7 +12360,17 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 6.7.2(eslint@8.49.0)(typescript@5.5.3) + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -12304,7 +12391,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -12522,6 +12609,8 @@ snapshots: esutils@2.0.3: {} + event-target-shim@5.0.1: {} + events@3.3.0: {} execa@5.1.1: @@ -12661,8 +12750,21 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + form-data-encoder@1.7.2: {} + form-data-encoder@2.1.4: {} + form-data@4.0.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + fp-and-or@0.1.4: {} fraction.js@4.3.6: {} @@ -14361,6 +14463,8 @@ snapshots: node-addon-api@6.1.0: {} + node-domexception@1.0.0: {} + node-fetch@2.7.0(encoding@0.1.13): dependencies: whatwg-url: 5.0.0 @@ -16449,7 +16553,7 @@ snapshots: fsevents: 2.3.3 terser: 5.20.0 - vitest-browser-react@0.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(@vitest/browser@2.1.2(@vitest/spy@2.1.2)(bufferutil@4.0.8)(playwright@1.48.0)(typescript@5.5.3)(utf-8-validate@6.0.3)(vite@5.4.8(@types/node@18.18.6)(terser@5.20.0))(vitest@2.1.2))(react-dom@18.2.0(react@18.3.1))(react@18.3.1)(vitest@2.1.2(@types/node@18.18.6)(@vitest/browser@2.1.2)(msw@2.4.10(typescript@5.5.3))(terser@5.20.0)): + vitest-browser-react@0.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(@vitest/browser@2.1.2)(react-dom@18.2.0(react@18.3.1))(react@18.3.1)(vitest@2.1.2): dependencies: '@vitest/browser': 2.1.2(@vitest/spy@2.1.2)(bufferutil@4.0.8)(playwright@1.48.0)(typescript@5.5.3)(utf-8-validate@6.0.3)(vite@5.4.8(@types/node@18.18.6)(terser@5.20.0))(vitest@2.1.2) react: 18.3.1 @@ -16509,6 +16613,8 @@ snapshots: dependencies: defaults: 1.0.4 + web-streams-polyfill@4.0.0-beta.3: {} + web-vitals@4.2.2: {} webidl-conversions@3.0.1: {} From f7bbc398dd6df1a866ded948746e6d86e2b0377d Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Fri, 22 Nov 2024 23:59:59 -0800 Subject: [PATCH 02/13] Don't send playback_id --- apps/web/src/app/api/desktop/stream/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/api/desktop/stream/route.ts b/apps/web/src/app/api/desktop/stream/route.ts index 8c0b73306..af875e079 100644 --- a/apps/web/src/app/api/desktop/stream/route.ts +++ b/apps/web/src/app/api/desktop/stream/route.ts @@ -42,5 +42,5 @@ export async function POST(request: Request) { .from('sandbox_streams') .insert([{ sandbox_id: sandboxId, playback_id: liveStream.playback_ids[0].id }]) - return NextResponse.json({ streamKey: liveStream.stream_key, playbackId: liveStream.playback_ids[0].id }, { status: 201 }) + return NextResponse.json({ streamKey: liveStream.stream_key }, { status: 201 }) } From b390945b4ee6dcb847e7dc8f1ed56e6aa83c3fe8 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 01:37:31 -0800 Subject: [PATCH 03/13] Prepare streaming page for desktop sandbox --- apps/web/package.json | 1 + .../stream => stream/sandbox}/route.ts | 21 +++++ apps/web/src/app/layout.tsx | 2 - apps/web/src/app/not-found.tsx | 11 +++ apps/web/src/app/stream/sandbox/page.tsx | 65 +++++++++++++ apps/web/src/middleware.ts | 1 + apps/web/src/pages/_404/[...path].tsx | 15 --- pnpm-lock.yaml | 94 +++++++++++++++++++ 8 files changed, 193 insertions(+), 17 deletions(-) rename apps/web/src/app/api/{desktop/stream => stream/sandbox}/route.ts (70%) create mode 100644 apps/web/src/app/not-found.tsx create mode 100644 apps/web/src/app/stream/sandbox/page.tsx delete mode 100644 apps/web/src/pages/_404/[...path].tsx diff --git a/apps/web/package.json b/apps/web/package.json index 4c46128f7..0a6df6d40 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -19,6 +19,7 @@ "@mdx-js/loader": "^2.1.5", "@mdx-js/react": "^2.1.5", "@mux/mux-node": "^9.0.1", + "@mux/mux-player-react": "^3.1.0", "@next/mdx": "^14.2.5", "@nivo/line": "^0.87.0", "@radix-ui/react-alert-dialog": "^1.0.5", diff --git a/apps/web/src/app/api/desktop/stream/route.ts b/apps/web/src/app/api/stream/sandbox/route.ts similarity index 70% rename from apps/web/src/app/api/desktop/stream/route.ts rename to apps/web/src/app/api/stream/sandbox/route.ts index af875e079..999c7b30b 100644 --- a/apps/web/src/app/api/desktop/stream/route.ts +++ b/apps/web/src/app/api/stream/sandbox/route.ts @@ -44,3 +44,24 @@ export async function POST(request: Request) { return NextResponse.json({ streamKey: liveStream.stream_key }, { status: 201 }) } + +export async function GET(request: Request) { + const url = new URL(request.url) + const sandboxId = url.searchParams.get('sandboxId') + + if (!sandboxId) { + return NextResponse.json({ error: 'Missing sandboxId' }, { status: 400 }) + } + + const { data, error } = await supabase + .from('sandbox_streams') + .select('playback_id') + .eq('sandbox_id', sandboxId) + .single() + + if (error || !data) { + return NextResponse.json({ error: 'Playback ID not found' }, { status: 404 }) + } + + return NextResponse.json({ playbackId: data.playback_id }, { status: 200 }) +} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index f16556055..712e03eea 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -13,8 +13,6 @@ import { Section } from '@/components/SectionProvider' import { Layout } from '@/components/Layout' export const metadata: Metadata = { - // TODO: Add metadataBase - // metadataBase: '' title: { template: '%s - E2B', default: 'E2B - Code Interpreting for AI apps', diff --git a/apps/web/src/app/not-found.tsx b/apps/web/src/app/not-found.tsx new file mode 100644 index 000000000..b2a8d2f44 --- /dev/null +++ b/apps/web/src/app/not-found.tsx @@ -0,0 +1,11 @@ +import Link from 'next/link' + +export default function NotFound() { + return ( +
+

Not Found

+

Could not find requested resource

+ Return Home +
+ ) +} diff --git a/apps/web/src/app/stream/sandbox/page.tsx b/apps/web/src/app/stream/sandbox/page.tsx new file mode 100644 index 000000000..b4b1574b3 --- /dev/null +++ b/apps/web/src/app/stream/sandbox/page.tsx @@ -0,0 +1,65 @@ +'use client' + +import { useSearchParams } from 'next/navigation' +import { useEffect, useState } from 'react' +import MuxPlayer from '@mux/mux-player-react' + + + +interface SandboxStream { + sandboxId: string + playbackId: string +} + +export default function StreamPage() { + const searchParams = useSearchParams() + const sandboxId = searchParams.get('sandboxId') + const [stream, setStream] = useState(null) + const [error, setError] = useState(null) + + useEffect(() => { + const fetchStream = async () => { + if (sandboxId) { + try { + const response = await fetch(`/api/stream/sandbox?sandboxId=${sandboxId}`) + if (!response.ok) { + throw new Error('Network response was not ok') + } + const data = await response.json() + setStream(data) + } catch (err) { + setError(err.message) + } + } + } + + fetchStream() + }, [sandboxId]) + + if (error) { + return
Error loading stream: {error}
+ } + + if (!stream) { + return
Stream not found
+ } + console.log('stream', stream) + + return ( +
+ hello +

Stream Details

+
Sandbox ID: {stream.sandboxId}
+
Playback ID: {stream.playbackId}
+ + +
+ ) +} \ No newline at end of file diff --git a/apps/web/src/middleware.ts b/apps/web/src/middleware.ts index b9b8f317d..1b6aa0d0c 100644 --- a/apps/web/src/middleware.ts +++ b/apps/web/src/middleware.ts @@ -5,6 +5,7 @@ export async function middleware(req: NextRequest): Promise { if (req.method !== 'GET') return NextResponse.next() const url = new URL(req.nextUrl.toString()) + console.log('url', url) url.protocol = 'https' url.port = '' diff --git a/apps/web/src/pages/_404/[...path].tsx b/apps/web/src/pages/_404/[...path].tsx deleted file mode 100644 index 3be8c9c6f..000000000 --- a/apps/web/src/pages/_404/[...path].tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { GetServerSideProps } from 'next' - -// https://github.com/vercel/next.js/discussions/16749#discussioncomment-2992732 -export const getServerSideProps: GetServerSideProps = async () => { - return { - redirect: { - destination: '/', - permanent: false, - }, - } -} - -export default function Custom404() { - return null -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f04772721..514984756 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,6 +51,9 @@ importers: '@mux/mux-node': specifier: ^9.0.1 version: 9.0.1(encoding@0.1.13) + '@mux/mux-player-react': + specifier: ^3.1.0 + version: 3.1.0(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@next/mdx': specifier: ^14.2.5 version: 14.2.5(@mdx-js/loader@2.3.0(webpack@5.88.2))(@mdx-js/react@2.3.0(react@18.2.0)) @@ -1361,6 +1364,28 @@ packages: '@mux/mux-node@9.0.1': resolution: {integrity: sha512-+wSqwCkb3/RplJkhd35R44+Ov1pQTzXDJSCLF8yxBRodUL2uqG/ajCSix+miIiPNY+v/tx0rJ9+t6dxe2ZR/Dg==} + '@mux/mux-player-react@3.1.0': + resolution: {integrity: sha512-oJWcRtDNE84KKSi/5tz7CKGHBLA34V9XlLnv30qqVMAvfifa3S0lY82gP41YA0OfYANwp5Sg29bbh3quekusPg==} + peerDependencies: + '@types/react': ^17.0.0 || ^17.0.0-0 || ^18 || ^18.0.0-0 || ^19 || ^19.0.0-0 + '@types/react-dom': '*' + react: ^17.0.2 || ^17.0.0-0 || ^18 || ^18.0.0-0 || ^19 || ^19.0.0-0 + react-dom: ^17.0.2 || ^17.0.2-0 || ^18 || ^18.0.0-0 || ^19 || ^19.0.0-0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@mux/mux-player@3.1.0': + resolution: {integrity: sha512-vU7HjvM3KLDfMwMfjbotlhjQrakwm9A4zixxtzBdxwDMLKf0FUKiFOGyTGOdsIKNBRVlS5Ffz9ERU+3Hh+XcBQ==} + + '@mux/mux-video@0.22.0': + resolution: {integrity: sha512-VrY4AVc6KkQcG0EPOtHf7aGXFwO1DTLZKtRRdPCx0KWSAlwR1II5YnHcEAwPbi1Uv94Hykq3Lbjt5dLqRNXKtA==} + + '@mux/playback-core@0.27.0': + resolution: {integrity: sha512-9kzpGRJNXLNMfFV6hvOde2+Uy3HyllwwEt9H5r4gYXOmrivQ6IWIGr9nXrUy7fmNkx6H05W+96zt1GhtBTlSDQ==} + '@next/env@14.2.5': resolution: {integrity: sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA==} @@ -3454,6 +3479,9 @@ packages: caniuse-lite@1.0.30001667: resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==} + castable-video@1.1.0: + resolution: {integrity: sha512-64/roq+vieXz8aOEvSs5bohHRym1fxhvHQMZXPn8/s8z0oi7XD5B67fnt9gFyCsfzH8RnuYJ0PxMSYjbMPHOtw==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -3720,6 +3748,9 @@ packages: resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} engines: {node: '>= 0.1.90'} + custom-media-element@1.3.2: + resolution: {integrity: sha512-nDyMobZgoAVqz7mA8rsn7i1/6bjH6N9ab2Ge7LyyNxrvxAq7zQJPg8i3u2VH7wEB+Y1T1+C3/h1G774/D+ZLag==} + d3-array@2.12.1: resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} @@ -4664,6 +4695,9 @@ packages: highlight.js@10.7.3: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + hls.js@1.5.17: + resolution: {integrity: sha512-wA66nnYFvQa1o4DO/BFgLNRKnBTVXpNeldGRBJ2Y0SvFtdwvFKCbqa9zhHoZLoxHhZ+jYsj3aIBkWQQCPNOhMw==} + hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -5451,6 +5485,12 @@ packages: mdx-annotations@0.1.3: resolution: {integrity: sha512-2XrOlQeBDUa8GirNHy/Y7BR1h/P+vzk+1G2rzAfqJ+lg6JcEOKMCqsVkpVFSw0hdzpVuj9BnoNeA+aU1XPTkoA==} + media-chrome@4.2.3: + resolution: {integrity: sha512-gzwFy2b+RLsEtnPzUzqzf2L5XkaTLQr8POOyLOcoebWSAWg31cPy2vfXNiUnd93sc5IxwJ8OAwkKxnaJNZ8Gjg==} + + media-tracks@0.3.3: + resolution: {integrity: sha512-9P2FuUHnZZ3iji+2RQk7Zkh5AmZTnOG5fODACnjhCVveX1McY3jmCRHofIEI+yTBqplz7LXy48c7fQ3Uigp88w==} + mem@6.1.1: resolution: {integrity: sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==} engines: {node: '>=8'} @@ -5748,6 +5788,9 @@ packages: resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + mux-embed@5.4.1: + resolution: {integrity: sha512-WsBV/K5tXiXi5pg1Ex65rO8gbHqljdbwfNuDNYVYsV8jZ1pe9leFe9ElSYfVa2nsooCBB196X+FKXlZs9KPYog==} + mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -6227,6 +6270,9 @@ packages: platform@1.3.6: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + player.style@0.0.8: + resolution: {integrity: sha512-ScmFzio3634eEn+ejpkEw13F5xYvnPghtaZz/Kg7QQP78ECrxdjRVqwVPZhUwbYxmg5OIScByOgHfrHpzTtR1Q==} + playwright-core@1.48.0: resolution: {integrity: sha512-RBvzjM9rdpP7UUFrQzRwR8L/xR4HyC1QXMzGYTbf1vjw25/ya9NRAVnXi/0fvFopjebvyPzsmoK58xxeEOaVvA==} engines: {node: '>=18'} @@ -9031,6 +9077,36 @@ snapshots: transitivePeerDependencies: - encoding + '@mux/mux-player-react@3.1.0(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@mux/mux-player': 3.1.0 + '@mux/playback-core': 0.27.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + optionalDependencies: + '@types/react': 18.2.48 + '@types/react-dom': 18.2.7 + + '@mux/mux-player@3.1.0': + dependencies: + '@mux/mux-video': 0.22.0 + '@mux/playback-core': 0.27.0 + media-chrome: 4.2.3 + player.style: 0.0.8 + + '@mux/mux-video@0.22.0': + dependencies: + '@mux/playback-core': 0.27.0 + castable-video: 1.1.0 + custom-media-element: 1.3.2 + media-tracks: 0.3.3 + + '@mux/playback-core@0.27.0': + dependencies: + hls.js: 1.5.17 + mux-embed: 5.4.1 + '@next/env@14.2.5': {} '@next/eslint-plugin-next@14.2.5': @@ -11586,6 +11662,10 @@ snapshots: caniuse-lite@1.0.30001667: {} + castable-video@1.1.0: + dependencies: + custom-media-element: 1.3.2 + ccount@2.0.1: {} chai@5.1.1: @@ -11855,6 +11935,8 @@ snapshots: csv-stringify: 5.6.5 stream-transform: 2.1.3 + custom-media-element@1.3.2: {} + d3-array@2.12.1: dependencies: internmap: 1.0.1 @@ -13080,6 +13162,8 @@ snapshots: highlight.js@10.7.3: {} + hls.js@1.5.17: {} + hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -13949,6 +14033,10 @@ snapshots: estree-util-visit: 1.2.1 unist-util-visit: 4.1.2 + media-chrome@4.2.3: {} + + media-tracks@0.3.3: {} + mem@6.1.1: dependencies: map-age-cleaner: 0.1.3 @@ -14397,6 +14485,8 @@ snapshots: mute-stream@1.0.0: {} + mux-embed@5.4.1: {} + mz@2.7.0: dependencies: any-promise: 1.3.0 @@ -14978,6 +15068,10 @@ snapshots: platform@1.3.6: {} + player.style@0.0.8: + dependencies: + media-chrome: 4.2.3 + playwright-core@1.48.0: {} playwright@1.48.0: From b1b54d8ee46c8358f2392a66cf47413fd1f63649 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 01:45:12 -0800 Subject: [PATCH 04/13] Add suspense --- apps/web/src/app/stream/sandbox/page.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/stream/sandbox/page.tsx b/apps/web/src/app/stream/sandbox/page.tsx index b4b1574b3..ebe11f966 100644 --- a/apps/web/src/app/stream/sandbox/page.tsx +++ b/apps/web/src/app/stream/sandbox/page.tsx @@ -1,7 +1,8 @@ 'use client' import { useSearchParams } from 'next/navigation' -import { useEffect, useState } from 'react' +import { useEffect, useState, Suspense } from 'react' +// @ts-ignore import MuxPlayer from '@mux/mux-player-react' @@ -46,7 +47,7 @@ export default function StreamPage() { console.log('stream', stream) return ( -
+ Loading...
}> hello

Stream Details

Sandbox ID: {stream.sandboxId}
@@ -60,6 +61,6 @@ export default function StreamPage() { viewer_user_id: 'user-id-007', }} /> - + ) } \ No newline at end of file From 008ed962a5e84a32383562568937298e08b9325d Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 10:10:12 -0800 Subject: [PATCH 05/13] Remove redirect of all dynamic pages to 404 and add dynamic page for displaying stream --- apps/web/next.config.mjs | 1 - apps/web/src/app/api/stream/sandbox/route.ts | 21 ------ .../app/stream/sandbox/[sandboxId]/page.tsx | 51 ++++++++++++++ apps/web/src/app/stream/sandbox/page.tsx | 66 ------------------- apps/web/src/types/mux-player-react.d.ts | 9 +++ 5 files changed, 60 insertions(+), 88 deletions(-) create mode 100644 apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx delete mode 100644 apps/web/src/app/stream/sandbox/page.tsx create mode 100644 apps/web/src/types/mux-player-react.d.ts diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index b957ad55d..409555986 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -61,7 +61,6 @@ const nextConfig = { destination: 'https://app.posthog.com/:path*', // BEWARE: setting basePath will break the analytics proxy }, - { source: '/:path*', destination: '/_404/:path*' }, ] } } diff --git a/apps/web/src/app/api/stream/sandbox/route.ts b/apps/web/src/app/api/stream/sandbox/route.ts index 999c7b30b..af875e079 100644 --- a/apps/web/src/app/api/stream/sandbox/route.ts +++ b/apps/web/src/app/api/stream/sandbox/route.ts @@ -44,24 +44,3 @@ export async function POST(request: Request) { return NextResponse.json({ streamKey: liveStream.stream_key }, { status: 201 }) } - -export async function GET(request: Request) { - const url = new URL(request.url) - const sandboxId = url.searchParams.get('sandboxId') - - if (!sandboxId) { - return NextResponse.json({ error: 'Missing sandboxId' }, { status: 400 }) - } - - const { data, error } = await supabase - .from('sandbox_streams') - .select('playback_id') - .eq('sandbox_id', sandboxId) - .single() - - if (error || !data) { - return NextResponse.json({ error: 'Playback ID not found' }, { status: 404 }) - } - - return NextResponse.json({ playbackId: data.playback_id }, { status: 200 }) -} diff --git a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx new file mode 100644 index 000000000..1cb0e80a0 --- /dev/null +++ b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx @@ -0,0 +1,51 @@ +import { Suspense } from 'react' +import { createClient } from '@supabase/supabase-js' +import MuxPlayer from '@mux/mux-player-react' + +const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! +const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY! + +const supabase = createClient(supabaseUrl, supabaseServiceKey) + +interface SandboxStream { + sandboxId: string + playbackId: string +} + +async function fetchStream(sandboxId: string): Promise { + const { data, error } = await supabase + .from('sandbox_streams') + .select('playback_id') + .eq('sandbox_id', sandboxId) + .single() + + if (error || !data) { + return null + } + + return { sandboxId, playbackId: data.playback_id } +} + +export default async function StreamPage({ params }: { params: { sandboxId: string } }) { + const stream = await fetchStream(params.sandboxId) + + if (!stream) { + return
Stream not found
+ } + + return ( + Loading...}> +

Stream Details

+
Sandbox ID: {stream.sandboxId}
+
Playback ID: {stream.playbackId}
+ + +
+ ) +} diff --git a/apps/web/src/app/stream/sandbox/page.tsx b/apps/web/src/app/stream/sandbox/page.tsx deleted file mode 100644 index ebe11f966..000000000 --- a/apps/web/src/app/stream/sandbox/page.tsx +++ /dev/null @@ -1,66 +0,0 @@ -'use client' - -import { useSearchParams } from 'next/navigation' -import { useEffect, useState, Suspense } from 'react' -// @ts-ignore -import MuxPlayer from '@mux/mux-player-react' - - - -interface SandboxStream { - sandboxId: string - playbackId: string -} - -export default function StreamPage() { - const searchParams = useSearchParams() - const sandboxId = searchParams.get('sandboxId') - const [stream, setStream] = useState(null) - const [error, setError] = useState(null) - - useEffect(() => { - const fetchStream = async () => { - if (sandboxId) { - try { - const response = await fetch(`/api/stream/sandbox?sandboxId=${sandboxId}`) - if (!response.ok) { - throw new Error('Network response was not ok') - } - const data = await response.json() - setStream(data) - } catch (err) { - setError(err.message) - } - } - } - - fetchStream() - }, [sandboxId]) - - if (error) { - return
Error loading stream: {error}
- } - - if (!stream) { - return
Stream not found
- } - console.log('stream', stream) - - return ( - Loading...}> - hello -

Stream Details

-
Sandbox ID: {stream.sandboxId}
-
Playback ID: {stream.playbackId}
- - -
- ) -} \ No newline at end of file diff --git a/apps/web/src/types/mux-player-react.d.ts b/apps/web/src/types/mux-player-react.d.ts new file mode 100644 index 000000000..7c5d47e17 --- /dev/null +++ b/apps/web/src/types/mux-player-react.d.ts @@ -0,0 +1,9 @@ +declare module '@mux/mux-player-react' { + export interface MuxPlayerProps { + [key: string]: any; + playbackId: string; + metadata?: Record; + } + + export default function MuxPlayer(props: MuxPlayerProps): JSX.Element +} \ No newline at end of file From 5b566a54a132445573f5ff457967ea0af0985372 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 10:32:57 -0800 Subject: [PATCH 06/13] Cleanup page --- .../src/app/(dashboard)/dashboard/layout.tsx | 14 +++++++----- apps/web/src/app/layout.tsx | 13 +++++++++-- .../app/stream/sandbox/[sandboxId]/layout.tsx | 9 ++++++++ .../app/stream/sandbox/[sandboxId]/page.tsx | 22 +++++++++---------- apps/web/src/components/LayoutDashboard.tsx | 18 --------------- 5 files changed, 38 insertions(+), 38 deletions(-) create mode 100644 apps/web/src/app/stream/sandbox/[sandboxId]/layout.tsx delete mode 100644 apps/web/src/components/LayoutDashboard.tsx diff --git a/apps/web/src/app/(dashboard)/dashboard/layout.tsx b/apps/web/src/app/(dashboard)/dashboard/layout.tsx index bb8f8a0df..3fa45af74 100644 --- a/apps/web/src/app/(dashboard)/dashboard/layout.tsx +++ b/apps/web/src/app/(dashboard)/dashboard/layout.tsx @@ -1,12 +1,14 @@ -import { LayoutDashboard } from '@/components/LayoutDashboard' +import { FooterMain } from '@/components/Footer' import { Toaster } from '@/components/ui/toaster' - export default async function Layout({ children }) { return ( - - {children} - - +
+
+ {children} + +
+ +
) } diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 712e03eea..0f2f1083c 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -37,8 +37,18 @@ declare global { } } +export default async function RootLayout({ children, params }) { + const isSandboxRoute = params?.sandboxId !== undefined + + if (isSandboxRoute) { + return ( + + + {children} + + ) + } -export default async function RootLayout({ children }) { const pages = await glob('**/*.mdx', { cwd: 'src/app/(docs)/docs' }) const allSectionsEntries = (await Promise.all( pages.map(async filename => [ @@ -48,7 +58,6 @@ export default async function RootLayout({ children }) { )) as Array<[string, Array
]> const allSections = Object.fromEntries(allSectionsEntries) - return ( + {children} + + ) +} diff --git a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx index 1cb0e80a0..7df9c0944 100644 --- a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx +++ b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx @@ -34,18 +34,16 @@ export default async function StreamPage({ params }: { params: { sandboxId: stri } return ( - Loading...}> -

Stream Details

-
Sandbox ID: {stream.sandboxId}
-
Playback ID: {stream.playbackId}
- - + Loading stream...}> +
+ +
) } diff --git a/apps/web/src/components/LayoutDashboard.tsx b/apps/web/src/components/LayoutDashboard.tsx deleted file mode 100644 index 5262c828f..000000000 --- a/apps/web/src/components/LayoutDashboard.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { FooterMain } from '@/components/Footer' - -export function LayoutDashboard({ - children, -}: { - children: React.ReactNode -}) { - return ( -
-
- {children} -
- -
- ) -} - - From b670c0d8adb7f16b6189c500e3b7d3f655c7a28d Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 12:57:19 -0800 Subject: [PATCH 07/13] Customize the livestream video player --- apps/web/package.json | 2 -- apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 0a6df6d40..394414b58 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -36,8 +36,6 @@ "@supabase/supabase-js": "^2.36.0", "@tailwindcss/typography": "0.5.9", "@types/node": "20.6.3", - "@types/react": "18.2.48", - "@types/react-dom": "18.2.7", "@types/react-highlight-words": "^0.16.4", "@vercel/analytics": "^1.0.2", "acorn": "^8.8.1", diff --git a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx index 7df9c0944..fa2606a8c 100644 --- a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx +++ b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx @@ -37,11 +37,15 @@ export default async function StreamPage({ params }: { params: { sandboxId: stri Loading stream...}>
From fb14148df34866a59945764b27b865703a734813 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 12:57:29 -0800 Subject: [PATCH 08/13] Customize the livestream video player --- pnpm-lock.yaml | 445 ++++++++++++++++++++++++------------------------- 1 file changed, 215 insertions(+), 230 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 514984756..305edd7b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,7 +53,7 @@ importers: version: 9.0.1(encoding@0.1.13) '@mux/mux-player-react': specifier: ^3.1.0 - version: 3.1.0(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 3.1.0(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@next/mdx': specifier: ^14.2.5 version: 14.2.5(@mdx-js/loader@2.3.0(webpack@5.88.2))(@mdx-js/react@2.3.0(react@18.2.0)) @@ -62,19 +62,19 @@ importers: version: 0.87.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@radix-ui/react-alert-dialog': specifier: ^1.0.5 - version: 1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 - version: 2.0.6(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 2.0.6(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@radix-ui/react-popover': specifier: ^1.0.6 - version: 1.0.6(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 1.0.6(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 - version: 1.0.2(@types/react@18.2.48)(react@18.2.0) + version: 1.0.2(@types/react@18.3.11)(react@18.2.0) '@radix-ui/react-toast': specifier: ^1.1.5 - version: 1.1.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 1.1.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) '@sentry/nextjs': specifier: ^8.18.0 version: 8.18.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@14.2.5(@babel/core@7.24.9)(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)(webpack@5.88.2) @@ -102,12 +102,6 @@ importers: '@types/node': specifier: 20.6.3 version: 20.6.3 - '@types/react': - specifier: 18.2.48 - version: 18.2.48 - '@types/react-dom': - specifier: 18.2.7 - version: 18.2.7 '@types/react-highlight-words': specifier: ^0.16.4 version: 0.16.4 @@ -221,7 +215,7 @@ importers: version: 9.0.1 zustand: specifier: ^4.3.2 - version: 4.4.1(@types/react@18.2.48)(react@18.2.0) + version: 4.4.1(@types/react@18.3.11)(react@18.2.0) devDependencies: '@nodelib/fs.walk': specifier: ^2.0.0 @@ -9077,7 +9071,7 @@ snapshots: transitivePeerDependencies: - encoding - '@mux/mux-player-react@3.1.0(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@mux/mux-player-react@3.1.0(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@mux/mux-player': 3.1.0 '@mux/playback-core': 0.27.0 @@ -9085,7 +9079,7 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 '@mux/mux-player@3.1.0': @@ -9654,402 +9648,402 @@ snapshots: dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-context@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-context@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.11)(react@18.2.0) aria-hidden: 1.2.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.3.11)(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-direction@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-direction@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-id@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-id@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) aria-hidden: 1.2.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.3.11)(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-popover@1.0.6(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-popover@1.0.6(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-popper': 1.1.2(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-portal': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-popper': 1.1.2(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-portal': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.11)(react@18.2.0) aria-hidden: 1.2.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-remove-scroll: 2.5.5(@types/react@18.2.48)(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.3.11)(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-popper@1.1.2(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-popper@1.1.2(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.3.11)(react@18.2.0) '@radix-ui/rect': 1.0.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.3.11)(react@18.2.0) '@radix-ui/rect': 1.0.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-slot': 1.0.2(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-direction': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-id': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-slot@1.0.2(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-slot@1.0.2(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-toast@1.1.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-toast@1.1.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-context': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) - '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 - '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-use-rect@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-use-rect@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 '@radix-ui/rect': 1.0.1 react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-use-size@1.0.1(@types/react@18.2.48)(react@18.2.0)': + '@radix-ui/react-use-size@1.0.1(@types/react@18.3.11)(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.48)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.11)(react@18.2.0) react: 18.2.0 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: '@babel/runtime': 7.22.15 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.3.11)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 '@types/react-dom': 18.2.7 '@radix-ui/rect@1.0.1': @@ -10786,7 +10780,8 @@ snapshots: '@types/react-dom@18.2.7': dependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 + optional: true '@types/react-highlight-words@0.16.4': dependencies: @@ -12407,7 +12402,7 @@ snapshots: eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.28.1)(eslint@8.57.1) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint@8.57.1) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.1) eslint-plugin-react: 7.33.2(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.0(eslint@8.57.1) @@ -12431,7 +12426,7 @@ snapshots: enhanced-resolve: 5.15.0 eslint: 8.57.1 eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1) - eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint@8.57.1) + eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1) fast-glob: 3.3.1 get-tsconfig: 4.7.0 is-core-module: 2.13.0 @@ -12442,16 +12437,6 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 6.7.2(eslint@8.49.0)(typescript@5.5.3) - eslint: 8.57.1 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1): dependencies: debug: 3.2.7 @@ -12463,7 +12448,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint@8.57.1): + eslint-plugin-import@2.28.1(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1): dependencies: array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 @@ -12473,7 +12458,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.7.2(eslint@8.49.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.8.0(eslint@8.57.1)(typescript@5.1.6))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.0)(eslint@8.57.1) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -12484,7 +12469,7 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.14.2 optionalDependencies: - '@typescript-eslint/parser': 6.7.2(eslint@8.49.0)(typescript@5.5.3) + '@typescript-eslint/parser': 6.8.0(eslint@8.57.1)(typescript@5.1.6) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -13535,7 +13520,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 18.18.6 + '@types/node': 20.6.3 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -15309,33 +15294,33 @@ snapshots: react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.4(@types/react@18.2.48)(react@18.2.0): + react-remove-scroll-bar@2.3.4(@types/react@18.3.11)(react@18.2.0): dependencies: react: 18.2.0 - react-style-singleton: 2.2.1(@types/react@18.2.48)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.2.0) tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - react-remove-scroll@2.5.5(@types/react@18.2.48)(react@18.2.0): + react-remove-scroll@2.5.5(@types/react@18.3.11)(react@18.2.0): dependencies: react: 18.2.0 - react-remove-scroll-bar: 2.3.4(@types/react@18.2.48)(react@18.2.0) - react-style-singleton: 2.2.1(@types/react@18.2.48)(react@18.2.0) + react-remove-scroll-bar: 2.3.4(@types/react@18.3.11)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.3.11)(react@18.2.0) tslib: 2.6.2 - use-callback-ref: 1.3.0(@types/react@18.2.48)(react@18.2.0) - use-sidecar: 1.1.2(@types/react@18.2.48)(react@18.2.0) + use-callback-ref: 1.3.0(@types/react@18.3.11)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.3.11)(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - react-style-singleton@2.2.1(@types/react@18.2.48)(react@18.2.0): + react-style-singleton@2.2.1(@types/react@18.3.11)(react@18.2.0): dependencies: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.2.0 tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 react@18.2.0: dependencies: @@ -16537,20 +16522,20 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 - use-callback-ref@1.3.0(@types/react@18.2.48)(react@18.2.0): + use-callback-ref@1.3.0(@types/react@18.3.11)(react@18.2.0): dependencies: react: 18.2.0 tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 - use-sidecar@1.1.2(@types/react@18.2.48)(react@18.2.0): + use-sidecar@1.1.2(@types/react@18.3.11)(react@18.2.0): dependencies: detect-node-es: 1.1.0 react: 18.2.0 tslib: 2.6.2 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 use-sync-external-store@1.2.0(react@18.2.0): dependencies: @@ -16969,11 +16954,11 @@ snapshots: zod@3.22.4: {} - zustand@4.4.1(@types/react@18.2.48)(react@18.2.0): + zustand@4.4.1(@types/react@18.3.11)(react@18.2.0): dependencies: use-sync-external-store: 1.2.0(react@18.2.0) optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.11 react: 18.2.0 zwitch@2.0.4: {} From 6cc247d3676c8c67b585ef5766ae568bc1ad4b03 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 13:11:09 -0800 Subject: [PATCH 09/13] Center the player --- apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx index fa2606a8c..918e2bd39 100644 --- a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx +++ b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx @@ -35,7 +35,7 @@ export default async function StreamPage({ params }: { params: { sandboxId: stri return ( Loading stream...}> -
+
Date: Sat, 23 Nov 2024 13:28:00 -0800 Subject: [PATCH 10/13] Revert uninstalled types packages --- apps/web/package.json | 2 + apps/web/src/components/ui/Popover.tsx | 2 +- pnpm-lock.yaml | 247 +++++++++++++------------ 3 files changed, 127 insertions(+), 124 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index 394414b58..be9d7c2eb 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -79,6 +79,8 @@ "@nodelib/fs.walk": "^2.0.0", "@stylistic/eslint-plugin-ts": "^1.6.2", "@types/mdx": "^2.0.8", + "@types/react": "^18.3.11", + "@types/react-dom": "^18.3.1", "eslint-config-next": "14.2.5", "knip": "^2.25.2", "sharp": "^0.32.0", diff --git a/apps/web/src/components/ui/Popover.tsx b/apps/web/src/components/ui/Popover.tsx index ce5e43fed..00a011e87 100644 --- a/apps/web/src/components/ui/Popover.tsx +++ b/apps/web/src/components/ui/Popover.tsx @@ -16,7 +16,7 @@ const PopoverContent = React.forwardRef< Date: Sat, 23 Nov 2024 15:49:21 -0800 Subject: [PATCH 11/13] Resolve PR feedback --- apps/web/package.json | 2 +- apps/web/src/app/api/stream/sandbox/route.ts | 7 ------- apps/web/src/app/layout.tsx | 13 +------------ apps/web/src/components/ui/Popover.tsx | 2 +- apps/web/src/middleware.ts | 1 - apps/web/src/types/mux-player-react.d.ts | 4 ++++ 6 files changed, 7 insertions(+), 22 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index be9d7c2eb..119087c04 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -86,4 +86,4 @@ "sharp": "^0.32.0", "tailwind-scrollbar": "^3.0.5" } -} +} \ No newline at end of file diff --git a/apps/web/src/app/api/stream/sandbox/route.ts b/apps/web/src/app/api/stream/sandbox/route.ts index af875e079..09282e39a 100644 --- a/apps/web/src/app/api/stream/sandbox/route.ts +++ b/apps/web/src/app/api/stream/sandbox/route.ts @@ -14,14 +14,7 @@ const mux = new Mux({ }) export async function POST(request: Request) { - // TODO: UseG apiKey - // const apiKey = request.headers.get('X-API-Key') const { sandboxId } = await request.json() - console.log('sandboxId', sandboxId) - - // if (!apiKey) { - // return NextResponse.json({ error: 'Missing X-API-Key' }, { status: 400 }) - // } if (!sandboxId) { return NextResponse.json({ error: 'Missing sandboxId' }, { status: 400 }) diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 0f2f1083c..0587a02de 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -37,18 +37,7 @@ declare global { } } -export default async function RootLayout({ children, params }) { - const isSandboxRoute = params?.sandboxId !== undefined - - if (isSandboxRoute) { - return ( - - - {children} - - ) - } - +export default async function RootLayout({ children }) { const pages = await glob('**/*.mdx', { cwd: 'src/app/(docs)/docs' }) const allSectionsEntries = (await Promise.all( pages.map(async filename => [ diff --git a/apps/web/src/components/ui/Popover.tsx b/apps/web/src/components/ui/Popover.tsx index 00a011e87..ce5e43fed 100644 --- a/apps/web/src/components/ui/Popover.tsx +++ b/apps/web/src/components/ui/Popover.tsx @@ -16,7 +16,7 @@ const PopoverContent = React.forwardRef< { if (req.method !== 'GET') return NextResponse.next() const url = new URL(req.nextUrl.toString()) - console.log('url', url) url.protocol = 'https' url.port = '' diff --git a/apps/web/src/types/mux-player-react.d.ts b/apps/web/src/types/mux-player-react.d.ts index 7c5d47e17..d8c736b60 100644 --- a/apps/web/src/types/mux-player-react.d.ts +++ b/apps/web/src/types/mux-player-react.d.ts @@ -3,6 +3,10 @@ declare module '@mux/mux-player-react' { [key: string]: any; playbackId: string; metadata?: Record; + autoplay?: boolean; + muted?: boolean; + themeProps?: Record; + streamType?: 'on-demand' | 'live'; } export default function MuxPlayer(props: MuxPlayerProps): JSX.Element From a6b312165cb2fe45bb01572b6a5c8886ae2f79d2 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 16:24:39 -0800 Subject: [PATCH 12/13] Remove unnecessary types file for MuxPlayer --- apps/web/src/types/mux-player-react.d.ts | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 apps/web/src/types/mux-player-react.d.ts diff --git a/apps/web/src/types/mux-player-react.d.ts b/apps/web/src/types/mux-player-react.d.ts deleted file mode 100644 index d8c736b60..000000000 --- a/apps/web/src/types/mux-player-react.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -declare module '@mux/mux-player-react' { - export interface MuxPlayerProps { - [key: string]: any; - playbackId: string; - metadata?: Record; - autoplay?: boolean; - muted?: boolean; - themeProps?: Record; - streamType?: 'on-demand' | 'live'; - } - - export default function MuxPlayer(props: MuxPlayerProps): JSX.Element -} \ No newline at end of file From c3d5bda61d59830955cf1438a069e921f5173432 Mon Sep 17 00:00:00 2001 From: Vasek Mlejnsky Date: Sat, 23 Nov 2024 17:37:23 -0800 Subject: [PATCH 13/13] Improve security for sandbox video stream by introducing token --- apps/web/package.json | 2 +- .../api/stream/sandbox/[sandboxId]/route.ts | 42 +++++++++++ apps/web/src/app/api/stream/sandbox/route.ts | 43 +++++++++++- .../app/stream/sandbox/[sandboxId]/layout.tsx | 9 --- .../app/stream/sandbox/[sandboxId]/page.tsx | 21 ++++-- apps/web/src/lib/utils.ts | 7 ++ pnpm-lock.yaml | 70 ++++--------------- 7 files changed, 122 insertions(+), 72 deletions(-) create mode 100644 apps/web/src/app/api/stream/sandbox/[sandboxId]/route.ts delete mode 100644 apps/web/src/app/stream/sandbox/[sandboxId]/layout.tsx diff --git a/apps/web/package.json b/apps/web/package.json index 119087c04..074d2bd73 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -42,7 +42,7 @@ "autoprefixer": "^10.4.7", "class-variance-authority": "^0.7.0", "clsx": "^1.2.1", - "e2b": "^0.16.2", + "e2b": "^1.0.5", "fast-glob": "^3.3.0", "fast-xml-parser": "^4.3.3", "flexsearch": "^0.7.31", diff --git a/apps/web/src/app/api/stream/sandbox/[sandboxId]/route.ts b/apps/web/src/app/api/stream/sandbox/[sandboxId]/route.ts new file mode 100644 index 000000000..e4b26773c --- /dev/null +++ b/apps/web/src/app/api/stream/sandbox/[sandboxId]/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server' +import { createClient } from '@supabase/supabase-js' +import { verifySandbox } from '@/lib/utils' + +const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! +const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY! + +const supabase = createClient(supabaseUrl, supabaseServiceKey) + +export async function GET(request: Request, { params }: { params: { sandboxId: string } }) { + const apiKey = request.headers.get('X-API-Key') + const sandboxId = params.sandboxId + + if (!sandboxId) { + return NextResponse.json({ error: 'Missing sandbox ID' }, { status: 400 }) + } + + if (!apiKey) { + return NextResponse.json({ error: 'Missing E2B API Key' }, { status: 400 }) + } + + if (!(await verifySandbox(apiKey, sandboxId))) { + return NextResponse.json({ error: 'Invalid E2B API Key' }, { status: 401 }) + } + + const { data: stream, error } = await supabase + .from('sandbox_streams') + .select('token') + .eq('sandbox_id', sandboxId) + .single() + + if (error) { + return NextResponse.json({ error: `Failed to retrieve stream - ${error.message}` }, { status: 500 }) + } + + if (!stream) { + return NextResponse.json({ error: `Stream not found for sandbox ${sandboxId}` }, { status: 404 }) + } + + return NextResponse.json({ token: stream.token }, { status: 200 }) +} + diff --git a/apps/web/src/app/api/stream/sandbox/route.ts b/apps/web/src/app/api/stream/sandbox/route.ts index 09282e39a..754e2dde4 100644 --- a/apps/web/src/app/api/stream/sandbox/route.ts +++ b/apps/web/src/app/api/stream/sandbox/route.ts @@ -1,7 +1,7 @@ import Mux from '@mux/mux-node' import { NextResponse } from 'next/server' - import { createClient } from '@supabase/supabase-js' +import { verifySandbox } from '@/lib/utils' const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL! const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY! @@ -13,13 +13,40 @@ const mux = new Mux({ tokenSecret: process.env.MUX_TOKEN_SECRET }) + +// Create a new live stream and return the stream key export async function POST(request: Request) { + const apiKey = request.headers.get('X-API-Key') const { sandboxId } = await request.json() if (!sandboxId) { return NextResponse.json({ error: 'Missing sandboxId' }, { status: 400 }) } + if (!apiKey) { + return NextResponse.json({ error: 'Missing E2B API Key' }, { status: 400 }) + } + + if (!(await verifySandbox(apiKey, sandboxId))) { + return NextResponse.json({ error: 'Invalid E2B API Key' }, { status: 401 }) + } + + // Check if a stream already exists for the sandbox + const { data: existingStream, error: existingStreamError } = await supabase + .from('sandbox_streams') + .select('token') + .eq('sandbox_id', sandboxId) + .single() + + if (existingStreamError && existingStreamError.code !== 'PGRST116') { + return NextResponse.json({ error: `Failed to check existing stream - ${existingStreamError.message}` }, { status: 500 }) + } + + if (existingStream) { + return NextResponse.json({ error: `Stream for the sandbox '${sandboxId}' already exists. There can be only one stream per sandbox.` }, { status: 400 }) + } + + // The stream doesn't exist yet, so create a new live stream const liveStream = await mux.video.liveStreams.create({ latency_mode: 'low', reconnect_window: 60, @@ -31,9 +58,19 @@ export async function POST(request: Request) { return NextResponse.json({ error: 'Failed to create live stream' }, { status: 500 }) } - await supabase + const { data, error }: { data: { token: string } | null, error: any } = await supabase .from('sandbox_streams') .insert([{ sandbox_id: sandboxId, playback_id: liveStream.playback_ids[0].id }]) + .select('token') + .single() + + if (error) { + return NextResponse.json({ error: `Failed to insert and retrieve token - ${error.message}` }, { status: 500 }) + } + + if (!data) { + return NextResponse.json({ error: 'Failed to insert and retrieve token - no data' }, { status: 500 }) + } - return NextResponse.json({ streamKey: liveStream.stream_key }, { status: 201 }) + return NextResponse.json({ streamKey: liveStream.stream_key, token: data.token }, { status: 201 }) } diff --git a/apps/web/src/app/stream/sandbox/[sandboxId]/layout.tsx b/apps/web/src/app/stream/sandbox/[sandboxId]/layout.tsx deleted file mode 100644 index ba57e405e..000000000 --- a/apps/web/src/app/stream/sandbox/[sandboxId]/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Fragment } from 'react' - -export default async function Layout({ children }) { - return ( - - {children} - - ) -} diff --git a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx index 918e2bd39..eb23c704e 100644 --- a/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx +++ b/apps/web/src/app/stream/sandbox/[sandboxId]/page.tsx @@ -12,11 +12,12 @@ interface SandboxStream { playbackId: string } -async function fetchStream(sandboxId: string): Promise { +async function fetchStream(sandboxId: string, token: string): Promise { const { data, error } = await supabase .from('sandbox_streams') .select('playback_id') .eq('sandbox_id', sandboxId) + .eq('token', token) .single() if (error || !data) { @@ -26,8 +27,20 @@ async function fetchStream(sandboxId: string): Promise { return { sandboxId, playbackId: data.playback_id } } -export default async function StreamPage({ params }: { params: { sandboxId: string } }) { - const stream = await fetchStream(params.sandboxId) +export default async function StreamPage({ + params, + searchParams // Add searchParams to props +}: { + params: { sandboxId: string } + searchParams: { token?: string } // Add type for searchParams +}) { + const token = searchParams.token + + if (!token) { + return
Missing token
+ } + + const stream = await fetchStream(params.sandboxId, token) if (!stream) { return
Stream not found
@@ -35,7 +48,7 @@ export default async function StreamPage({ params }: { params: { sandboxId: stri return ( Loading stream...
}> -
+
sandbox.sandboxId === sandboxId) +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1870d2672..3bf18285b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -121,8 +121,8 @@ importers: specifier: ^1.2.1 version: 1.2.1 e2b: - specifier: ^0.16.2 - version: 0.16.2 + specifier: ^1.0.5 + version: 1.0.5 fast-glob: specifier: ^3.3.0 version: 3.3.1 @@ -3979,14 +3979,14 @@ packages: duplexer3@0.1.5: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} - e2b@0.16.2: - resolution: {integrity: sha512-xKmVK4ipgVQPJ/uyyrfH9LnaawERRWt8U2UZhdhGfzdL/QU/OpBjuhoIbFCv1Uy6qXV4nIiJ6Nw4MBC4HmXf1g==} - engines: {node: '>=18'} - e2b@1.0.1: resolution: {integrity: sha512-A3T56Dso60AXTJO+V0zUNecYXDQB9jv6nm94DpLuEshjlk2MfbCF99rHgYUbOp9IOmh3EBv0RdEGIY5l4zJZQA==} engines: {node: '>=18'} + e2b@1.0.5: + resolution: {integrity: sha512-0c2xqNQfVcVBmETsd1bXWCYaN3iVl7m81dJVcjB7O2/c15A7t0s/FkydcZGzVvfZchj40/1f09AdjGX6nk1eNQ==} + engines: {node: '>=18'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -5077,11 +5077,6 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isomorphic-ws@5.0.0: - resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} - peerDependencies: - ws: '*' - iterable-lookahead@1.0.0: resolution: {integrity: sha512-hJnEP2Xk4+44DDwJqUQGdXal5VbyeWLaPyDl2AQc242Zr7iqz4DgpQOrEzglWVMGHMDCkguLHEKxd1+rOsmgSQ==} engines: {node: '>=4'} @@ -6030,10 +6025,6 @@ packages: openapi-fetch@0.9.8: resolution: {integrity: sha512-zM6elH0EZStD/gSiNlcPrzXcVQ/pZo3BDvC6CDwRDUt1dDzxlshpmQnpD6cZaJ39THaSmwVCxxRrPKNM1hHrDg==} - openapi-typescript-fetch@1.1.3: - resolution: {integrity: sha512-smLZPck4OkKMNExcw8jMgrMOGgVGx2N/s6DbKL2ftNl77g5HfoGpZGFy79RBzU/EkaO0OZpwBnslfdBfh7ZcWg==} - engines: {node: '>= 12.0.0', npm: '>= 7.0.0'} - openapi-typescript-helpers@0.0.8: resolution: {integrity: sha512-1eNjQtbfNi5Z/kFhagDIaIRj6qqDzhjNJKz8cmMW0CVdGwT6e1GLbAfgI0d28VTJa1A8jz82jm/4dG8qNoNS8g==} @@ -6166,9 +6157,6 @@ packages: parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -7870,18 +7858,6 @@ packages: write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - ws@8.15.1: - resolution: {integrity: sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.18.0: resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} @@ -12120,18 +12096,6 @@ snapshots: duplexer3@0.1.5: {} - e2b@0.16.2: - dependencies: - isomorphic-ws: 5.0.0(ws@8.15.1(bufferutil@4.0.8)(utf-8-validate@6.0.3)) - normalize-path: 3.0.0 - openapi-typescript-fetch: 1.1.3 - path-browserify: 1.0.1 - platform: 1.3.6 - ws: 8.15.1(bufferutil@4.0.8)(utf-8-validate@6.0.3) - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 6.0.3 - e2b@1.0.1: dependencies: '@bufbuild/protobuf': 1.10.0 @@ -12141,6 +12105,15 @@ snapshots: openapi-fetch: 0.9.8 platform: 1.3.6 + e2b@1.0.5: + dependencies: + '@bufbuild/protobuf': 2.2.2 + '@connectrpc/connect': 2.0.0-rc.3(@bufbuild/protobuf@2.2.2) + '@connectrpc/connect-web': 2.0.0-rc.3(@bufbuild/protobuf@2.2.2)(@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.2.2)) + compare-versions: 6.1.1 + openapi-fetch: 0.9.8 + platform: 1.3.6 + eastasianwidth@0.2.0: {} easy-table@1.2.0: @@ -13493,10 +13466,6 @@ snapshots: isexe@2.0.0: {} - isomorphic-ws@5.0.0(ws@8.15.1(bufferutil@4.0.8)(utf-8-validate@6.0.3)): - dependencies: - ws: 8.15.1(bufferutil@4.0.8)(utf-8-validate@6.0.3) - iterable-lookahead@1.0.0: {} iterator.prototype@1.1.2: @@ -14812,8 +14781,6 @@ snapshots: dependencies: openapi-typescript-helpers: 0.0.8 - openapi-typescript-fetch@1.1.3: {} - openapi-typescript-helpers@0.0.8: {} openapi-typescript@6.7.6: @@ -14980,8 +14947,6 @@ snapshots: parse5@6.0.1: {} - path-browserify@1.0.1: {} - path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -16859,11 +16824,6 @@ snapshots: signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 - ws@8.15.1(bufferutil@4.0.8)(utf-8-validate@6.0.3): - optionalDependencies: - bufferutil: 4.0.8 - utf-8-validate: 6.0.3 - ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.3): optionalDependencies: bufferutil: 4.0.8