00{idx + 1}
diff --git a/app/components/PageFeedback.tsx b/app/components/PageFeedback.tsx
new file mode 100644
index 00000000..7a97a929
--- /dev/null
+++ b/app/components/PageFeedback.tsx
@@ -0,0 +1,60 @@
+"use client";
+
+import { useState } from "react";
+import { usePathname } from "next/navigation";
+import { Button } from "@/app/components/ui/button";
+import { ThumbsUp, ThumbsDown } from "lucide-react";
+
+export function PageFeedback() {
+ const pathname = usePathname();
+ const [voted, setVoted] = useState<"helpful" | "not_helpful" | null>(null);
+
+ const handleVote = (vote: "helpful" | "not_helpful") => {
+ if (voted) return;
+
+ if (window.umami) {
+ // Umami 埋点: 记录用户是否有帮助的投票
+ window.umami.track("feedback_submit", {
+ page: pathname,
+ vote,
+ });
+ }
+ setVoted(vote);
+ };
+
+ if (voted) {
+ return (
+
+ Thanks for your feedback! / 感谢您的反馈!
+
+ );
+ }
+
+ return (
+
+
+ Was this page helpful? / 这篇文章有帮助吗?
+
+
+
+
+
+
+ );
+}
diff --git a/app/components/assistant-ui/SettingsDialog.tsx b/app/components/assistant-ui/SettingsDialog.tsx
index 9825faf8..a52c66b0 100644
--- a/app/components/assistant-ui/SettingsDialog.tsx
+++ b/app/components/assistant-ui/SettingsDialog.tsx
@@ -44,7 +44,7 @@ export const SettingsDialog = ({
return (
@@ -198,31 +237,66 @@ const ThreadWelcome: FC = () => {
);
};
-const ThreadWelcomeSuggestions: FC = () => {
+// 欢迎页面的初始建议组件
+interface ThreadWelcomeSuggestionsProps {
+ suggestions?: WelcomeSuggestion[];
+ isLoading?: boolean;
+}
+
+const ThreadWelcomeSuggestions: FC = ({
+ suggestions,
+ isLoading,
+}) => {
+ if (isLoading) {
+ return (
+
+ {/* 显示4个骨架屏来代表四条预取建议 */}
+ {[1, 2, 3, 4].map((i) => (
+
+ ))}
+
+ );
+ }
+
+ // 如果建议为空也没显示骨架屏(例如出错或加载失败),依然展示默认退避问题
+ const defaultSuggestions: WelcomeSuggestion[] = [
+ {
+ title: "总结本文",
+ label: "内容要点",
+ action: "请帮我总结一下当前页面的主要内容和要点",
+ },
+ {
+ title: "什么是基座大模型",
+ label: "概念解释",
+ action: "什么是基座大模型?请详细解释一下",
+ },
+ {
+ title: "解释技术概念",
+ label: "深入理解",
+ action: "请解释一下这个页面中提到的核心技术概念",
+ },
+ {
+ title: "学习建议",
+ label: "如何入门",
+ action: "基于当前内容,你能给出一些学习建议和入门路径吗?",
+ },
+ ];
+
+ const displaySuggestions = suggestions?.length
+ ? suggestions
+ : defaultSuggestions;
+
return (
- {[
- {
- title: "总结本文",
- label: "内容要点",
- action: "请帮我总结一下当前页面的主要内容和要点",
- },
- {
- title: "什么是基座大模型",
- label: "概念解释",
- action: "什么是基座大模型?请详细解释一下",
- },
- {
- title: "解释技术概念",
- label: "深入理解",
- action: "请解释一下这个页面中提到的核心技术概念",
- },
- {
- title: "学习建议",
- label: "如何入门",
- action: "基于当前内容,你能给出一些学习建议和入门路径吗?",
- },
- ].map((suggestedAction, index) => (
+ {displaySuggestions.map((suggestedAction, index) => (
{
);
};
+// 输入框组件 Props
interface ComposerProps {
isSettingsOpen: boolean;
onOpenChange: (open: boolean) => void;
onClearError?: () => void;
}
+// 输入框组件,负责处理用户输入和发送消息
const Composer: FC = ({
isSettingsOpen,
onOpenChange,
@@ -290,16 +366,14 @@ const Composer: FC = ({
return (
-
-
-
+ {/* 当没有消息时,显示空状态内容(现已经移到上面的Viewport内以统一滑动,这里可以置空或保留其它用途)*/}
{!hasActiveKey && (
-
+
Add your {providerLabel} API key in Settings to start chatting.
@@ -342,6 +416,7 @@ interface ComposerActionProps {
onClearError?: () => void;
}
+// 输入框操作按钮组件(发送、设置、取消)
const ComposerAction: FC
= ({
canSend,
isSettingsOpen,
@@ -415,6 +490,57 @@ const MessageError: FC = () => {
);
};
+// AI 消息组件
+// 正在思考的加载状态组件
+const ThreadThinking: FC = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+const AssistantMessageContent: FC = () => {
+ const message = useMessage() as unknown as {
+ status?: string | { type: string };
+ content?: string | unknown[];
+ };
+
+ const isRunning =
+ message.status === "in_progress" ||
+ (typeof message.status === "object" && message.status?.type === "running");
+
+ const hasContent =
+ message.content &&
+ (typeof message.content === "string"
+ ? message.content.length > 0
+ : Array.isArray(message.content)
+ ? message.content.length > 0
+ : !!message.content);
+
+ return (
+ <>
+
+
+ {/* 当正在生成且内容为空时显示加载动画 */}
+ {isRunning && !hasContent && (
+
+
+
+ )}
+
+
+ >
+ );
+};
+
const AssistantMessage: FC = () => {
return (
@@ -422,14 +548,8 @@ const AssistantMessage: FC = () => {
className="aui-assistant-message-root relative mx-auto w-full max-w-[var(--thread-max-width)] animate-in py-4 duration-200 fade-in slide-in-from-bottom-1 last:mb-24"
data-role="assistant"
>
-
-
-
+
@@ -441,6 +561,7 @@ const AssistantMessage: FC = () => {
);
};
+// AI 消息操作栏(复制、刷新)
const AssistantActionBar: FC = () => {
return (
{
);
};
+// 用户消息组件
const UserMessage: FC = () => {
return (
@@ -492,6 +614,7 @@ const UserMessage: FC = () => {
);
};
+// 用户消息操作栏(编辑)
const UserActionBar: FC = () => {
return (
{
);
};
+// 编辑输入框组件(用于编辑已发送的消息)
const EditComposer: FC = () => {
return (
@@ -534,6 +658,7 @@ const EditComposer: FC = () => {
);
};
+// 分支切换组件(用于在多次生成的回复之间切换)
const BranchPicker: FC
= ({
className,
...rest
@@ -563,3 +688,53 @@ const BranchPicker: FC = ({
);
};
+
+// 后续问题建议组件 Props
+interface ThreadFollowupSuggestionsProps {
+ suggestions?: string[];
+ isLoading?: boolean;
+}
+
+// 后续问题建议组件,显示 AI 生成的建议问题
+const ThreadFollowupSuggestions: FC = ({
+ suggestions,
+ isLoading,
+}) => {
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ if (!suggestions || suggestions.length === 0) return null;
+
+ return (
+
+
+ 建议提问
+
+
+ {suggestions.map((suggestion, index) => (
+
+
+
+ ))}
+
+
+ );
+};
diff --git a/app/components/float-window/FloatWindow.tsx b/app/components/float-window/FloatWindow.tsx
index 4b4cc29d..31cda913 100644
--- a/app/components/float-window/FloatWindow.tsx
+++ b/app/components/float-window/FloatWindow.tsx
@@ -1,8 +1,9 @@
"use client";
-import { useState, useEffect, useCallback, useRef } from "react";
+import { useState, useCallback } from "react";
import { usePathname } from "next/navigation";
import Image from "next/image";
+import { motion, AnimatePresence } from "motion/react";
import { activityEventsConfig } from "@/app/types/event";
import { cn } from "@/lib/utils";
import { X, ChevronUp, ExternalLink, Play } from "lucide-react";
@@ -33,42 +34,6 @@ export function FloatWindow() {
// 仅在首页 (/) 可见
const isHomePage = pathname === "/";
- const [position, setPosition] = useState<{ x: number; y: number } | null>(
- null,
- );
- const [isDragging, setIsDragging] = useState(false);
- const dragOffset = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
-
- const handlePointerDown = (e: React.PointerEvent) => {
- if (e.button !== 0) return;
- const el = e.currentTarget as HTMLElement;
- const rect = el.getBoundingClientRect();
- setIsDragging(true);
- dragOffset.current = {
- x: e.clientX - rect.left,
- y: e.clientY - rect.top,
- };
- if (!position) setPosition({ x: rect.left, y: rect.top });
- el.setPointerCapture(e.pointerId);
- };
-
- useEffect(() => {
- if (!isDragging) return;
- const handlePointerMove = (e: PointerEvent) => {
- setPosition({
- x: e.clientX - dragOffset.current.x,
- y: e.clientY - dragOffset.current.y,
- });
- };
- const handlePointerUp = () => setIsDragging(false);
- window.addEventListener("pointermove", handlePointerMove);
- window.addEventListener("pointerup", handlePointerUp);
- return () => {
- window.removeEventListener("pointermove", handlePointerMove);
- window.removeEventListener("pointerup", handlePointerUp);
- };
- }, [isDragging]);
-
const handleDismiss = useCallback(() => setIsDismissed(true), []);
const handleToggle = useCallback(() => setIsCollapsed((prev) => !prev), []);
@@ -78,147 +43,156 @@ export function FloatWindow() {
const currentEvent = latestEvent;
return (
- {
- if (node) node.style.touchAction = "none";
- }}
+
e.stopPropagation()} // Prevent conflicts
>
- {/* 极简折叠状态 */}
- {isCollapsed ? (
-
- ) : (
- /* 展开状态 - 报纸卡片 */
-
- {/* Header Bar */}
-
-
- The Daily Feed
-
-
-
-
-
-
-
- {/* Content */}
-
- {/* 图片区域 - 默认为灰度(暗黑模式除外) */}
-
-
- {/* 突发新闻徽章 */}
- {!currentEvent.deprecated && (
-
- Breaking
-
- )}
-
-
- {/* 标题与描述 */}
-
-
- {currentEvent.name}
-
-
- {currentEvent.deprecated
- ? "This event has concluded. View the archives for full coverage."
- : "Join us for this significant community event. Detailed coverage inside."}
-
-
- {/* 操作按钮 */}
- {currentEvent.deprecated && currentEvent.playback ? (
-
+ {isCollapsed ? (
+
+
+ Latest
+
+
+ ) : (
+ /* 展开状态 - 报纸卡片 */
+
+ {/* Header Bar */}
+
+
+ The Daily Feed
+
+
+
+
+
-
-
- )}
-
+
+ {/* Content */}
+
+ {/* 图片区域 - 默认为灰度(暗黑模式除外) */}
+
+
+ {/* 突发新闻徽章 */}
+ {!currentEvent.deprecated && (
+
+ Breaking
+
+ )}
+
+
+ {/* 标题与描述 */}
+
+
+ {currentEvent.name}
+
+
+ {currentEvent.deprecated
+ ? "This event has concluded. View the archives for full coverage."
+ : "Join us for this significant community event. Detailed coverage inside."}
+
+
+ {/* 操作按钮 */}
+ {currentEvent.deprecated && currentEvent.playback ? (
+
e.stopPropagation()}
+ className={cn(
+ "flex items-center justify-center gap-2 w-full px-4 py-2",
+ "border border-[#111111] dark:border-[#F9F9F7]",
+ "bg-transparent hover:bg-[#111111] hover:text-[#F9F9F7]",
+ "dark:hover:bg-[#F9F9F7] dark:hover:text-[#111111]",
+ "font-mono text-xs uppercase tracking-widest font-bold",
+ "transition-colors duration-200",
+ )}
+ >
+
+ Watch Replay
+
+ ) : (
+
e.stopPropagation()}
+ className={cn(
+ "flex items-center justify-center gap-2 w-full px-4 py-2",
+ "bg-[#111111] text-[#F9F9F7]",
+ "hover:bg-[#CC0000] hover:border-[#CC0000]",
+ "font-mono text-xs uppercase tracking-widest font-bold",
+ "transition-colors duration-200",
+ )}
+ >
+ Read More
+
+
+ )}
+
+
+
+ )}
+
+
);
}
diff --git a/app/docs/[...slug]/page.tsx b/app/docs/[...slug]/page.tsx
index e982a4c5..64c62e29 100644
--- a/app/docs/[...slug]/page.tsx
+++ b/app/docs/[...slug]/page.tsx
@@ -13,31 +13,9 @@ import {
import { Contributors } from "@/app/components/Contributors";
import { DocsAssistant } from "@/app/components/DocsAssistant";
import { LicenseNotice } from "@/app/components/LicenseNotice";
-import fs from "fs/promises";
-import path from "path";
-
-// Extract clean text content from MDX
-function extractTextFromMDX(content: string): string {
- let text = content
- .replace(/^---[\s\S]*?---/m, "") // Remove frontmatter
- .replace(/```[\s\S]*?```/g, "") // Remove code blocks
- .replace(/`([^`]+)`/g, "$1"); // Remove inline code
- // Remove HTML/MDX tags recursively to prevent incomplete multi-character sanitization
- let prevText;
- do {
- prevText = text;
- text = text.replace(/<[^>]+>/g, "");
- } while (text !== prevText);
- return text
- .replace(/\*\*([^*]+)\*\*/g, "$1") // Remove bold
- .replace(/\*([^*]+)\*/g, "$1") // Remove italic
- .replace(/#{1,6}\s+/g, "") // Remove headers
- .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") // Remove links, keep text
- .replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1") // Remove images, keep alt text
- .replace(/[#*`()[!\]!]/g, "") // Remove common markdown symbols
- .replace(/\n{2,}/g, "\n") // Normalize line breaks
- .trim();
-}
+import { PageFeedback } from "@/app/components/PageFeedback";
+// Extract clean text content from MDX - no longer used on client/page side
+// content fetching moved to API route for performance
interface Param {
params: Promise<{
@@ -66,20 +44,6 @@ export default async function DocPage({ params }: Param) {
getDocContributorsByDocId(docIdFromPage);
const Mdx = page.data.body;
- // Prepare page content for AI assistant
- let pageContentForAI = "";
- try {
- const fullFilePath = path.join(process.cwd(), "app/docs", page.file.path);
- const rawContent = await fs.readFile(fullFilePath, "utf-8");
- const extractedText = extractTextFromMDX(rawContent);
- // Use full extracted content without truncation
- pageContentForAI = extractedText;
- } catch (error) {
- console.warn("Failed to read file content for AI assistant:", error);
- // Fallback to using page metadata
- pageContentForAI = `${page.data.title}\n${page.data.description || ""}`;
- }
-
return (
<>
@@ -92,6 +56,7 @@ export default async function DocPage({ params }: Param) {
+
@@ -102,7 +67,6 @@ export default async function DocPage({ params }: Param) {
pageContext={{
title: page.data.title,
description: page.data.description,
- content: pageContentForAI,
slug: slug?.join("/"),
}}
/>
diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx
index 8e0d46ab..404848db 100644
--- a/app/docs/layout.tsx
+++ b/app/docs/layout.tsx
@@ -4,6 +4,7 @@ import { baseOptions } from "@/lib/layout.shared";
import type { ReactNode } from "react";
import { DocsRouteFlag } from "@/app/components/RouteFlags";
import type { PageTree } from "fumadocs-core/server";
+import { CopyTracking } from "@/app/components/CopyTracking";
function pruneEmptyFolders(root: PageTree.Root): PageTree.Root {
const transformNode = (node: PageTree.Node): PageTree.Node | null => {
@@ -68,6 +69,7 @@ export default async function Layout({ children }: { children: ReactNode }) {
return (
<>
{/* Add a class on while in docs to adjust global backgrounds */}
+
{
: parsed.provider === "intern"
? "intern"
: "openai",
+ // Use only stored key if saveToLocalStorage is true
// 只有在saveToLocalStorage为true时才使用存储的key
openaiApiKey:
saveToLocalStorage && typeof parsed.openaiApiKey === "string"
@@ -100,6 +101,7 @@ export const AssistantSettingsProvider = ({
}
try {
+ // Decide whether to save API keys based on saveToLocalStorage
// 根据saveToLocalStorage决定是否保存API key
const dataToSave = settings.saveToLocalStorage
? settings
diff --git a/app/not-found.tsx b/app/not-found.tsx
index c161da29..0053a3b7 100644
--- a/app/not-found.tsx
+++ b/app/not-found.tsx
@@ -9,8 +9,12 @@ export default function NotFound() {
const pathname = usePathname();
useEffect(() => {
+ // Umami 埋点: 记录 404 错误和来源页面 (Referrer)
if (window.umami) {
- window.umami.track("404", { path: pathname });
+ window.umami.track("error_404", {
+ path: pathname,
+ referrer: document.referrer || "direct",
+ });
}
}, [pathname]);
diff --git a/auth.ts b/auth.ts
index 6ce9d9f3..87b78e96 100644
--- a/auth.ts
+++ b/auth.ts
@@ -1,23 +1,14 @@
import NextAuth from "next-auth";
import { authConfig } from "./auth.config";
import GitHub from "next-auth/providers/github";
-import { Pool } from "@neondatabase/serverless";
-import NeonAdapter from "@auth/neon-adapter";
-
-type NeonAdapterPool = Parameters[0];
+import { PrismaAdapter } from "@auth/prisma-adapter";
+import { prisma } from "@/lib/db";
export const { handlers, auth, signIn, signOut } = NextAuth(() => {
- // Neon 连接只在有数据库配置时启用;本地协作者若没有 `.env`,将回退为纯 JWT 会话,避免直接抛错阻塞开发。
- const databaseUrl = process.env.DATABASE_URL;
- const adapter = databaseUrl
- ? NeonAdapter(
- new Pool({
- connectionString: databaseUrl,
- }) as unknown as NeonAdapterPool,
- )
- : undefined;
+ // 数据库适配器:仅在有 DATABASE_URL 时启用
+ const adapter = process.env.DATABASE_URL ? PrismaAdapter(prisma) : undefined;
- if (!databaseUrl) {
+ if (!process.env.DATABASE_URL) {
console.warn("[auth] DATABASE_URL missing – running without Neon adapter");
}
return {
diff --git a/data/event.json b/data/event.json
index 6e2ab7d3..279b11c7 100644
--- a/data/event.json
+++ b/data/event.json
@@ -26,4 +26,4 @@
"deprecated": true
}
]
-}
\ No newline at end of file
+}
diff --git a/docs/umami_tracking.md b/docs/umami_tracking.md
index ffeb9a37..909e0a76 100644
--- a/docs/umami_tracking.md
+++ b/docs/umami_tracking.md
@@ -6,13 +6,15 @@
**内部导航 (Internal Navigation)**: 仅用于网站内部页面的跳转。
-| 区域 (Region) | 元素说明 | 触发行为 | 埋点事件名 (Event Name) | 埋点传参 (Event Data) |
-| :------------- | :---------------------------- | :------- | :---------------------- | :------------------------------------------------------------------------------------ |
-| **header** | 导航链接 (特点, 社区等) | 点击 | `navigation_click` | `region`: "header", `label`: 链接名 (e.g., "features"), `path`: 目标路径 |
-| **footer** | 归档/资源链接 | 点击 | `navigation_click` | `region`: "footer", `label`: 链接名 (e.g., "AI & Mathematics"), `category`: "archive" |
-| **sidebar** | 文档侧边栏链接 | 点击 | `navigation_click` | `region`: "sidebar", `label`: 页面标题, `path`: 目标路径 |
-| **toc** | 目录 (Table of Contents) 链接 | 点击 | `navigation_click` | `region`: "toc", `label`: 章节标题 |
-| **pagination** | 上一篇/下一篇 | 点击 | `navigation_click` | `region`: "pagination", `label`: "prev" / "next", `path`: 目标路径 |
+| 区域 (Region) | 元素说明 | 触发行为 | 埋点事件名 (Event Name) | 埋点传参 (Event Data) |
+| :------------------- | :---------------------------- | :------- | :---------------------- | :------------------------------------------------------------------------------------ |
+| **header** | 导航链接 (特点, 社区等) | 点击 | `navigation_click` | `region`: "header", `label`: 链接名 (e.g., "features"), `path`: 目标路径 |
+| **footer** | 归档/资源链接 | 点击 | `navigation_click` | `region`: "footer", `label`: 链接名 (e.g., "Mission Brief"), `category`: "archive" |
+| **sidebar** | 文档侧边栏链接 | 点击 | `navigation_click` | `region`: "sidebar", `label`: 页面标题, `path`: 目标路径 |
+| **toc** | 目录 (Table of Contents) 链接 | 点击 | `navigation_click` | `region`: "toc", `label`: 章节标题 |
+| **pagination** | 上一篇/下一篇 | 点击 | `navigation_click` | `region`: "pagination", `label`: "prev" / "next", `path`: 目标路径 |
+| **hero_cta** | 首页 Hero 按钮 | 点击 | `navigation_click` | `region`: "hero_cta", `label`: "Access Articles" |
+| **home_categories** | 首页分类卡片 | 点击 | `navigation_click` | `region`: "home_categories", `label`: 分类标题 (e.g., "AI") |
**资源与外部链接 (Resources & External Links)**: 用于追踪外部资源、工具或社交媒体的点击。
@@ -35,18 +37,19 @@
## 3. 内容互动与反馈 (Content Interaction & Feedback)
-| 区域 | 元素说明 | 触发行为 | 埋点事件名 (Event Name) | 埋点传参 (Event Data) |
-| :--------------- | :----------------- | :------- | :---------------------- | :------------------------------------------------------------------- |
-| **Content** | 复制生词/代码块 | 点击 | `prose_copy` | `type`: "code"/"text", `content_length`: 字符数范围 |
-| **Content** | 页面反馈 (Helpful) | 点击 | `feedback_submit` | `page`: 当前页面路径, `vote`: "helpful" / "not_helpful" |
-| **Feature** | 投稿 (Contribute) | 点击 | `contribute_trigger` | `location`: "hero" / "docs" |
-| **AI Assistant** | 提问 | 发送 | `ai_assistant_query` | `length`: 字符数范围 (e.g., "0-50") _注意:不记录具体内容以保护隐私_ |
+| 区域 | 元素说明 | 触发行为 | 埋点事件名 (Event Name) | 埋点传参 (Event Data) |
+| :--------------- | :------------------------- | :------- | :--------------------------- | :----------------------------------------------------------- |
+| **Content** | 复制生词/代码块 | 复制 | `content_copy` | `type`: "code"/"text", `content_length`: 字符数 (number) |
+| **Content** | 页面反馈 (Helpful) | 点击 | `feedback_submit` | `page`: 当前页面路径, `vote`: "helpful" / "not_helpful" |
+| **Feature** | 投稿 (Contribute) | 点击 | `contribute_trigger` | `location`: "hero" / "docs" |
+| **Feature** | 投稿跳转 (Github Redirect) | 跳转 | `contribute_github_redirect` | `dir`: 目标目录, `filename`: 文件名 |
+| **AI Assistant** | 提问 | 完成 | `ai_assistant_query` | _(暂未包含具体参数)_ |
## 4. 异常与错误 (Errors)
-| 场景 | 说明 | 触发条件 | 埋点事件名 (Event Name) | 埋点传参 (Event Data) |
-| :------ | :--------- | :------------ | :---------------------- | :------------------------------------- |
-| **404** | 页面未找到 | 访问 404 页面 | `error_404` | `path`: 访问路径, `referrer`: 来源页面 |
+| 场景 | 说明 | 触发条件 | 埋点事件名 (Event Name) | 埋点传参 (Event Data) |
+| :------ | :--------- | :------------ | :---------------------- | :----------------------------------------------- |
+| **404** | 页面未找到 | 访问 404 页面 | `error_404` | `path`: 访问路径, `referrer`: 来源页面 (document.referrer) |
## 实施指南
@@ -68,15 +71,23 @@
>Artificial Intelligence
```
-### 搜索埋点示例 (配合 cmdk / fumadocs)
+### 搜索埋点示例 (CustomSearchDialog)
```tsx
-// 在搜索组件中
-const onSelectResult = (result, index) => {
- umami.track("search_result_click", {
- query: searchQuery,
- rank: index + 1,
- url: result.url,
- });
-};
+// 在搜索结果点击时
+umami.track("search_result_click", {
+ query: searchQuery,
+ rank: index + 1,
+ url: result.url,
+});
+```
+
+### 复制监听示例 (CopyTracking)
+
+```tsx
+// 自动监听 document copy 事件
+umami.track("content_copy", {
+ type: isCode ? "code" : "text",
+ content_length: selection.toString().length,
+});
```
diff --git a/generated/doc-contributors.json b/generated/doc-contributors.json
index 1003d7d7..d687b8d8 100644
--- a/generated/doc-contributors.json
+++ b/generated/doc-contributors.json
@@ -1,6 +1,6 @@
{
"repo": "InvolutionHell/involutionhell",
- "generatedAt": "2026-02-10T16:55:33.836Z",
+ "generatedAt": "2026-02-19T14:50:35.107Z",
"docsDir": "app/docs",
"totalDocs": 146,
"results": [
diff --git a/lib/ai/providers/glm.ts b/lib/ai/providers/glm.ts
new file mode 100644
index 00000000..7b3a3f80
--- /dev/null
+++ b/lib/ai/providers/glm.ts
@@ -0,0 +1,16 @@
+import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
+
+/**
+ * 创建智谱 GLM 模型实例
+ * 使用 GLM-4-Flash(免费模型),适合轻量任务如建议生成
+ * API key 需在环境变量 ZHIPU_API_KEY 中配置
+ */
+export function createGlmFlashModel() {
+ const glm = createOpenAICompatible({
+ name: "zhipu",
+ baseURL: "https://open.bigmodel.cn/api/paas/v4/",
+ apiKey: process.env.ZHIPU_API_KEY,
+ });
+
+ return glm("glm-4-flash");
+}
diff --git a/lib/db.ts b/lib/db.ts
new file mode 100644
index 00000000..c9c962d4
--- /dev/null
+++ b/lib/db.ts
@@ -0,0 +1,16 @@
+import { PrismaClient } from "../generated/prisma/client";
+import { PrismaPg } from "@prisma/adapter-pg";
+import { Pool } from "pg";
+
+const connectionString = `${process.env.DATABASE_URL}`;
+
+const globalForPrisma = globalThis as unknown as {
+ prisma: PrismaClient | undefined;
+};
+
+const pool = new Pool({ connectionString });
+
+const adapter = new PrismaPg(pool);
+export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter });
+
+if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
diff --git a/package.json b/package.json
index 768bafbe..92805367 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"start": "next start -p 3000",
"test": "vitest run",
"test:watch": "vitest",
- "postinstall": "fumadocs-mdx",
+ "postinstall": "fumadocs-mdx && prisma generate",
"prepare": "husky",
"lint:images": "node scripts/check-images.mjs",
"migrate:images": "node scripts/move-doc-images.mjs",
@@ -28,16 +28,16 @@
"@assistant-ui/react": "^0.11.14",
"@assistant-ui/react-ai-sdk": "^1.1.0",
"@assistant-ui/react-markdown": "^0.11.0",
- "@auth/neon-adapter": "^1.10.0",
+ "@auth/prisma-adapter": "^2.11.1",
"@aws-sdk/client-s3": "^3.932.0",
"@aws-sdk/s3-request-presigner": "^3.932.0",
"@giscus/react": "^3.1.0",
"@milkdown/crepe": "^7.17.1",
"@milkdown/kit": "^7.17.1",
- "@neondatabase/serverless": "^1.0.1",
"@orama/orama": "^3.1.14",
"@orama/tokenizers": "^3.1.14",
- "@prisma/client": "^6.16.2",
+ "@prisma/adapter-pg": "^7.4.1",
+ "@prisma/client": "7",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.15",
@@ -46,6 +46,7 @@
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@types/mdx": "^2.0.13",
+ "@types/pg": "^8.16.0",
"@vercel/speed-insights": "^1.2.0",
"ai": "^5.0.96",
"antd": "^5.27.4",
@@ -64,7 +65,7 @@
"next": "16.1.5",
"next-auth": "5.0.0-beta.30",
"next-intl": "^4.3.9",
- "prisma": "^6.16.2",
+ "pg": "^8.18.0",
"react": "19.2.3",
"react-dom": "19.2.3",
"rehype-autolink-headings": "^7.1.0",
@@ -95,6 +96,7 @@
"lint-staged": "^16.1.6",
"postcss": "^8.5.6",
"prettier": "3.6.2",
+ "prisma": "^7.4.1",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
"tailwindcss": "^4.1.13",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4210635c..8297bca8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -33,9 +33,9 @@ importers:
'@assistant-ui/react-markdown':
specifier: ^0.11.0
version: 0.11.0(@assistant-ui/react@0.11.14(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(use-sync-external-store@1.5.0(react@19.2.3)))(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
- '@auth/neon-adapter':
- specifier: ^1.10.0
- version: 1.10.0
+ '@auth/prisma-adapter':
+ specifier: ^2.11.1
+ version: 2.11.1(@prisma/client@7.4.1(prisma@7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2))(typescript@5.9.2))
'@aws-sdk/client-s3':
specifier: ^3.932.0
version: 3.948.0
@@ -51,18 +51,18 @@ importers:
'@milkdown/kit':
specifier: ^7.17.1
version: 7.17.1(@codemirror/language@6.11.3)(@codemirror/state@6.5.2)(@codemirror/view@6.38.6)(typescript@5.9.2)
- '@neondatabase/serverless':
- specifier: ^1.0.1
- version: 1.0.1
'@orama/orama':
specifier: ^3.1.14
version: 3.1.14
'@orama/tokenizers':
specifier: ^3.1.14
version: 3.1.14
+ '@prisma/adapter-pg':
+ specifier: ^7.4.1
+ version: 7.4.1
'@prisma/client':
- specifier: ^6.16.2
- version: 6.16.2(prisma@6.16.2(typescript@5.9.2))(typescript@5.9.2)
+ specifier: '7'
+ version: 7.4.1(prisma@7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2))(typescript@5.9.2)
'@radix-ui/react-avatar':
specifier: ^1.1.10
version: 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -87,6 +87,9 @@ importers:
'@types/mdx':
specifier: ^2.0.13
version: 2.0.13
+ '@types/pg':
+ specifier: ^8.16.0
+ version: 8.16.0
'@vercel/speed-insights':
specifier: ^1.2.0
version: 1.2.0(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(vue@3.5.24(typescript@5.9.2))
@@ -141,9 +144,9 @@ importers:
next-intl:
specifier: ^4.3.9
version: 4.3.9(next@16.1.5(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(typescript@5.9.2)
- prisma:
- specifier: ^6.16.2
- version: 6.16.2(typescript@5.9.2)
+ pg:
+ specifier: ^8.18.0
+ version: 8.18.0
react:
specifier: 19.2.3
version: 19.2.3
@@ -226,6 +229,9 @@ importers:
prettier:
specifier: 3.6.2
version: 3.6.2
+ prisma:
+ specifier: ^7.4.1
+ version: 7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)
rehype-katex:
specifier: ^7.0.1
version: 7.0.1
@@ -400,8 +406,8 @@ packages:
react:
optional: true
- '@auth/core@0.40.0':
- resolution: {integrity: sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==}
+ '@auth/core@0.41.0':
+ resolution: {integrity: sha512-Wd7mHPQ/8zy6Qj7f4T46vg3aoor8fskJm6g2Zyj064oQ3+p0xNZXAV60ww0hY+MbTesfu29kK14Zk5d5JTazXQ==}
peerDependencies:
'@simplewebauthn/browser': ^9.0.1
'@simplewebauthn/server': ^9.0.2
@@ -414,12 +420,12 @@ packages:
nodemailer:
optional: true
- '@auth/core@0.41.0':
- resolution: {integrity: sha512-Wd7mHPQ/8zy6Qj7f4T46vg3aoor8fskJm6g2Zyj064oQ3+p0xNZXAV60ww0hY+MbTesfu29kK14Zk5d5JTazXQ==}
+ '@auth/core@0.41.1':
+ resolution: {integrity: sha512-t9cJ2zNYAdWMacGRMT6+r4xr1uybIdmYa49calBPeTqwgAFPV/88ac9TEvCR85pvATiSPt8VaNf+Gt24JIT/uw==}
peerDependencies:
'@simplewebauthn/browser': ^9.0.1
'@simplewebauthn/server': ^9.0.2
- nodemailer: ^6.8.0
+ nodemailer: ^7.0.7
peerDependenciesMeta:
'@simplewebauthn/browser':
optional: true
@@ -428,8 +434,10 @@ packages:
nodemailer:
optional: true
- '@auth/neon-adapter@1.10.0':
- resolution: {integrity: sha512-KuwialF1LrM5AZOzGurw6OUfeO/sW1ZAQirceYuxzpiVPvUJCeOPHQro0vcvD29JmdpWh5XegnEbRHXtVXROPg==}
+ '@auth/prisma-adapter@2.11.1':
+ resolution: {integrity: sha512-Ke7DXP0Fy0Mlmjz/ZJLXwQash2UkA4621xCM0rMtEczr1kppLc/njCbUkHkIQ/PnmILjqSPEKeTjDPsYruvkug==}
+ peerDependencies:
+ '@prisma/client': '>=2.26.0 || >=3 || >=4 || >=5 || >=6'
'@aws-crypto/crc32@5.2.0':
resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==}
@@ -669,6 +677,18 @@ packages:
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
engines: {node: '>=6.9.0'}
+ '@chevrotain/cst-dts-gen@10.5.0':
+ resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==}
+
+ '@chevrotain/gast@10.5.0':
+ resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==}
+
+ '@chevrotain/types@10.5.0':
+ resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==}
+
+ '@chevrotain/utils@10.5.0':
+ resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==}
+
'@codemirror/autocomplete@6.19.1':
resolution: {integrity: sha512-q6NenYkEy2fn9+JyjIxMWcNjzTL/IhwqfzOut1/G3PrIFkrbl4AL7Wkse5tLrQUUyqGoAKU5+Pi5jnnXxH5HGw==}
@@ -786,6 +806,20 @@ packages:
resolution: {integrity: sha512-0dEVyRLM/lG4gp1R/Ik5bfPl/1wX00xFwd5KcNH602tzBa09oF7pbTKETEhR1GjZ75K6OJnYFu8II2dyMhONMw==}
engines: {node: '>=16'}
+ '@electric-sql/pglite-socket@0.0.20':
+ resolution: {integrity: sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==}
+ hasBin: true
+ peerDependencies:
+ '@electric-sql/pglite': 0.3.15
+
+ '@electric-sql/pglite-tools@0.2.20':
+ resolution: {integrity: sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==}
+ peerDependencies:
+ '@electric-sql/pglite': 0.3.15
+
+ '@electric-sql/pglite@0.3.15':
+ resolution: {integrity: sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==}
+
'@emnapi/core@1.5.0':
resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==}
@@ -1186,6 +1220,12 @@ packages:
react: ^16 || ^17 || ^18 || ^19
react-dom: ^16 || ^17 || ^18 || ^19
+ '@hono/node-server@1.19.9':
+ resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
+ engines: {node: '>=18.14.1'}
+ peerDependencies:
+ hono: ^4
+
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@@ -1501,19 +1541,16 @@ packages:
'@milkdown/utils@7.17.1':
resolution: {integrity: sha512-QTjbaxv+ZOB4a1BaQULkeJExyIvMnQw69UKf9QoM/E8iY2q1c8kppnN6i6ZeN9ZkCh4lXu+r7w/LH6zSFXrsdA==}
+ '@mrleebo/prisma-ast@0.13.1':
+ resolution: {integrity: sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==}
+ engines: {node: '>=16'}
+
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
'@napi-rs/wasm-runtime@1.0.7':
resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==}
- '@neondatabase/serverless@0.10.4':
- resolution: {integrity: sha512-2nZuh3VUO9voBauuh+IGYRhGU/MskWHt1IuZvHcJw6GLjDgtqj/KViKo7SIrLdGLdot7vFbiRRw+BgEy3wT9HA==}
-
- '@neondatabase/serverless@1.0.1':
- resolution: {integrity: sha512-O6yC5TT0jbw86VZVkmnzCZJB0hfxBl0JJz6f+3KHoZabjb/X08r9eFA+vuY06z1/qaovykvdkrXYq3SPUuvogA==}
- engines: {node: '>=19.0.0'}
-
'@next/env@16.1.5':
resolution: {integrity: sha512-CRSCPJiSZoi4Pn69RYBDI9R7YK2g59vLexPQFXY0eyw+ILevIenCywzg+DqmlBik9zszEnw2HLFOUlLAcJbL7g==}
@@ -1620,35 +1657,63 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@prisma/client@6.16.2':
- resolution: {integrity: sha512-E00PxBcalMfYO/TWnXobBVUai6eW/g5OsifWQsQDzJYm7yaY+IRLo7ZLsaefi0QkTpxfuhFcQ/w180i6kX3iJw==}
- engines: {node: '>=18.18'}
+ '@prisma/adapter-pg@7.4.1':
+ resolution: {integrity: sha512-AH9XrqvSoBAaStn0Gm/sAnF97pDKz8uLpNmn51j1S9O9dhUva6LIxGdoDiiU9VXRIR89wAJXsvJSy+mK40m2xw==}
+
+ '@prisma/client-runtime-utils@7.4.1':
+ resolution: {integrity: sha512-8fy74OMYC7mt9cJ2MncIDk1awPRgmtXVvwTN2FlW4JVhbck8Dgt0wTkhPG85myfj4ZeP2stjF9Sdg12n5HrpQg==}
+
+ '@prisma/client@7.4.1':
+ resolution: {integrity: sha512-pgIll2W1NVdof37xLeyySW+yfQ4rI+ERGCRwnO3BjVOx42GpYq6jhTyuALK8VKirvJJIvImgfGDA2qwhYVvMuA==}
+ engines: {node: ^20.19 || ^22.12 || >=24.0}
peerDependencies:
prisma: '*'
- typescript: '>=5.1.0'
+ typescript: '>=5.4.0'
peerDependenciesMeta:
prisma:
optional: true
typescript:
optional: true
- '@prisma/config@6.16.2':
- resolution: {integrity: sha512-mKXSUrcqXj0LXWPmJsK2s3p9PN+aoAbyMx7m5E1v1FufofR1ZpPoIArjjzOIm+bJRLLvYftoNYLx1tbHgF9/yg==}
+ '@prisma/config@7.4.1':
+ resolution: {integrity: sha512-vteSXm8N46bo3FW9MhPGVHAj+KRgrR6TWtlSk6GqToCKjTnOexXdPZyiDyEsfVW38YhqEmVl6w/6iHN8uYVJcw==}
+
+ '@prisma/debug@7.2.0':
+ resolution: {integrity: sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==}
+
+ '@prisma/debug@7.4.1':
+ resolution: {integrity: sha512-qEtzO8oLouRv18JDQUC3G3Gnv+fGVscHZm/x1DBB/WT+kOvPDQLM2woX6IGgWnSMYYlrxjuALshT7G/blvY0bQ==}
+
+ '@prisma/dev@0.20.0':
+ resolution: {integrity: sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==}
+
+ '@prisma/driver-adapter-utils@7.4.1':
+ resolution: {integrity: sha512-gEZOC2tnlHaZNbHUdbK8YvQphq2tKq/Ovu1YixJ/hPSutDAvNzC3R+xUeBuJ4AJp236eELMzwxb7rgo3UbRkTg==}
- '@prisma/debug@6.16.2':
- resolution: {integrity: sha512-bo4/gA/HVV6u8YK2uY6glhNsJ7r+k/i5iQ9ny/3q5bt9ijCj7WMPUwfTKPvtEgLP+/r26Z686ly11hhcLiQ8zA==}
+ '@prisma/engines-version@7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3':
+ resolution: {integrity: sha512-fUxVd1TjOW8K4XsZ8dAm88sDW5Ry7AxWDfsYEWwScS6Fjo3caKC6hgNumUfsmsy0Il9LjDn5X0PpVXNt3iwayw==}
- '@prisma/engines-version@6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43':
- resolution: {integrity: sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA==}
+ '@prisma/engines@7.4.1':
+ resolution: {integrity: sha512-BZEBdHvNJx5PzIG37EI/Zi5UUI5hGWjkYsQmKa7OIK6evAvebOTwutjS/VRI6cA6grmA52eLZR+oekGRMqkKxQ==}
- '@prisma/engines@6.16.2':
- resolution: {integrity: sha512-7yf3AjfPUgsg/l7JSu1iEhsmZZ/YE00yURPjTikqm2z4btM0bCl2coFtTGfeSOWbQMmq45Jab+53yGUIAT1sjA==}
+ '@prisma/fetch-engine@7.4.1':
+ resolution: {integrity: sha512-Z9kbuxX2bvEsyeS3LZEiEnxG0lVtZbpYgaAnPj69N+A9f2De8Lta0EoFtld9zhfERVPIQWhSWUc8himky3qYdA==}
- '@prisma/fetch-engine@6.16.2':
- resolution: {integrity: sha512-wPnZ8DMRqpgzye758ZvfAMiNJRuYpz+rhgEBZi60ZqDIgOU2694oJxiuu3GKFeYeR/hXxso4/2oBC243t/whxQ==}
+ '@prisma/get-platform@7.2.0':
+ resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==}
- '@prisma/get-platform@6.16.2':
- resolution: {integrity: sha512-U/P36Uke5wS7r1+omtAgJpEB94tlT4SdlgaeTc6HVTTT93pXj7zZ+B/cZnmnvjcNPfWddgoDx8RLjmQwqGDYyA==}
+ '@prisma/get-platform@7.4.1':
+ resolution: {integrity: sha512-kN4tmkQzlgm/KtE+jTNSYjsDxxe/5i6GApPI32BN9T0tlgsgSBtDJbjGBICttkAIjsh73dXf8raPKxO/2n2UUg==}
+
+ '@prisma/query-plan-executor@7.2.0':
+ resolution: {integrity: sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==}
+
+ '@prisma/studio-core@0.13.1':
+ resolution: {integrity: sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==}
+ peerDependencies:
+ '@types/react': 19.2.7
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
'@radix-ui/number@1.1.1':
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
@@ -2743,17 +2808,14 @@ packages:
'@types/node@16.18.11':
resolution: {integrity: sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==}
- '@types/node@22.19.7':
- resolution: {integrity: sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==}
-
'@types/node@25.1.0':
resolution: {integrity: sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA==}
- '@types/pg@8.11.6':
- resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==}
+ '@types/node@25.3.0':
+ resolution: {integrity: sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==}
- '@types/pg@8.15.5':
- resolution: {integrity: sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==}
+ '@types/pg@8.16.0':
+ resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==}
'@types/react-dom@19.2.3':
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
@@ -3270,6 +3332,10 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
+ aws-ssl-profiles@1.1.2:
+ resolution: {integrity: sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==}
+ engines: {node: '>= 6.0.0'}
+
axe-core@4.10.3:
resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==}
engines: {node: '>=4'}
@@ -3373,6 +3439,9 @@ packages:
character-reference-invalid@2.0.1:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+ chevrotain@10.5.0:
+ resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==}
+
chokidar@4.0.0:
resolution: {integrity: sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==}
engines: {node: '>= 14.16.0'}
@@ -3571,6 +3640,10 @@ packages:
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+ denque@2.1.0:
+ resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
+ engines: {node: '>=0.10'}
+
depd@1.1.2:
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
engines: {node: '>= 0.6'}
@@ -3627,8 +3700,8 @@ packages:
engines: {node: '>=16'}
hasBin: true
- effect@3.16.12:
- resolution: {integrity: sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==}
+ effect@3.18.4:
+ resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==}
electron-to-chromium@1.5.222:
resolution: {integrity: sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==}
@@ -4225,6 +4298,9 @@ packages:
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ generate-function@2.3.1:
+ resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==}
+
generic-pool@3.4.2:
resolution: {integrity: sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==}
engines: {node: '>= 4'}
@@ -4245,6 +4321,9 @@ packages:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
+ get-port-please@3.2.0:
+ resolution: {integrity: sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==}
+
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
@@ -4301,9 +4380,15 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ grammex@3.1.12:
+ resolution: {integrity: sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==}
+
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ graphmatch@1.1.1:
+ resolution: {integrity: sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==}
+
gray-matter@4.0.3:
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
engines: {node: '>=6.0'}
@@ -4383,6 +4468,10 @@ packages:
hermes-parser@0.25.1:
resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+ hono@4.11.4:
+ resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==}
+ engines: {node: '>=16.9.0'}
+
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
@@ -4397,6 +4486,9 @@ packages:
resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==}
engines: {node: '>= 0.6'}
+ http-status-codes@2.3.0:
+ resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==}
+
https-proxy-agent@7.0.6:
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
@@ -4414,6 +4506,10 @@ packages:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
+ iconv-lite@0.7.2:
+ resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
+ engines: {node: '>=0.10.0'}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -4553,6 +4649,9 @@ packages:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
+ is-property@1.0.2:
+ resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
+
is-regex@1.2.1:
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
engines: {node: '>= 0.4'}
@@ -4758,6 +4857,10 @@ packages:
resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
engines: {node: '>= 12.0.0'}
+ lilconfig@2.1.0:
+ resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
+ engines: {node: '>=10'}
+
lilconfig@3.1.3:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
@@ -4790,10 +4893,16 @@ packages:
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
log-update@6.1.0:
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
engines: {node: '>=18'}
+ long@5.3.2:
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+
longest-streak@3.1.0:
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
@@ -4815,6 +4924,10 @@ packages:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
+ lru.min@1.1.4:
+ resolution: {integrity: sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==}
+ engines: {bun: '>=1.0.0', deno: '>=1.30.0', node: '>=8.0.0'}
+
lucide-react@0.544.0:
resolution: {integrity: sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==}
peerDependencies:
@@ -5107,6 +5220,14 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ mysql2@3.15.3:
+ resolution: {integrity: sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==}
+ engines: {node: '>= 8.0'}
+
+ named-placeholders@1.1.6:
+ resolution: {integrity: sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==}
+ engines: {node: '>=8.0.0'}
+
nano-spawn@1.0.3:
resolution: {integrity: sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA==}
engines: {node: '>=20.17'}
@@ -5280,9 +5401,6 @@ packages:
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
- obuf@1.1.2:
- resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
-
ohash@2.0.11:
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
@@ -5390,24 +5508,39 @@ packages:
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
+ pg-cloudflare@1.3.0:
+ resolution: {integrity: sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==}
+
+ pg-connection-string@2.11.0:
+ resolution: {integrity: sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==}
+
pg-int8@1.0.1:
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
engines: {node: '>=4.0.0'}
- pg-numeric@1.0.2:
- resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==}
- engines: {node: '>=4'}
+ pg-pool@3.11.0:
+ resolution: {integrity: sha512-MJYfvHwtGp870aeusDh+hg9apvOe2zmpZJpyt+BMtzUWlVqbhFmMK6bOBXLBUPd7iRtIF9fZplDc7KrPN3PN7w==}
+ peerDependencies:
+ pg: '>=8.0'
- pg-protocol@1.10.3:
- resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==}
+ pg-protocol@1.11.0:
+ resolution: {integrity: sha512-pfsxk2M9M3BuGgDOfuy37VNRRX3jmKgMjcvAcWqNDpZSf4cUmv8HSOl5ViRQFsfARFn0KuUQTgLxVMbNq5NW3g==}
pg-types@2.2.0:
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
engines: {node: '>=4'}
- pg-types@4.1.0:
- resolution: {integrity: sha512-o2XFanIMy/3+mThw69O8d4n1E5zsLhdO+OPqswezu7Z5ekP4hYDqlDjlmOpYMbzY2Br0ufCwJLdDIXeNVwcWFg==}
- engines: {node: '>=10'}
+ pg@8.18.0:
+ resolution: {integrity: sha512-xqrUDL1b9MbkydY/s+VZ6v+xiMUmOUk7SS9d/1kpyQxoJ6U9AO1oIJyUWVZojbfe5Cc/oluutcgFG4L9RDP1iQ==}
+ engines: {node: '>= 16.0.0'}
+ peerDependencies:
+ pg-native: '>=3.0.1'
+ peerDependenciesMeta:
+ pg-native:
+ optional: true
+
+ pgpass@1.0.5:
+ resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
picocolors@1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
@@ -5462,29 +5595,18 @@ packages:
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
engines: {node: '>=0.10.0'}
- postgres-bytea@3.0.0:
- resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==}
- engines: {node: '>= 6'}
-
postgres-date@1.0.7:
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
engines: {node: '>=0.10.0'}
- postgres-date@2.1.0:
- resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
- engines: {node: '>=12'}
-
postgres-interval@1.2.0:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
- postgres-interval@3.0.0:
- resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==}
+ postgres@3.4.7:
+ resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
engines: {node: '>=12'}
- postgres-range@1.1.4:
- resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
-
preact-render-to-string@6.5.11:
resolution: {integrity: sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==}
peerDependencies:
@@ -5506,13 +5628,16 @@ packages:
resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==}
engines: {node: '>=10'}
- prisma@6.16.2:
- resolution: {integrity: sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA==}
- engines: {node: '>=18.18'}
+ prisma@7.4.1:
+ resolution: {integrity: sha512-gDKOXwnPiMdB+uYMhMeN8jj4K7Cu3Q2wB/wUsITOoOk446HtVb8T9BZxFJ1Zop6alc89k6PMNdR2FZCpbXp/jw==}
+ engines: {node: ^20.19 || ^22.12 || >=24.0}
hasBin: true
peerDependencies:
- typescript: '>=5.1.0'
+ better-sqlite3: '>=9.0.0'
+ typescript: '>=5.4.0'
peerDependenciesMeta:
+ better-sqlite3:
+ optional: true
typescript:
optional: true
@@ -5522,6 +5647,9 @@ packages:
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ proper-lockfile@4.1.2:
+ resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==}
+
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
@@ -5926,6 +6054,9 @@ packages:
regex@6.0.1:
resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==}
+ regexp-to-ast@0.5.0:
+ resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==}
+
regexp.prototype.flags@1.5.4:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
@@ -5966,6 +6097,9 @@ packages:
remark@15.0.1:
resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
+ remeda@2.33.4:
+ resolution: {integrity: sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==}
+
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
@@ -5997,6 +6131,10 @@ packages:
resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
engines: {node: '>=18'}
+ retry@0.12.0:
+ resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
+ engines: {node: '>= 4'}
+
retry@0.13.1:
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
engines: {node: '>= 4'}
@@ -6070,6 +6208,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ seq-queue@0.0.5:
+ resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -6145,9 +6286,17 @@ packages:
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+ split2@4.2.0:
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
+ engines: {node: '>= 10.x'}
+
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+ sqlstring@2.3.3:
+ resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
+ engines: {node: '>= 0.6'}
+
srvx@0.8.9:
resolution: {integrity: sha512-wYc3VLZHRzwYrWJhkEqkhLb31TI0SOkfYZDkUhXdp3NoCnNS0FqajiQszZZjfow/VYEuc6Q5sZh9nM6kPy2NBQ==}
engines: {node: '>=20.16.0'}
@@ -6450,12 +6599,12 @@ packages:
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
engines: {node: '>= 0.4'}
- undici-types@6.21.0:
- resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
-
undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
+ undici-types@7.18.2:
+ resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
+
undici@5.28.4:
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
engines: {node: '>=14.0'}
@@ -6574,6 +6723,14 @@ packages:
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+ valibot@1.2.0:
+ resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==}
+ peerDependencies:
+ typescript: '>=5'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
vercel@48.8.0:
resolution: {integrity: sha512-ZPoq4txk2OkKAZVi+E+UKEFA70n4FkFmv/PSHTv4wAvJl3n2WvCaGCrfT33b9U9iDGQs9ZnwE2eQDylamc8FVA==}
engines: {node: '>= 18'}
@@ -6776,6 +6933,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ zeptomatch@2.1.0:
+ resolution: {integrity: sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==}
+
zod-validation-error@4.0.2:
resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
engines: {node: '>=18.0.0'}
@@ -6996,7 +7156,7 @@ snapshots:
optionalDependencies:
react: 19.2.3
- '@auth/core@0.40.0':
+ '@auth/core@0.41.0':
dependencies:
'@panva/hkdf': 1.2.1
jose: 6.1.0
@@ -7004,7 +7164,7 @@ snapshots:
preact: 10.24.3
preact-render-to-string: 6.5.11(preact@10.24.3)
- '@auth/core@0.41.0':
+ '@auth/core@0.41.1':
dependencies:
'@panva/hkdf': 1.2.1
jose: 6.1.0
@@ -7012,10 +7172,10 @@ snapshots:
preact: 10.24.3
preact-render-to-string: 6.5.11(preact@10.24.3)
- '@auth/neon-adapter@1.10.0':
+ '@auth/prisma-adapter@2.11.1(@prisma/client@7.4.1(prisma@7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2))(typescript@5.9.2))':
dependencies:
- '@auth/core': 0.40.0
- '@neondatabase/serverless': 0.10.4
+ '@auth/core': 0.41.1
+ '@prisma/client': 7.4.1(prisma@7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2))(typescript@5.9.2)
transitivePeerDependencies:
- '@simplewebauthn/browser'
- '@simplewebauthn/server'
@@ -7620,6 +7780,21 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
+ '@chevrotain/cst-dts-gen@10.5.0':
+ dependencies:
+ '@chevrotain/gast': 10.5.0
+ '@chevrotain/types': 10.5.0
+ lodash: 4.17.21
+
+ '@chevrotain/gast@10.5.0':
+ dependencies:
+ '@chevrotain/types': 10.5.0
+ lodash: 4.17.21
+
+ '@chevrotain/types@10.5.0': {}
+
+ '@chevrotain/utils@10.5.0': {}
+
'@codemirror/autocomplete@6.19.1':
dependencies:
'@codemirror/language': 6.11.3
@@ -7891,6 +8066,16 @@ snapshots:
dependencies:
'@edge-runtime/primitives': 4.1.0
+ '@electric-sql/pglite-socket@0.0.20(@electric-sql/pglite@0.3.15)':
+ dependencies:
+ '@electric-sql/pglite': 0.3.15
+
+ '@electric-sql/pglite-tools@0.2.20(@electric-sql/pglite@0.3.15)':
+ dependencies:
+ '@electric-sql/pglite': 0.3.15
+
+ '@electric-sql/pglite@0.3.15': {}
+
'@emnapi/core@1.5.0':
dependencies:
'@emnapi/wasi-threads': 1.1.0
@@ -8162,6 +8347,10 @@ snapshots:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
+ '@hono/node-server@1.19.9(hono@4.11.4)':
+ dependencies:
+ hono: 4.11.4
+
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.7':
@@ -8709,6 +8898,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@mrleebo/prisma-ast@0.13.1':
+ dependencies:
+ chevrotain: 10.5.0
+ lilconfig: 2.1.0
+
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.5.0
@@ -8723,15 +8917,6 @@ snapshots:
'@tybys/wasm-util': 0.10.1
optional: true
- '@neondatabase/serverless@0.10.4':
- dependencies:
- '@types/pg': 8.11.6
-
- '@neondatabase/serverless@1.0.1':
- dependencies:
- '@types/node': 22.19.7
- '@types/pg': 8.15.5
-
'@next/env@16.1.5': {}
'@next/eslint-plugin-next@16.0.7':
@@ -8801,40 +8986,92 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
- '@prisma/client@6.16.2(prisma@6.16.2(typescript@5.9.2))(typescript@5.9.2)':
+ '@prisma/adapter-pg@7.4.1':
+ dependencies:
+ '@prisma/driver-adapter-utils': 7.4.1
+ pg: 8.18.0
+ postgres-array: 3.0.4
+ transitivePeerDependencies:
+ - pg-native
+
+ '@prisma/client-runtime-utils@7.4.1': {}
+
+ '@prisma/client@7.4.1(prisma@7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2))(typescript@5.9.2)':
+ dependencies:
+ '@prisma/client-runtime-utils': 7.4.1
optionalDependencies:
- prisma: 6.16.2(typescript@5.9.2)
+ prisma: 7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2)
typescript: 5.9.2
- '@prisma/config@6.16.2':
+ '@prisma/config@7.4.1':
dependencies:
c12: 3.1.0
deepmerge-ts: 7.1.5
- effect: 3.16.12
+ effect: 3.18.4
empathic: 2.0.0
transitivePeerDependencies:
- magicast
- '@prisma/debug@6.16.2': {}
+ '@prisma/debug@7.2.0': {}
+
+ '@prisma/debug@7.4.1': {}
+
+ '@prisma/dev@0.20.0(typescript@5.9.2)':
+ dependencies:
+ '@electric-sql/pglite': 0.3.15
+ '@electric-sql/pglite-socket': 0.0.20(@electric-sql/pglite@0.3.15)
+ '@electric-sql/pglite-tools': 0.2.20(@electric-sql/pglite@0.3.15)
+ '@hono/node-server': 1.19.9(hono@4.11.4)
+ '@mrleebo/prisma-ast': 0.13.1
+ '@prisma/get-platform': 7.2.0
+ '@prisma/query-plan-executor': 7.2.0
+ foreground-child: 3.3.1
+ get-port-please: 3.2.0
+ hono: 4.11.4
+ http-status-codes: 2.3.0
+ pathe: 2.0.3
+ proper-lockfile: 4.1.2
+ remeda: 2.33.4
+ std-env: 3.10.0
+ valibot: 1.2.0(typescript@5.9.2)
+ zeptomatch: 2.1.0
+ transitivePeerDependencies:
+ - typescript
+
+ '@prisma/driver-adapter-utils@7.4.1':
+ dependencies:
+ '@prisma/debug': 7.4.1
- '@prisma/engines-version@6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43': {}
+ '@prisma/engines-version@7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3': {}
- '@prisma/engines@6.16.2':
+ '@prisma/engines@7.4.1':
dependencies:
- '@prisma/debug': 6.16.2
- '@prisma/engines-version': 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43
- '@prisma/fetch-engine': 6.16.2
- '@prisma/get-platform': 6.16.2
+ '@prisma/debug': 7.4.1
+ '@prisma/engines-version': 7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3
+ '@prisma/fetch-engine': 7.4.1
+ '@prisma/get-platform': 7.4.1
- '@prisma/fetch-engine@6.16.2':
+ '@prisma/fetch-engine@7.4.1':
dependencies:
- '@prisma/debug': 6.16.2
- '@prisma/engines-version': 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43
- '@prisma/get-platform': 6.16.2
+ '@prisma/debug': 7.4.1
+ '@prisma/engines-version': 7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3
+ '@prisma/get-platform': 7.4.1
- '@prisma/get-platform@6.16.2':
+ '@prisma/get-platform@7.2.0':
dependencies:
- '@prisma/debug': 6.16.2
+ '@prisma/debug': 7.2.0
+
+ '@prisma/get-platform@7.4.1':
+ dependencies:
+ '@prisma/debug': 7.4.1
+
+ '@prisma/query-plan-executor@7.2.0': {}
+
+ '@prisma/studio-core@0.13.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@types/react': 19.2.7
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
'@radix-ui/number@1.1.1': {}
@@ -9992,24 +10229,18 @@ snapshots:
'@types/node@16.18.11': {}
- '@types/node@22.19.7':
- dependencies:
- undici-types: 6.21.0
-
'@types/node@25.1.0':
dependencies:
undici-types: 7.16.0
- '@types/pg@8.11.6':
+ '@types/node@25.3.0':
dependencies:
- '@types/node': 25.1.0
- pg-protocol: 1.10.3
- pg-types: 4.1.0
+ undici-types: 7.18.2
- '@types/pg@8.15.5':
+ '@types/pg@8.16.0':
dependencies:
- '@types/node': 25.1.0
- pg-protocol: 1.10.3
+ '@types/node': 25.3.0
+ pg-protocol: 1.11.0
pg-types: 2.2.0
'@types/react-dom@19.2.3(@types/react@19.2.7)':
@@ -10759,6 +10990,8 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
+ aws-ssl-profiles@1.1.2: {}
+
axe-core@4.10.3: {}
axobject-query@4.1.0: {}
@@ -10857,6 +11090,15 @@ snapshots:
character-reference-invalid@2.0.1: {}
+ chevrotain@10.5.0:
+ dependencies:
+ '@chevrotain/cst-dts-gen': 10.5.0
+ '@chevrotain/gast': 10.5.0
+ '@chevrotain/types': 10.5.0
+ '@chevrotain/utils': 10.5.0
+ lodash: 4.17.21
+ regexp-to-ast: 0.5.0
+
chokidar@4.0.0:
dependencies:
readdirp: 4.1.2
@@ -11028,6 +11270,8 @@ snapshots:
defu@6.1.4: {}
+ denque@2.1.0: {}
+
depd@1.1.2: {}
dequal@2.0.3: {}
@@ -11078,7 +11322,7 @@ snapshots:
signal-exit: 4.0.2
time-span: 4.0.0
- effect@3.16.12:
+ effect@3.18.4:
dependencies:
'@standard-schema/spec': 1.1.0
fast-check: 3.23.2
@@ -11852,6 +12096,10 @@ snapshots:
functions-have-names@1.2.3: {}
+ generate-function@2.3.1:
+ dependencies:
+ is-property: 1.0.2
+
generic-pool@3.4.2: {}
gensync@1.0.0-beta.2: {}
@@ -11873,6 +12121,8 @@ snapshots:
get-nonce@1.0.1: {}
+ get-port-please@3.2.0: {}
+
get-proto@1.0.1:
dependencies:
dunder-proto: 1.0.1
@@ -11937,8 +12187,12 @@ snapshots:
graceful-fs@4.2.11: {}
+ grammex@3.1.12: {}
+
graphemer@1.4.0: {}
+ graphmatch@1.1.1: {}
+
gray-matter@4.0.3:
dependencies:
js-yaml: 3.14.2
@@ -12097,6 +12351,8 @@ snapshots:
dependencies:
hermes-estree: 0.25.1
+ hono@4.11.4: {}
+
html-url-attributes@3.0.1: {}
html-void-elements@3.0.0: {}
@@ -12114,6 +12370,8 @@ snapshots:
statuses: 1.5.0
toidentifier: 1.0.0
+ http-status-codes@2.3.0: {}
+
https-proxy-agent@7.0.6:
dependencies:
agent-base: 7.1.4
@@ -12129,6 +12387,10 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
+ iconv-lite@0.7.2:
+ dependencies:
+ safer-buffer: 2.1.2
+
ignore@5.3.2: {}
ignore@7.0.5: {}
@@ -12258,6 +12520,8 @@ snapshots:
is-plain-obj@4.1.0: {}
+ is-property@1.0.2: {}
+
is-regex@1.2.1:
dependencies:
call-bound: 1.0.4
@@ -12443,6 +12707,8 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.30.1
lightningcss-win32-x64-msvc: 1.30.1
+ lilconfig@2.1.0: {}
+
lilconfig@3.1.3: {}
lint-staged@16.1.6:
@@ -12493,6 +12759,8 @@ snapshots:
lodash.merge@4.6.2: {}
+ lodash@4.17.21: {}
+
log-update@6.1.0:
dependencies:
ansi-escapes: 7.1.0
@@ -12501,6 +12769,8 @@ snapshots:
strip-ansi: 7.1.2
wrap-ansi: 9.0.2
+ long@5.3.2: {}
+
longest-streak@3.1.0: {}
loose-envify@1.4.0:
@@ -12519,6 +12789,8 @@ snapshots:
dependencies:
yallist: 4.0.0
+ lru.min@1.1.4: {}
+
lucide-react@0.544.0(react@19.2.3):
dependencies:
react: 19.2.3
@@ -13072,6 +13344,22 @@ snapshots:
ms@2.1.3: {}
+ mysql2@3.15.3:
+ dependencies:
+ aws-ssl-profiles: 1.1.2
+ denque: 2.1.0
+ generate-function: 2.3.1
+ iconv-lite: 0.7.2
+ long: 5.3.2
+ lru.min: 1.1.4
+ named-placeholders: 1.1.6
+ seq-queue: 0.0.5
+ sqlstring: 2.3.3
+
+ named-placeholders@1.1.6:
+ dependencies:
+ lru.min: 1.1.4
+
nano-spawn@1.0.3: {}
nanoid@3.3.11: {}
@@ -13212,8 +13500,6 @@ snapshots:
define-properties: 1.2.1
es-object-atoms: 1.1.1
- obuf@1.1.2: {}
-
ohash@2.0.11: {}
once@1.3.3:
@@ -13321,11 +13607,18 @@ snapshots:
perfect-debounce@1.0.0: {}
+ pg-cloudflare@1.3.0:
+ optional: true
+
+ pg-connection-string@2.11.0: {}
+
pg-int8@1.0.1: {}
- pg-numeric@1.0.2: {}
+ pg-pool@3.11.0(pg@8.18.0):
+ dependencies:
+ pg: 8.18.0
- pg-protocol@1.10.3: {}
+ pg-protocol@1.11.0: {}
pg-types@2.2.0:
dependencies:
@@ -13335,15 +13628,19 @@ snapshots:
postgres-date: 1.0.7
postgres-interval: 1.2.0
- pg-types@4.1.0:
+ pg@8.18.0:
dependencies:
- pg-int8: 1.0.1
- pg-numeric: 1.0.2
- postgres-array: 3.0.4
- postgres-bytea: 3.0.0
- postgres-date: 2.1.0
- postgres-interval: 3.0.0
- postgres-range: 1.1.4
+ pg-connection-string: 2.11.0
+ pg-pool: 3.11.0(pg@8.18.0)
+ pg-protocol: 1.11.0
+ pg-types: 2.2.0
+ pgpass: 1.0.5
+ optionalDependencies:
+ pg-cloudflare: 1.3.0
+
+ pgpass@1.0.5:
+ dependencies:
+ split2: 4.2.0
picocolors@1.0.0: {}
@@ -13388,21 +13685,13 @@ snapshots:
postgres-bytea@1.0.0: {}
- postgres-bytea@3.0.0:
- dependencies:
- obuf: 1.1.2
-
postgres-date@1.0.7: {}
- postgres-date@2.1.0: {}
-
postgres-interval@1.2.0:
dependencies:
xtend: 4.0.2
- postgres-interval@3.0.0: {}
-
- postgres-range@1.1.4: {}
+ postgres@3.4.7: {}
preact-render-to-string@6.5.11(preact@10.24.3):
dependencies:
@@ -13418,14 +13707,21 @@ snapshots:
dependencies:
parse-ms: 2.1.0
- prisma@6.16.2(typescript@5.9.2):
+ prisma@7.4.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.2):
dependencies:
- '@prisma/config': 6.16.2
- '@prisma/engines': 6.16.2
+ '@prisma/config': 7.4.1
+ '@prisma/dev': 0.20.0(typescript@5.9.2)
+ '@prisma/engines': 7.4.1
+ '@prisma/studio-core': 0.13.1(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ mysql2: 3.15.3
+ postgres: 3.4.7
optionalDependencies:
typescript: 5.9.2
transitivePeerDependencies:
+ - '@types/react'
- magicast
+ - react
+ - react-dom
promisepipe@3.0.0: {}
@@ -13435,6 +13731,12 @@ snapshots:
object-assign: 4.1.1
react-is: 16.13.1
+ proper-lockfile@4.1.2:
+ dependencies:
+ graceful-fs: 4.2.11
+ retry: 0.12.0
+ signal-exit: 3.0.7
+
property-information@7.1.0: {}
prosemirror-changeset@2.3.1:
@@ -13993,6 +14295,8 @@ snapshots:
dependencies:
regex-utilities: 2.3.0
+ regexp-to-ast@0.5.0: {}
+
regexp.prototype.flags@1.5.4:
dependencies:
call-bind: 1.0.8
@@ -14102,6 +14406,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ remeda@2.33.4: {}
+
require-from-string@2.0.2: {}
resize-observer-polyfill@1.5.1: {}
@@ -14129,6 +14435,8 @@ snapshots:
onetime: 7.0.0
signal-exit: 4.1.0
+ retry@0.12.0: {}
+
retry@0.13.1: {}
reusify@1.1.0: {}
@@ -14235,6 +14543,8 @@ snapshots:
semver@7.7.3: {}
+ seq-queue@0.0.5: {}
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -14355,8 +14665,12 @@ snapshots:
space-separated-tokens@2.0.2: {}
+ split2@4.2.0: {}
+
sprintf-js@1.0.3: {}
+ sqlstring@2.3.3: {}
+
srvx@0.8.9:
dependencies:
cookie-es: 2.0.0
@@ -14686,10 +15000,10 @@ snapshots:
has-symbols: 1.1.0
which-boxed-primitive: 1.1.1
- undici-types@6.21.0: {}
-
undici-types@7.16.0: {}
+ undici-types@7.18.2: {}
+
undici@5.28.4:
dependencies:
'@fastify/busboy': 2.1.1
@@ -14832,6 +15146,10 @@ snapshots:
v8-compile-cache-lib@3.0.1: {}
+ valibot@1.2.0(typescript@5.9.2):
+ optionalDependencies:
+ typescript: 5.9.2
+
vercel@48.8.0(rollup@4.52.5)(typescript@5.9.2):
dependencies:
'@vercel/backends': 0.0.4(rollup@4.52.5)(typescript@5.9.2)
@@ -15063,6 +15381,11 @@ snapshots:
yocto-queue@0.1.0: {}
+ zeptomatch@2.1.0:
+ dependencies:
+ grammex: 3.1.12
+ graphmatch: 1.1.1
+
zod-validation-error@4.0.2(zod@4.1.11):
dependencies:
zod: 4.1.11
diff --git a/prisma.config.ts b/prisma.config.ts
new file mode 100644
index 00000000..8f05042d
--- /dev/null
+++ b/prisma.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from "prisma/config";
+
+export default defineConfig({
+ schema: "prisma/schema.prisma",
+ datasource: {
+ url: process.env.DATABASE_URL,
+ },
+});
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 21145483..8e900cbc 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -1,11 +1,10 @@
generator client {
- provider = "prisma-client-js"
+ provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "postgresql"
- url = env("DATABASE_URL")
}
model accounts {
@@ -61,11 +60,13 @@ model sessions {
}
model users {
- id Int @id @default(autoincrement())
- name String? @db.VarChar(255)
- email String? @db.VarChar(255)
- emailVerified DateTime? @db.Timestamptz(6)
- image String?
+ id Int @id @default(autoincrement())
+ name String? @db.VarChar(255)
+ email String? @db.VarChar(255)
+ emailVerified DateTime? @db.Timestamptz(6)
+ image String?
+ chats Chat[]
+ analyticsEvents AnalyticsEvent[]
}
model verification_token {
@@ -87,3 +88,40 @@ model doc_paths {
@@id([doc_id, path])
@@index([path])
}
+
+model Chat {
+ id String @id @default(cuid())
+ userId Int?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+ messages Message[]
+
+ user users? @relation(fields: [userId], references: [id])
+
+ @@index([userId])
+}
+
+model Message {
+ id String @id @default(cuid())
+ chatId String
+ role String
+ content String
+ createdAt DateTime @default(now())
+
+ chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
+
+ @@index([chatId])
+}
+
+model AnalyticsEvent {
+ id String @id @default(cuid())
+ userId Int?
+ eventType String
+ eventData Json?
+ createdAt DateTime @default(now())
+
+ user users? @relation(fields: [userId], references: [id])
+
+ @@index([eventType])
+ @@index([userId])
+}