From f2c0abbcdc9354d2d4784546c41847b5523d6444 Mon Sep 17 00:00:00 2001 From: Izan Gil <66965250+SrIzan10@users.noreply.github.com> Date: Sun, 23 Mar 2025 00:14:14 +0100 Subject: [PATCH] feat: initial chat and abstract auth away from next --- apps/chat/.gitignore | 28 +++++++++++++ apps/chat/README.md | 8 ++++ apps/chat/package.json | 19 +++++++++ apps/chat/src/3d.txt | 15 +++++++ apps/chat/src/index.ts | 27 +++++++++++++ apps/chat/tsconfig.json | 14 +++++++ apps/web/next.config.mjs | 8 ++++ apps/web/package.json | 1 + .../(protected)/api/rtmp/hls/[path]/route.ts | 2 +- .../(protected)/api/rtmp/streamKey/route.ts | 2 +- .../api/stream/chat/[username]/route.ts | 2 +- .../(protected)/api/stream/follow/route.ts | 2 +- .../app/(protected)/api/stream/info/route.ts | 2 +- apps/web/src/app/(protected)/layout.tsx | 2 +- .../app/(public)/auth/slack/callback/route.ts | 2 +- apps/web/src/app/(public)/auth/slack/route.ts | 2 +- apps/web/src/app/(public)/onboarding/page.tsx | 2 +- apps/web/src/app/(public)/page.tsx | 2 +- apps/web/src/app/layout.tsx | 2 +- .../app/EditLivestream/EditLivestream.tsx | 2 +- apps/web/src/lib/auth/index.ts | 29 -------------- apps/web/src/lib/auth/personalChannel.ts | 4 +- apps/web/src/lib/auth/validate.ts | 31 +++++++++++++++ apps/web/src/lib/form/actions.ts | 2 +- packages/auth/package.json | 12 ++++++ packages/auth/src/index.ts | 39 +++++++++++++++++++ turbo.json | 2 +- yarn.lock | 37 +++++++++++++++--- 28 files changed, 250 insertions(+), 50 deletions(-) create mode 100644 apps/chat/.gitignore create mode 100644 apps/chat/README.md create mode 100644 apps/chat/package.json create mode 100644 apps/chat/src/3d.txt create mode 100644 apps/chat/src/index.ts create mode 100644 apps/chat/tsconfig.json create mode 100644 apps/web/src/lib/auth/validate.ts create mode 100644 packages/auth/package.json create mode 100644 packages/auth/src/index.ts diff --git a/apps/chat/.gitignore b/apps/chat/.gitignore new file mode 100644 index 0000000..36fabb6 --- /dev/null +++ b/apps/chat/.gitignore @@ -0,0 +1,28 @@ +# dev +.yarn/ +!.yarn/releases +.vscode/* +!.vscode/launch.json +!.vscode/*.code-snippets +.idea/workspace.xml +.idea/usage.statistics.xml +.idea/shelf + +# deps +node_modules/ + +# env +.env +.env.production + +# logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# misc +.DS_Store diff --git a/apps/chat/README.md b/apps/chat/README.md new file mode 100644 index 0000000..e12b31d --- /dev/null +++ b/apps/chat/README.md @@ -0,0 +1,8 @@ +``` +npm install +npm run dev +``` + +``` +open http://localhost:3000 +``` diff --git a/apps/chat/package.json b/apps/chat/package.json new file mode 100644 index 0000000..cc99b20 --- /dev/null +++ b/apps/chat/package.json @@ -0,0 +1,19 @@ +{ + "name": "@hctv/chat", + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "tsx watch src/index.ts" + }, + "dependencies": { + "@hctv/db": "*", + "@hono/node-server": "^1.14.0", + "@hono/node-ws": "^1.1.0", + "@oslojs/encoding": "^1.1.0", + "hono": "^4.7.5" + }, + "devDependencies": { + "@types/node": "^20.11.17", + "tsx": "^4.7.1" + } +} diff --git a/apps/chat/src/3d.txt b/apps/chat/src/3d.txt new file mode 100644 index 0000000..b5db774 --- /dev/null +++ b/apps/chat/src/3d.txt @@ -0,0 +1,15 @@ + ,---, ___ +,--.' | ,--.'|_ +| | : | | :,' +: : : : : ' : .---. +: | |,--. ,---. .;__,' / /. ./| +| : ' | / \| | | .-' . ' | +| | /' : / / ':__,'| : /___/ \: | +' : | | |. ' / ' : |__. \ ' . +| | ' | :' ; :__ | | '.'|\ \ ' +| : :_:,'' | '.'| ; : ; \ \ +| | ,' | : : | , / \ \ | +`--'' \ \ / ---`-' '---" + `----' + +This is hctv's chat backend. There's not much here, so go back to where you came from :) \ No newline at end of file diff --git a/apps/chat/src/index.ts b/apps/chat/src/index.ts new file mode 100644 index 0000000..8292e11 --- /dev/null +++ b/apps/chat/src/index.ts @@ -0,0 +1,27 @@ +import { serve } from '@hono/node-server' +import { createNodeWebSocket } from '@hono/node-ws' +import { Hono } from 'hono' +import { readFile } from 'node:fs/promises' + +const threed = await readFile('./src/3d.txt', 'utf-8') + +const app = new Hono() +const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app }) + +app.get('/', async (c) => { + return c.text(threed) +}) + +app.get( + '/ws', + upgradeWebSocket((c) => ({ + // https://hono.dev/helpers/websocket + })) +) + +serve({ + fetch: app.fetch, + port: 8000, +}, (info) => { + console.log(`Server is running on http://localhost:${info.port}`) +}) diff --git a/apps/chat/tsconfig.json b/apps/chat/tsconfig.json new file mode 100644 index 0000000..7719c23 --- /dev/null +++ b/apps/chat/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "NodeNext", + "strict": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "types": [ + "node" + ], + "jsx": "react-jsx", + "jsxImportSource": "hono/jsx", + } +} \ No newline at end of file diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 8f57203..6212d3c 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -25,6 +25,14 @@ const nextConfig = { reactStrictMode: false, output: 'standalone', outputFileTracingRoot: path.join(__dirname, '../../'), + async rewrites() { + return [ + { + source: '/api/chat/:path*', + destination: `http://localhost:8000/:path*`, + }, + ]; + } }; export default nextConfig; diff --git a/apps/web/package.json b/apps/web/package.json index 68fc190..864de28 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,6 +14,7 @@ "check-types": "tsc --noEmit" }, "dependencies": { + "@hctv/auth": "*", "@hctv/db": "*", "@hookform/resolvers": "^3.9.1", "@livekit/components-react": "^2.7.0", diff --git a/apps/web/src/app/(protected)/api/rtmp/hls/[path]/route.ts b/apps/web/src/app/(protected)/api/rtmp/hls/[path]/route.ts index 87aef75..76888aa 100644 --- a/apps/web/src/app/(protected)/api/rtmp/hls/[path]/route.ts +++ b/apps/web/src/app/(protected)/api/rtmp/hls/[path]/route.ts @@ -1,4 +1,4 @@ -import { validateRequest } from "@/lib/auth"; +import { validateRequest } from '@/lib/auth/validate'; import fsP from 'fs/promises'; import fs from 'fs'; diff --git a/apps/web/src/app/(protected)/api/rtmp/streamKey/route.ts b/apps/web/src/app/(protected)/api/rtmp/streamKey/route.ts index 801e628..05366eb 100644 --- a/apps/web/src/app/(protected)/api/rtmp/streamKey/route.ts +++ b/apps/web/src/app/(protected)/api/rtmp/streamKey/route.ts @@ -1,4 +1,4 @@ -import { validateRequest } from "@/lib/auth"; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; import { NextRequest } from "next/server"; diff --git a/apps/web/src/app/(protected)/api/stream/chat/[username]/route.ts b/apps/web/src/app/(protected)/api/stream/chat/[username]/route.ts index 58804dd..d7c4cdb 100644 --- a/apps/web/src/app/(protected)/api/stream/chat/[username]/route.ts +++ b/apps/web/src/app/(protected)/api/stream/chat/[username]/route.ts @@ -1,4 +1,4 @@ -import { lucia } from '@/lib/auth'; +import { lucia } from '@hctv/auth'; import prisma from '@hctv/db'; import { resolveUserPersonalChannel } from '@/lib/db/resolve'; import type { WebSocket } from 'ws'; diff --git a/apps/web/src/app/(protected)/api/stream/follow/route.ts b/apps/web/src/app/(protected)/api/stream/follow/route.ts index 72ed48b..f3284f4 100644 --- a/apps/web/src/app/(protected)/api/stream/follow/route.ts +++ b/apps/web/src/app/(protected)/api/stream/follow/route.ts @@ -1,4 +1,4 @@ -import { validateRequest } from '@/lib/auth'; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; import { NextRequest } from 'next/server'; diff --git a/apps/web/src/app/(protected)/api/stream/info/route.ts b/apps/web/src/app/(protected)/api/stream/info/route.ts index ad02f8a..da437d0 100644 --- a/apps/web/src/app/(protected)/api/stream/info/route.ts +++ b/apps/web/src/app/(protected)/api/stream/info/route.ts @@ -1,4 +1,4 @@ -import { validateRequest } from '@/lib/auth'; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; import type { NextRequest } from 'next/server'; diff --git a/apps/web/src/app/(protected)/layout.tsx b/apps/web/src/app/(protected)/layout.tsx index ff30efd..63212e5 100644 --- a/apps/web/src/app/(protected)/layout.tsx +++ b/apps/web/src/app/(protected)/layout.tsx @@ -1,4 +1,4 @@ -import { validateRequest } from '@/lib/auth'; +import { validateRequest } from '@/lib/auth/validate'; import { redirect, RedirectType } from 'next/navigation'; export default async function Layout({ children }: { children: React.ReactNode }) { diff --git a/apps/web/src/app/(public)/auth/slack/callback/route.ts b/apps/web/src/app/(public)/auth/slack/callback/route.ts index a0af4b6..6f6a210 100644 --- a/apps/web/src/app/(public)/auth/slack/callback/route.ts +++ b/apps/web/src/app/(public)/auth/slack/callback/route.ts @@ -1,4 +1,4 @@ -import { slack, lucia } from '@/lib/auth'; +import { slack, lucia } from '@hctv/auth'; import { cookies as nextCookies } from 'next/headers'; import { decodeIdToken, OAuth2RequestError } from 'arctic'; import { generateIdFromEntropySize } from 'lucia'; diff --git a/apps/web/src/app/(public)/auth/slack/route.ts b/apps/web/src/app/(public)/auth/slack/route.ts index 4084be8..e27d48b 100644 --- a/apps/web/src/app/(public)/auth/slack/route.ts +++ b/apps/web/src/app/(public)/auth/slack/route.ts @@ -1,5 +1,5 @@ import { generateState } from "arctic"; -import { slack } from "@/lib/auth"; +import { slack } from '@hctv/auth'; import { cookies } from "next/headers"; export async function GET(): Promise { diff --git a/apps/web/src/app/(public)/onboarding/page.tsx b/apps/web/src/app/(public)/onboarding/page.tsx index 503398b..c71fde8 100644 --- a/apps/web/src/app/(public)/onboarding/page.tsx +++ b/apps/web/src/app/(public)/onboarding/page.tsx @@ -1,4 +1,4 @@ -import { validateRequest } from "@/lib/auth"; +import { validateRequest } from '@/lib/auth/validate'; import { redirect } from "next/navigation"; import OnboardingClient from "./page.client"; diff --git a/apps/web/src/app/(public)/page.tsx b/apps/web/src/app/(public)/page.tsx index e2f518a..de0953c 100644 --- a/apps/web/src/app/(public)/page.tsx +++ b/apps/web/src/app/(public)/page.tsx @@ -1,7 +1,7 @@ import LandingPage from '@/components/app/LandingPage/LandingPage'; import { Card, CardContent } from '@/components/ui/card'; import ConfusedDino from '@/components/ui/confuseddino'; -import { validateRequest } from '@/lib/auth'; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; import { Avatar, AvatarImage, AvatarFallback } from '@radix-ui/react-avatar'; import Image from 'next/image'; diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 966b6b6..d7deebd 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -3,7 +3,7 @@ import { Inter } from 'next/font/google'; import './globals.css'; import Navbar from '@/components/app/NavBar/NavBar'; import { SessionProvider } from '@/lib/providers/SessionProvider'; -import { validateRequest } from '@/lib/auth'; +import { validateRequest } from '@/lib/auth/validate'; import { Toaster } from '@/components/ui/sonner'; import { ThemeProvider } from '@/lib/providers/ThemeProvider'; import { SidebarProvider } from '@/components/ui/sidebar'; diff --git a/apps/web/src/components/app/EditLivestream/EditLivestream.tsx b/apps/web/src/components/app/EditLivestream/EditLivestream.tsx index 68d66f3..4a8f280 100644 --- a/apps/web/src/components/app/EditLivestream/EditLivestream.tsx +++ b/apps/web/src/components/app/EditLivestream/EditLivestream.tsx @@ -1,4 +1,4 @@ -import { validateRequest } from '@/lib/auth'; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; import EditLivestreamDialog from './dialog'; diff --git a/apps/web/src/lib/auth/index.ts b/apps/web/src/lib/auth/index.ts index 76a52b1..5fbe8eb 100644 --- a/apps/web/src/lib/auth/index.ts +++ b/apps/web/src/lib/auth/index.ts @@ -1,8 +1,6 @@ import { PrismaAdapter } from '@lucia-auth/adapter-prisma'; import { Lucia } from 'lucia'; import prisma from '@hctv/db'; -import { cache } from 'react'; -import { cookies } from 'next/headers'; import { Slack } from 'arctic'; const adapter = new PrismaAdapter(prisma.session, prisma.user); @@ -26,33 +24,6 @@ export const lucia = new Lucia(adapter, { }; }, }); -export const validateRequest = cache(async () => { - const sessionId = (await cookies()).get(lucia.sessionCookieName)?.value ?? null; - - if (!sessionId) - return { - user: null, - session: null, - }; - - const { user, session } = await lucia.validateSession(sessionId); - try { - if (session && session.fresh) { - const sessionCookie = lucia.createSessionCookie(session.id); - (await cookies()).set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes); - } - if (!session) { - const sessionCookie = lucia.createBlankSessionCookie(); - (await cookies()).set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes); - } - } catch { - // Next.js throws error attempting to set cookies when rendering page - } - return { - user, - session, - }; -}); declare module 'lucia' { interface Register { diff --git a/apps/web/src/lib/auth/personalChannel.ts b/apps/web/src/lib/auth/personalChannel.ts index 761a891..dffb144 100644 --- a/apps/web/src/lib/auth/personalChannel.ts +++ b/apps/web/src/lib/auth/personalChannel.ts @@ -1,4 +1,4 @@ -import { validateRequest } from "."; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; export async function getPersonalChannel(id?: string) { @@ -15,4 +15,4 @@ export async function getPersonalChannel(id?: string) { return null; } return db.personalChannel; -} \ No newline at end of file +} diff --git a/apps/web/src/lib/auth/validate.ts b/apps/web/src/lib/auth/validate.ts new file mode 100644 index 0000000..1fab423 --- /dev/null +++ b/apps/web/src/lib/auth/validate.ts @@ -0,0 +1,31 @@ +import { cookies } from "next/headers"; +import { cache } from "react"; +import { lucia } from '@hctv/auth'; + +export const validateRequest = cache(async () => { + const sessionId = (await cookies()).get(lucia.sessionCookieName)?.value ?? null; + + if (!sessionId) + return { + user: null, + session: null, + }; + + const { user, session } = await lucia.validateSession(sessionId); + try { + if (session && session.fresh) { + const sessionCookie = lucia.createSessionCookie(session.id); + (await cookies()).set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes); + } + if (!session) { + const sessionCookie = lucia.createBlankSessionCookie(); + (await cookies()).set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes); + } + } catch { + // Next.js throws error attempting to set cookies when rendering page + } + return { + user, + session, + }; +}); \ No newline at end of file diff --git a/apps/web/src/lib/form/actions.ts b/apps/web/src/lib/form/actions.ts index 5499788..25dec0f 100644 --- a/apps/web/src/lib/form/actions.ts +++ b/apps/web/src/lib/form/actions.ts @@ -1,7 +1,7 @@ 'use server'; import { revalidatePath } from 'next/cache'; -import { validateRequest } from '../auth'; +import { validateRequest } from '@/lib/auth/validate'; import prisma from '@hctv/db'; import zodVerify from '../zodVerify'; import { onboardSchema, streamInfoEditSchema } from './zod'; diff --git a/packages/auth/package.json b/packages/auth/package.json new file mode 100644 index 0000000..b0d740d --- /dev/null +++ b/packages/auth/package.json @@ -0,0 +1,12 @@ +{ + "name": "@hctv/auth", + "version": "0.0.0", + "exports": { + ".": "./src/index.ts" + }, + "dependencies": { + "@hctv/db": "*", + "@lucia-auth/adapter-prisma": "^4.0.1", + "arctic": "^3.1.1" + } +} diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts new file mode 100644 index 0000000..5fbe8eb --- /dev/null +++ b/packages/auth/src/index.ts @@ -0,0 +1,39 @@ +import { PrismaAdapter } from '@lucia-auth/adapter-prisma'; +import { Lucia } from 'lucia'; +import prisma from '@hctv/db'; +import { Slack } from 'arctic'; + +const adapter = new PrismaAdapter(prisma.session, prisma.user); +export const slack = new Slack(process.env.SLACK_ID!, process.env.SLACK_SECRET!, process.env.SLACK_REDIRECT_URI!); + +export const lucia = new Lucia(adapter, { + sessionCookie: { + // this sets cookies with super long expiration + // since Next.js doesn't allow Lucia to extend cookie expiration when rendering pages + expires: false, + attributes: { + // set to `true` when using HTTPS + secure: process.env.NODE_ENV === 'production', + }, + }, + getUserAttributes: (attributes) => { + return { + slack_id: attributes.slack_id, + pfpUrl: attributes.pfpUrl, + hasOnboarded: attributes.hasOnboarded, + }; + }, +}); + +declare module 'lucia' { + interface Register { + Lucia: typeof lucia; + DatabaseUserAttributes: DatabaseUserAttributes; + } +} + +interface DatabaseUserAttributes { + slack_id: string; + pfpUrl: string; + hasOnboarded: boolean; +} diff --git a/turbo.json b/turbo.json index a07eb48..7c620d6 100644 --- a/turbo.json +++ b/turbo.json @@ -22,7 +22,7 @@ "cache": false }, "dd": { - "persistent": true, + "persistent": false, "cache": false }, "db:generate": { diff --git a/yarn.lock b/yarn.lock index 0c8ed4b..2edf565 100644 --- a/yarn.lock +++ b/yarn.lock @@ -455,6 +455,18 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== +"@hono/node-server@^1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.14.0.tgz#b64f7e6b10dbc0fa0642e8a0a1c03c2abf2b391c" + integrity sha512-YUCxJwgHRKSqjrdTk9e4VMGKN27MK5r4+MGPyZTgKH+IYbK+KtYbHeOcPGJ91KGGD6RIQiz2dAHxvjauNhOS8g== + +"@hono/node-ws@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@hono/node-ws/-/node-ws-1.1.0.tgz#aefb18f31a2e67d71787a5838110f156fa819183" + integrity sha512-uHaz1EPguJqsUmA+Jmhdi/DTRAMs2Fvcy7qno9E48rlK3WBtyGQw4u4DKlc+o18Nh1DGz2oA1n9hCzEyhVBeLw== + dependencies: + ws "^8.17.0" + "@hookform/resolvers@^3.9.1": version "3.10.0" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-3.10.0.tgz#7bfd18113daca4e57e27e1205b7d5a2d371aa59a" @@ -1478,7 +1490,7 @@ dependencies: undici-types "~6.20.0" -"@types/node@^20": +"@types/node@^20", "@types/node@^20.11.17": version "20.17.25" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.25.tgz#3135ad0af2b46a7689aa5ffb3ecafe1f50171a29" integrity sha512-bT+r2haIlplJUYtlZrEanFHdPIZTeiMeh/fSOEbOOfWf9uTn+lg8g0KU6Q3iMgjd9FLuuMAgfCNSkjUbxL6E3Q== @@ -2549,7 +2561,7 @@ esbuild-register@3.6.0: dependencies: debug "^4.3.4" -"esbuild@>=0.12 <1": +"esbuild@>=0.12 <1", esbuild@~0.25.0: version "0.25.1" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.1.tgz#a16b8d070b6ad4871935277bda6ccfe852e3fa2f" integrity sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ== @@ -2959,7 +2971,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@2.3.3, fsevents@~2.3.2: +fsevents@2.3.3, fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -3039,7 +3051,7 @@ get-symbol-description@^1.1.0: es-errors "^1.3.0" get-intrinsic "^1.2.6" -get-tsconfig@^4.10.0: +get-tsconfig@^4.10.0, get-tsconfig@^4.7.5: version "4.10.0" resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.0.tgz#403a682b373a823612475a4c2928c7326fc0f6bb" integrity sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A== @@ -3176,6 +3188,11 @@ hls.js@^1.5.11: resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.5.20.tgz#7eb23bb5e2595311d4e2761038ca6882673de7e2" integrity sha512-uu0VXUK52JhihhnN/MVVo1lvqNNuhoxkonqgO3IpjvQiGpJBdIXMGkofjQb/j9zvV7a1SW8U9g1FslWx/1HOiQ== +hono@^4.7.5: + version "4.7.5" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.7.5.tgz#5e28b48384971c16e011fe6f7b95668655d4b855" + integrity sha512-fDOK5W2C1vZACsgLONigdZTRZxuBqFtcKh7bUQ5cVSbwI2RWjloJDcgFOVzbQrlI6pCmhlTsVYZ7zpLj4m4qMQ== + htmlparser2@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23" @@ -5068,6 +5085,16 @@ tslib@2.8.1, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8. resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== +tsx@^4.7.1: + version "4.19.3" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.3.tgz#2bdbcb87089374d933596f8645615142ed727666" + integrity sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ== + dependencies: + esbuild "~0.25.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + turbo-darwin-64@2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.4.4.tgz#2508d9b3b358bb91e8745be3e62284621a2b8721" @@ -5392,7 +5419,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^8.18.1: +ws@^8.17.0, ws@^8.18.1: version "8.18.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==