')) {
+ divPositions.push({ line: index + 1, type: 'close', content: line.trim() });
+ }
+ });
+
+ console.log(`\n📍 div 标签位置:`);
+ divPositions.forEach(pos => {
+ console.log(` 第${pos.line}行: ${pos.type === 'open' ? '开始' : '结束'} - ${pos.content}`);
+ });
+
+ return openDivs === closeDivs && openProtectedRoute === closeProtectedRoute;
+
+ } catch (error) {
+ console.error('❌ 调试出错:', error.message);
+ return false;
+ }
+}
+
+// 运行调试
+const result = debugJSX();
+console.log(`\n🎯 结果: ${result ? '✅ 结构正确' : '❌ 结构有问题'}`);
+process.exit(result ? 0 : 1);
diff --git a/install.bat b/install.bat
new file mode 100644
index 0000000..3270a56
--- /dev/null
+++ b/install.bat
@@ -0,0 +1,238 @@
+@echo off
+chcp 65001 >nul
+setlocal enabledelayedexpansion
+
+:: PromptForge Windows 自动化安装脚本
+
+echo ================================
+echo PromptForge 自动化安装脚本
+echo ================================
+echo.
+
+:: 颜色定义
+set "RED=[91m"
+set "GREEN=[92m"
+set "YELLOW=[93m"
+set "BLUE=[94m"
+set "NC=[0m"
+
+:: 打印带颜色的消息
+:print_message
+echo %GREEN%[INFO]%NC% %~1
+goto :eof
+
+:print_warning
+echo %YELLOW%[WARNING]%NC% %~1
+goto :eof
+
+:print_error
+echo %RED%[ERROR]%NC% %~1
+goto :eof
+
+:: 检查系统要求
+call :print_message "检查系统要求..."
+
+:: 检查 Windows 版本
+for /f "tokens=4-5 delims=. " %%i in ('ver') do set VERSION=%%i.%%j
+if %VERSION% LSS 10.0 (
+ call :print_error "Windows 版本过低,需要 Windows 10 或更高版本"
+ pause
+ exit /b 1
+) else (
+ call :print_message "Windows 版本检查通过: %VERSION%"
+)
+
+:: 检查内存
+for /f "tokens=2 delims==" %%a in ('wmic computersystem get TotalPhysicalMemory /value') do set MEMORY=%%a
+set /a MEMORY_GB=%MEMORY:~0,-1%/1024/1024/1024
+if %MEMORY_GB% LSS 4 (
+ call :print_warning "内存不足,推荐至少 4GB RAM,当前: %MEMORY_GB%GB"
+) else (
+ call :print_message "内存检查通过: %MEMORY_GB%GB"
+)
+
+:: 检查磁盘空间
+for /f "tokens=3" %%a in ('dir /-c ^| find "bytes free"') do set DISK_SPACE=%%a
+set /a DISK_SPACE_GB=%DISK_SPACE:~0,-1%/1024/1024/1024
+if %DISK_SPACE_GB% LSS 2 (
+ call :print_warning "磁盘空间不足,推荐至少 2GB,当前: %DISK_SPACE_GB%GB"
+) else (
+ call :print_message "磁盘空间检查通过: %DISK_SPACE_GB%GB"
+)
+
+:: 检查 Node.js
+call :print_message "检查 Node.js..."
+
+node --version >nul 2>&1
+if %errorlevel% neq 0 (
+ call :print_warning "Node.js 未安装"
+ call :install_nodejs
+) else (
+ for /f "tokens=*" %%i in ('node --version') do set NODE_VERSION=%%i
+ call :print_message "Node.js 版本检查通过: %NODE_VERSION%"
+)
+
+:: 检查 npm
+npm --version >nul 2>&1
+if %errorlevel% neq 0 (
+ call :print_error "npm 未安装"
+ pause
+ exit /b 1
+) else (
+ for /f "tokens=*" %%i in ('npm --version') do set NPM_VERSION=%%i
+ call :print_message "npm 版本: v%NPM_VERSION%"
+)
+
+:: 检查 MySQL
+call :print_message "检查 MySQL..."
+
+mysql --version >nul 2>&1
+if %errorlevel% neq 0 (
+ call :print_warning "MySQL 未安装"
+ call :install_mysql
+) else (
+ for /f "tokens=*" %%i in ('mysql --version') do set MYSQL_VERSION=%%i
+ call :print_message "MySQL 版本检查通过: %MYSQL_VERSION%"
+)
+
+:: 检查 Git
+call :print_message "检查 Git..."
+
+git --version >nul 2>&1
+if %errorlevel% neq 0 (
+ call :print_warning "Git 未安装"
+ call :install_git
+) else (
+ for /f "tokens=*" %%i in ('git --version') do set GIT_VERSION=%%i
+ call :print_message "Git 版本检查通过: %GIT_VERSION%"
+)
+
+:: 安装项目依赖
+call :print_message "安装项目依赖..."
+
+if exist "package.json" (
+ npm install
+ if %errorlevel% neq 0 (
+ call :print_error "项目依赖安装失败"
+ pause
+ exit /b 1
+ ) else (
+ call :print_message "项目依赖安装完成"
+ )
+) else (
+ call :print_error "package.json 文件不存在"
+ pause
+ exit /b 1
+)
+
+:: 配置环境变量
+call :print_message "配置环境变量..."
+
+if not exist ".env.local" (
+ if exist ".env.example" (
+ copy ".env.example" ".env.local" >nul
+ call :print_message "已创建 .env.local 文件"
+ call :print_warning "请编辑 .env.local 文件,填入您的配置信息"
+ ) else (
+ call :print_warning ".env.example 文件不存在,请手动创建 .env.local 文件"
+ )
+) else (
+ call :print_message ".env.local 文件已存在"
+)
+
+:: 设置数据库
+call :print_message "设置数据库..."
+
+if exist "create-tables-final.js" (
+ call :print_message "创建数据库表..."
+ node create-tables-final.js
+ if %errorlevel% neq 0 (
+ call :print_warning "数据库表创建失败"
+ )
+) else (
+ call :print_warning "数据库脚本不存在,跳过数据库设置"
+)
+
+if exist "create-template-data.js" (
+ call :print_message "创建测试数据..."
+ node create-template-data.js
+ if %errorlevel% neq 0 (
+ call :print_warning "测试数据创建失败"
+ )
+) else (
+ call :print_warning "测试数据脚本不存在,跳过数据创建"
+)
+
+:: 验证安装
+call :print_message "验证安装..."
+
+:: 检查关键文件
+set "FILES=package.json next.config.js src\app\layout.tsx"
+for %%f in (%FILES%) do (
+ if exist "%%f" (
+ call :print_message "✓ %%f 存在"
+ ) else (
+ call :print_warning "⚠ %%f 不存在"
+ )
+)
+
+:: 检查依赖
+if exist "node_modules" (
+ call :print_message "✓ node_modules 目录存在"
+) else (
+ call :print_error "✗ node_modules 目录不存在"
+)
+
+:: 类型检查
+call :print_message "运行 TypeScript 类型检查..."
+npm run type-check >nul 2>&1
+if %errorlevel% neq 0 (
+ call :print_warning "⚠ TypeScript 类型检查失败"
+) else (
+ call :print_message "✓ TypeScript 类型检查通过"
+)
+
+:: 显示后续步骤
+echo.
+echo %BLUE%================================%NC%
+echo %BLUE% 安装完成!后续步骤:%NC%
+echo %BLUE%================================%NC%
+echo.
+echo 1. 编辑 .env.local 文件,配置数据库和 API 密钥
+echo 2. 启动开发服务器: npm run dev
+echo 3. 访问 http://localhost:3000
+echo 4. 注册新账户并开始使用
+echo.
+echo 📖 更多信息请查看:
+echo - 安装指南: INSTALLATION_GUIDE.md
+echo - 环境配置: ENV_SETUP_GUIDE.md
+echo - 模板教程: TEMPLATE_TUTORIAL.md
+echo.
+echo 🚀 祝您使用愉快!
+echo.
+pause
+goto :eof
+
+:: 安装 Node.js
+:install_nodejs
+call :print_message "安装 Node.js..."
+call :print_warning "请手动安装 Node.js: https://nodejs.org/"
+call :print_warning "安装完成后重新运行此脚本"
+pause
+exit /b 1
+
+:: 安装 MySQL
+:install_mysql
+call :print_message "安装 MySQL..."
+call :print_warning "请手动安装 MySQL: https://dev.mysql.com/downloads/mysql/"
+call :print_warning "安装完成后重新运行此脚本"
+pause
+exit /b 1
+
+:: 安装 Git
+:install_git
+call :print_message "安装 Git..."
+call :print_warning "请手动安装 Git: https://git-scm.com/"
+call :print_warning "安装完成后重新运行此脚本"
+pause
+exit /b 1
diff --git a/install.sh b/install.sh
new file mode 100644
index 0000000..541f728
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,302 @@
+#!/bin/bash
+
+# PromptForge 自动化安装脚本
+# 适用于 Linux 和 macOS 系统
+
+set -e
+
+# 颜色定义
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# 打印带颜色的消息
+print_message() {
+ echo -e "${GREEN}[INFO]${NC} $1"
+}
+
+print_warning() {
+ echo -e "${YELLOW}[WARNING]${NC} $1"
+}
+
+print_error() {
+ echo -e "${RED}[ERROR]${NC} $1"
+}
+
+print_header() {
+ echo -e "${BLUE}================================${NC}"
+ echo -e "${BLUE} PromptForge 自动化安装脚本${NC}"
+ echo -e "${BLUE}================================${NC}"
+}
+
+# 检查系统要求
+check_system_requirements() {
+ print_message "检查系统要求..."
+
+ # 检查操作系统
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ print_message "检测到 Linux 系统"
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ print_message "检测到 macOS 系统"
+ else
+ print_error "不支持的操作系统: $OSTYPE"
+ exit 1
+ fi
+
+ # 检查内存
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ MEMORY=$(free -m | awk 'NR==2{printf "%.0f", $2/1024}')
+ else
+ MEMORY=$(sysctl -n hw.memsize | awk '{printf "%.0f", $1/1024/1024/1024}')
+ fi
+
+ if [ "$MEMORY" -lt 4 ]; then
+ print_warning "内存不足,推荐至少 4GB RAM,当前: ${MEMORY}GB"
+ else
+ print_message "内存检查通过: ${MEMORY}GB"
+ fi
+
+ # 检查磁盘空间
+ DISK_SPACE=$(df -BG . | awk 'NR==2{print $4}' | sed 's/G//')
+ if [ "$DISK_SPACE" -lt 2 ]; then
+ print_warning "磁盘空间不足,推荐至少 2GB,当前: ${DISK_SPACE}GB"
+ else
+ print_message "磁盘空间检查通过: ${DISK_SPACE}GB"
+ fi
+}
+
+# 检查 Node.js
+check_nodejs() {
+ print_message "检查 Node.js..."
+
+ if command -v node &> /dev/null; then
+ NODE_VERSION=$(node --version | sed 's/v//')
+ NODE_MAJOR=$(echo $NODE_VERSION | cut -d. -f1)
+
+ if [ "$NODE_MAJOR" -ge 18 ]; then
+ print_message "Node.js 版本检查通过: v$NODE_VERSION"
+ else
+ print_error "Node.js 版本过低,需要 v18.0.0 或更高版本,当前: v$NODE_VERSION"
+ install_nodejs
+ fi
+ else
+ print_warning "Node.js 未安装"
+ install_nodejs
+ fi
+
+ if command -v npm &> /dev/null; then
+ NPM_VERSION=$(npm --version)
+ print_message "npm 版本: v$NPM_VERSION"
+ else
+ print_error "npm 未安装"
+ exit 1
+ fi
+}
+
+# 安装 Node.js
+install_nodejs() {
+ print_message "安装 Node.js..."
+
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Linux 安装
+ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
+ sudo apt-get install -y nodejs
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS 安装
+ if command -v brew &> /dev/null; then
+ brew install node
+ else
+ print_error "请先安装 Homebrew: https://brew.sh/"
+ exit 1
+ fi
+ fi
+
+ print_message "Node.js 安装完成"
+}
+
+# 检查 MySQL
+check_mysql() {
+ print_message "检查 MySQL..."
+
+ if command -v mysql &> /dev/null; then
+ MYSQL_VERSION=$(mysql --version | awk '{print $5}' | sed 's/,//')
+ print_message "MySQL 版本检查通过: $MYSQL_VERSION"
+ else
+ print_warning "MySQL 未安装"
+ install_mysql
+ fi
+}
+
+# 安装 MySQL
+install_mysql() {
+ print_message "安装 MySQL..."
+
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Linux 安装
+ sudo apt update
+ sudo apt install -y mysql-server
+ sudo systemctl start mysql
+ sudo systemctl enable mysql
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS 安装
+ if command -v brew &> /dev/null; then
+ brew install mysql
+ brew services start mysql
+ else
+ print_error "请先安装 Homebrew: https://brew.sh/"
+ exit 1
+ fi
+ fi
+
+ print_message "MySQL 安装完成"
+}
+
+# 检查 Git
+check_git() {
+ print_message "检查 Git..."
+
+ if command -v git &> /dev/null; then
+ GIT_VERSION=$(git --version | awk '{print $3}')
+ print_message "Git 版本检查通过: $GIT_VERSION"
+ else
+ print_warning "Git 未安装"
+ install_git
+ fi
+}
+
+# 安装 Git
+install_git() {
+ print_message "安装 Git..."
+
+ if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ sudo apt update
+ sudo apt install -y git
+ elif [[ "$OSTYPE" == "darwin"* ]]; then
+ if command -v brew &> /dev/null; then
+ brew install git
+ else
+ print_error "请先安装 Homebrew: https://brew.sh/"
+ exit 1
+ fi
+ fi
+
+ print_message "Git 安装完成"
+}
+
+# 安装项目依赖
+install_dependencies() {
+ print_message "安装项目依赖..."
+
+ if [ -f "package.json" ]; then
+ npm install
+ print_message "项目依赖安装完成"
+ else
+ print_error "package.json 文件不存在"
+ exit 1
+ fi
+}
+
+# 配置环境变量
+setup_environment() {
+ print_message "配置环境变量..."
+
+ if [ ! -f ".env.local" ]; then
+ if [ -f ".env.example" ]; then
+ cp .env.example .env.local
+ print_message "已创建 .env.local 文件"
+ print_warning "请编辑 .env.local 文件,填入您的配置信息"
+ else
+ print_warning ".env.example 文件不存在,请手动创建 .env.local 文件"
+ fi
+ else
+ print_message ".env.local 文件已存在"
+ fi
+}
+
+# 设置数据库
+setup_database() {
+ print_message "设置数据库..."
+
+ # 检查数据库脚本是否存在
+ if [ -f "create-tables-final.js" ]; then
+ print_message "创建数据库表..."
+ node create-tables-final.js
+ else
+ print_warning "数据库脚本不存在,跳过数据库设置"
+ fi
+
+ if [ -f "create-template-data.js" ]; then
+ print_message "创建测试数据..."
+ node create-template-data.js
+ else
+ print_warning "测试数据脚本不存在,跳过数据创建"
+ fi
+}
+
+# 验证安装
+verify_installation() {
+ print_message "验证安装..."
+
+ # 检查关键文件
+ FILES=("package.json" "next.config.js" "src/app/layout.tsx")
+ for file in "${FILES[@]}"; do
+ if [ -f "$file" ]; then
+ print_message "✓ $file 存在"
+ else
+ print_warning "⚠ $file 不存在"
+ fi
+ done
+
+ # 检查依赖
+ if [ -d "node_modules" ]; then
+ print_message "✓ node_modules 目录存在"
+ else
+ print_error "✗ node_modules 目录不存在"
+ fi
+
+ # 类型检查
+ if npm run type-check &> /dev/null; then
+ print_message "✓ TypeScript 类型检查通过"
+ else
+ print_warning "⚠ TypeScript 类型检查失败"
+ fi
+}
+
+# 显示后续步骤
+show_next_steps() {
+ echo -e "${BLUE}================================${NC}"
+ echo -e "${BLUE} 安装完成!后续步骤:${NC}"
+ echo -e "${BLUE}================================${NC}"
+ echo ""
+ echo "1. 编辑 .env.local 文件,配置数据库和 API 密钥"
+ echo "2. 启动开发服务器: npm run dev"
+ echo "3. 访问 http://localhost:3000"
+ echo "4. 注册新账户并开始使用"
+ echo ""
+ echo "📖 更多信息请查看:"
+ echo " - 安装指南: INSTALLATION_GUIDE.md"
+ echo " - 环境配置: ENV_SETUP_GUIDE.md"
+ echo " - 模板教程: TEMPLATE_TUTORIAL.md"
+ echo ""
+ echo "🚀 祝您使用愉快!"
+}
+
+# 主函数
+main() {
+ print_header
+
+ check_system_requirements
+ check_nodejs
+ check_mysql
+ check_git
+ install_dependencies
+ setup_environment
+ setup_database
+ verify_installation
+ show_next_steps
+}
+
+# 运行主函数
+main "$@"
diff --git a/migrate-prompt-template-data.js b/migrate-prompt-template-data.js
new file mode 100644
index 0000000..3282a2a
--- /dev/null
+++ b/migrate-prompt-template-data.js
@@ -0,0 +1,160 @@
+const mysql = require('mysql2/promise');
+
+// 数据库连接配置
+const dbConfig = {
+ host: 'gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
+ port: 24936,
+ user: 'root',
+ password: '!Rjb12191',
+ database: 'pronode_db',
+ charset: 'utf8mb4'
+};
+
+async function migratePromptTemplateData() {
+ let connection;
+
+ try {
+ console.log('🔗 连接数据库...');
+ connection = await mysql.createConnection(dbConfig);
+
+ // 1. 首先检查 prompt_template 表是否存在
+ console.log('📋 检查 prompt_template 表...');
+ const [tables] = await connection.execute(`
+ SELECT TABLE_NAME
+ FROM information_schema.TABLES
+ WHERE TABLE_SCHEMA = 'pronode_db'
+ AND TABLE_NAME = 'prompt_template'
+ `);
+
+ if (tables.length === 0) {
+ console.log('❌ prompt_template 表不存在');
+ return;
+ }
+
+ // 2. 获取 prompt_template 表的结构
+ console.log('🔍 获取 prompt_template 表结构...');
+ const [columns] = await connection.execute(`
+ DESCRIBE prompt_template
+ `);
+ console.log('prompt_template 表结构:', columns);
+
+ // 3. 获取 prompt_template 表中的所有数据
+ console.log('📊 获取 prompt_template 数据...');
+ const [sourceData] = await connection.execute('SELECT * FROM prompt_template');
+ console.log(`找到 ${sourceData.length} 条数据`);
+
+ if (sourceData.length === 0) {
+ console.log('❌ prompt_template 表中没有数据');
+ return;
+ }
+
+ // 4. 显示前几条数据作为示例
+ console.log('📝 数据示例:');
+ sourceData.slice(0, 3).forEach((row, index) => {
+ console.log(`记录 ${index + 1}:`, row);
+ });
+
+ // 5. 获取 promptforge_templates 表结构
+ console.log('🔍 获取 promptforge_templates 表结构...');
+ const [targetColumns] = await connection.execute(`
+ DESCRIBE promptforge_templates
+ `);
+ console.log('promptforge_templates 表结构:', targetColumns);
+
+ // 6. 开始数据迁移
+ console.log('🚀 开始数据迁移...');
+ let successCount = 0;
+ let errorCount = 0;
+
+ for (const sourceRow of sourceData) {
+ try {
+ // 构建目标数据,根据字段名进行映射
+ const targetData = {
+ id: sourceRow.id || `template_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
+ title: sourceRow.title || sourceRow.name || '未命名模板',
+ description: sourceRow.description || sourceRow.desc || '',
+ category: sourceRow.category || 'programming',
+ role: sourceRow.role || '',
+ task: sourceRow.task || '',
+ context: sourceRow.context || '',
+ constraints: sourceRow.constraints ? JSON.stringify(sourceRow.constraints) : '[]',
+ variables: sourceRow.variables ? JSON.stringify(sourceRow.variables) : '[]',
+ outputFormat: sourceRow.outputFormat || sourceRow.output_format || '',
+ authorId: sourceRow.authorId || sourceRow.user_id || sourceRow.author_id || 'system',
+ isPublic: sourceRow.isPublic || sourceRow.is_public || true,
+ usageCount: sourceRow.usageCount || sourceRow.usage_count || 0,
+ rating: sourceRow.rating || 0,
+ ratingCount: sourceRow.ratingCount || sourceRow.rating_count || 0,
+ createdAt: sourceRow.createdAt || sourceRow.created_at || new Date().toISOString().slice(0, 19).replace('T', ' '),
+ updatedAt: sourceRow.updatedAt || sourceRow.updated_at || new Date().toISOString().slice(0, 19).replace('T', ' ')
+ };
+
+ // 检查是否已存在相同ID的记录
+ const [existing] = await connection.execute(
+ 'SELECT id FROM promptforge_templates WHERE id = ?',
+ [targetData.id]
+ );
+
+ if (existing.length > 0) {
+ console.log(`⚠️ 跳过已存在的记录: ${targetData.id}`);
+ continue;
+ }
+
+ // 插入数据
+ await connection.execute(`
+ INSERT INTO promptforge_templates (
+ id, title, description, category, role, task, context,
+ constraints, variables, outputFormat, authorId, isPublic,
+ usageCount, rating, ratingCount, createdAt, updatedAt
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ `, [
+ targetData.id,
+ targetData.title,
+ targetData.description,
+ targetData.category,
+ targetData.role,
+ targetData.task,
+ targetData.context,
+ targetData.constraints,
+ targetData.variables,
+ targetData.outputFormat,
+ targetData.authorId,
+ targetData.isPublic,
+ targetData.usageCount,
+ targetData.rating,
+ targetData.ratingCount,
+ targetData.createdAt,
+ targetData.updatedAt
+ ]);
+
+ successCount++;
+ console.log(`✅ 成功迁移: ${targetData.title}`);
+
+ } catch (error) {
+ errorCount++;
+ console.error(`❌ 迁移失败 (${sourceRow.id || 'unknown'}):`, error.message);
+ }
+ }
+
+ console.log('\n📊 迁移完成统计:');
+ console.log(`✅ 成功: ${successCount} 条`);
+ console.log(`❌ 失败: ${errorCount} 条`);
+ console.log(`📝 总计: ${sourceData.length} 条`);
+
+ // 7. 验证迁移结果
+ console.log('\n🔍 验证迁移结果...');
+ const [finalCount] = await connection.execute('SELECT COUNT(*) as count FROM promptforge_templates');
+ console.log(`promptforge_templates 表现在有 ${finalCount[0].count} 条记录`);
+
+ } catch (error) {
+ console.error('❌ 迁移过程中发生错误:', error);
+ } finally {
+ if (connection) {
+ await connection.end();
+ console.log('🔌 数据库连接已关闭');
+ }
+ }
+}
+
+// 运行迁移
+migratePromptTemplateData().catch(console.error);
diff --git a/next.config.js b/next.config.js
new file mode 100644
index 0000000..f2adb83
--- /dev/null
+++ b/next.config.js
@@ -0,0 +1,15 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ images: {
+ domains: ['localhost'],
+ },
+ webpack: (config) => {
+ config.resolve.fallback = {
+ ...config.resolve.fallback,
+ fs: false,
+ };
+ return config;
+ },
+}
+
+module.exports = nextConfig
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..ec4945e
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,8018 @@
+{
+ "name": "promptforge",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "promptforge",
+ "version": "0.1.0",
+ "dependencies": {
+ "@mantine/code-highlight": "^7.3.2",
+ "@mantine/core": "^7.3.2",
+ "@mantine/dropzone": "^7.3.2",
+ "@mantine/form": "^7.3.2",
+ "@mantine/hooks": "^7.3.2",
+ "@mantine/notifications": "^7.3.2",
+ "@mantine/tiptap": "^7.3.2",
+ "@monaco-editor/react": "^4.6.0",
+ "@prisma/client": "^5.7.1",
+ "@tabler/icons-react": "^2.44.0",
+ "bcryptjs": "^2.4.3",
+ "clsx": "^2.0.0",
+ "framer-motion": "^10.16.16",
+ "lucide-react": "^0.303.0",
+ "mysql2": "^3.14.3",
+ "next": "14.0.4",
+ "next-auth": "^4.24.5",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-hot-toast": "^2.4.1",
+ "tailwind-merge": "^2.2.0",
+ "zustand": "^4.4.7"
+ },
+ "devDependencies": {
+ "@types/bcryptjs": "^2.4.6",
+ "@types/node": "^20.10.5",
+ "@types/react": "^18.2.45",
+ "@types/react-dom": "^18.2.18",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "14.0.4",
+ "postcss": "^8.4.32",
+ "prisma": "^5.7.1",
+ "tailwindcss": "^3.4.0",
+ "tsx": "^4.7.0",
+ "typescript": "^5.3.3"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.3",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz",
+ "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
+ "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
+ "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
+ "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+ "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emotion/memoize": "0.7.4"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
+ "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
+ "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz",
+ "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz",
+ "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz",
+ "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
+ "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz",
+ "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz",
+ "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz",
+ "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz",
+ "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz",
+ "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz",
+ "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz",
+ "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz",
+ "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz",
+ "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz",
+ "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz",
+ "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz",
+ "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz",
+ "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz",
+ "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz",
+ "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz",
+ "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz",
+ "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz",
+ "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz",
+ "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz",
+ "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz",
+ "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
+ "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.3",
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.26.28",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz",
+ "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.2",
+ "@floating-ui/utils": "^0.2.8",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
+ "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.4"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
+ "license": "MIT"
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz",
+ "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.30",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
+ "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@mantine/code-highlight": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/code-highlight/-/code-highlight-7.17.8.tgz",
+ "integrity": "sha512-KfdLi8MhpoeHiXkLMfuPQz1IDTUjvP2w3hbdx8Oz/hL0o+mbPYfgrU/w/D3ONjVQMoEbPpEL5vSA2eTYCmwVKg==",
+ "license": "MIT",
+ "dependencies": {
+ "clsx": "^2.1.1",
+ "highlight.js": "^11.10.0"
+ },
+ "peerDependencies": {
+ "@mantine/core": "7.17.8",
+ "@mantine/hooks": "7.17.8",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/core": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.17.8.tgz",
+ "integrity": "sha512-42sfdLZSCpsCYmLCjSuntuPcDg3PLbakSmmYfz5Auea8gZYLr+8SS5k647doVu0BRAecqYOytkX2QC5/u/8VHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react": "^0.26.28",
+ "clsx": "^2.1.1",
+ "react-number-format": "^5.4.3",
+ "react-remove-scroll": "^2.6.2",
+ "react-textarea-autosize": "8.5.9",
+ "type-fest": "^4.27.0"
+ },
+ "peerDependencies": {
+ "@mantine/hooks": "7.17.8",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/dropzone": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-7.17.8.tgz",
+ "integrity": "sha512-c9WEArpP23E9tbRWqoznEY3bGPVntMuBKr3F2LQijgdpdALIzt6DYmwXu7gUajGX9Qg9NrCHenhvWLTYqKnRlA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-dropzone-esm": "15.2.0"
+ },
+ "peerDependencies": {
+ "@mantine/core": "7.17.8",
+ "@mantine/hooks": "7.17.8",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/form": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.17.8.tgz",
+ "integrity": "sha512-cRLAMYOsZT17jyV9Myl29xacgaswGVAz3Ku6bvphBFad7Nzorra809uKFJxm2yKW5NknZ4ENHSXjyru7k0GTGA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "klona": "^2.0.6"
+ },
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/hooks": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.17.8.tgz",
+ "integrity": "sha512-96qygbkTjRhdkzd5HDU8fMziemN/h758/EwrFu7TlWrEP10Vw076u+Ap/sG6OT4RGPZYYoHrTlT+mkCZblWHuw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/notifications": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.17.8.tgz",
+ "integrity": "sha512-/YK16IZ198W6ru/IVecCtHcVveL08u2c8TbQTu/2p26LSIM9AbJhUkrU6H+AO0dgVVvmdmNdvPxcJnfq3S9TMg==",
+ "license": "MIT",
+ "dependencies": {
+ "@mantine/store": "7.17.8",
+ "react-transition-group": "4.4.5"
+ },
+ "peerDependencies": {
+ "@mantine/core": "7.17.8",
+ "@mantine/hooks": "7.17.8",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/store": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.17.8.tgz",
+ "integrity": "sha512-/FrB6PAVH4NEjQ1dsc9qOB+VvVlSuyjf4oOOlM9gscPuapDP/79Ryq7JkhHYfS55VWQ/YUlY24hDI2VV+VptXg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@mantine/tiptap": {
+ "version": "7.17.8",
+ "resolved": "https://registry.npmjs.org/@mantine/tiptap/-/tiptap-7.17.8.tgz",
+ "integrity": "sha512-LXeabIHhh0mKxlzWijDzacOzMGwI4oPvvr50igeHqUZrL5CTSAFVvQ9eAQQuTQxHJFVDGNuY4Qf5TqepSfA/CQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@mantine/core": "7.17.8",
+ "@mantine/hooks": "7.17.8",
+ "@tiptap/extension-link": ">=2.1.12",
+ "@tiptap/react": ">=2.1.12",
+ "react": "^18.x || ^19.x",
+ "react-dom": "^18.x || ^19.x"
+ }
+ },
+ "node_modules/@monaco-editor/loader": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz",
+ "integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==",
+ "license": "MIT",
+ "dependencies": {
+ "state-local": "^1.0.6"
+ }
+ },
+ "node_modules/@monaco-editor/react": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
+ "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@monaco-editor/loader": "^1.5.0"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.25.0 < 1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
+ "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@tybys/wasm-util": "^0.10.0"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz",
+ "integrity": "sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==",
+ "license": "MIT"
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz",
+ "integrity": "sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "glob": "7.1.7"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz",
+ "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz",
+ "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz",
+ "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz",
+ "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz",
+ "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz",
+ "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz",
+ "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz",
+ "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz",
+ "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nolyfill/is-core-module": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
+ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.4.0"
+ }
+ },
+ "node_modules/@panva/hkdf": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
+ "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@prisma/client": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz",
+ "integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16.13"
+ },
+ "peerDependencies": {
+ "prisma": "*"
+ },
+ "peerDependenciesMeta": {
+ "prisma": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@prisma/debug": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz",
+ "integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==",
+ "devOptional": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/engines": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz",
+ "integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0",
+ "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "@prisma/fetch-engine": "5.22.0",
+ "@prisma/get-platform": "5.22.0"
+ }
+ },
+ "node_modules/@prisma/engines-version": {
+ "version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz",
+ "integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==",
+ "devOptional": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/fetch-engine": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz",
+ "integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0",
+ "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2",
+ "@prisma/get-platform": "5.22.0"
+ }
+ },
+ "node_modules/@prisma/get-platform": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz",
+ "integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.22.0"
+ }
+ },
+ "node_modules/@remirror/core-constants": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz",
+ "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.12.0.tgz",
+ "integrity": "sha512-5EwMtOqvJMMa3HbmxLlF74e+3/HhwBTMcvt3nqVJgGCozO6hzIPOBlwm8mGVNR9SN2IJpxSnlxczyDjcn7qIyw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
+ "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tabler/icons": {
+ "version": "2.47.0",
+ "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-2.47.0.tgz",
+ "integrity": "sha512-4w5evLh+7FUUiA1GucvGj2ReX2TvOjEr4ejXdwL/bsjoSkof6r1gQmzqI+VHrE2CpJpB3al7bCTulOkFa/RcyA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ }
+ },
+ "node_modules/@tabler/icons-react": {
+ "version": "2.47.0",
+ "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-2.47.0.tgz",
+ "integrity": "sha512-iqly2FvCF/qUbgmvS8E40rVeYY7laltc5GUjRxQj59DuX0x/6CpKHTXt86YlI2whg4czvd/c8Ce8YR08uEku0g==",
+ "license": "MIT",
+ "dependencies": {
+ "@tabler/icons": "2.47.0",
+ "prop-types": "^15.7.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/codecalm"
+ },
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@tiptap/core": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.3.0.tgz",
+ "integrity": "sha512-YAmFITHzgp/hafA7Ety1qMo4Tl5e5b2+06LaiB9k3rAI7gfO6AXCwhXUqm3fCScmBfMMvMycq9IOIiHk946IzA==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/pm": "^3.3.0"
+ }
+ },
+ "node_modules/@tiptap/extension-link": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.3.0.tgz",
+ "integrity": "sha512-bQa8KHj5TFnZn8bCdpqDQUzsdsSt/VahZ9ZxvGgv3szyKrbprvugmXbSmU1m0CwLegt/66OcO/r+BdUU+yciAw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "linkifyjs": "^4.3.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^3.3.0",
+ "@tiptap/pm": "^3.3.0"
+ }
+ },
+ "node_modules/@tiptap/pm": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.3.0.tgz",
+ "integrity": "sha512-uKsysdjP5kQbQRQN8YinN5lr71TVgsHKhxgkq/psXZzNoUh2fPoNpzkhZTaondgr0IXFwzYX+DA5cLkzu4ig/A==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-changeset": "^2.3.0",
+ "prosemirror-collab": "^1.3.1",
+ "prosemirror-commands": "^1.6.2",
+ "prosemirror-dropcursor": "^1.8.1",
+ "prosemirror-gapcursor": "^1.3.2",
+ "prosemirror-history": "^1.4.1",
+ "prosemirror-inputrules": "^1.4.0",
+ "prosemirror-keymap": "^1.2.2",
+ "prosemirror-markdown": "^1.13.1",
+ "prosemirror-menu": "^1.2.4",
+ "prosemirror-model": "^1.24.1",
+ "prosemirror-schema-basic": "^1.2.3",
+ "prosemirror-schema-list": "^1.5.0",
+ "prosemirror-state": "^1.4.3",
+ "prosemirror-tables": "^1.6.4",
+ "prosemirror-trailing-node": "^3.0.0",
+ "prosemirror-transform": "^1.10.2",
+ "prosemirror-view": "^1.38.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
+ "node_modules/@tiptap/react": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.3.0.tgz",
+ "integrity": "sha512-7TCloYAMcEA0Z+Ke5m2X8BRM15amIzXRYPPXLlLKfDdYZgUh597jfF25gT5k/1MRPREo84p+GyP1OcY2WdTrjA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "fast-deep-equal": "^3.1.3",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "optionalDependencies": {
+ "@tiptap/extension-bubble-menu": "^3.3.0",
+ "@tiptap/extension-floating-menu": "^3.3.0"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "^3.3.0",
+ "@tiptap/pm": "^3.3.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz",
+ "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/bcryptjs": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
+ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "14.1.2",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/linkify-it": "^5",
+ "@types/mdurl": "^2"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.11.tgz",
+ "integrity": "sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.15",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.24",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.24.tgz",
+ "integrity": "sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
+ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
+ "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
+ "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
+ "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
+ "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
+ "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
+ "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
+ "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
+ "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
+ "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
+ "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
+ "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
+ "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
+ "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
+ "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
+ "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
+ "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^0.2.11"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
+ "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
+ "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
+ "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.21",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
+ "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.24.4",
+ "caniuse-lite": "^1.0.30001702",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/aws-ssl-profiles": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
+ "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.10.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz",
+ "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
+ "license": "MIT"
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.25.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz",
+ "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001737",
+ "electron-to-chromium": "^1.5.211",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001737",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz",
+ "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/crelt": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
+ "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "license": "MIT"
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.211",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz",
+ "integrity": "sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "peer": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.0",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
+ "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
+ "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.3",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.6",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.4",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.25.9",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
+ "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.9",
+ "@esbuild/android-arm": "0.25.9",
+ "@esbuild/android-arm64": "0.25.9",
+ "@esbuild/android-x64": "0.25.9",
+ "@esbuild/darwin-arm64": "0.25.9",
+ "@esbuild/darwin-x64": "0.25.9",
+ "@esbuild/freebsd-arm64": "0.25.9",
+ "@esbuild/freebsd-x64": "0.25.9",
+ "@esbuild/linux-arm": "0.25.9",
+ "@esbuild/linux-arm64": "0.25.9",
+ "@esbuild/linux-ia32": "0.25.9",
+ "@esbuild/linux-loong64": "0.25.9",
+ "@esbuild/linux-mips64el": "0.25.9",
+ "@esbuild/linux-ppc64": "0.25.9",
+ "@esbuild/linux-riscv64": "0.25.9",
+ "@esbuild/linux-s390x": "0.25.9",
+ "@esbuild/linux-x64": "0.25.9",
+ "@esbuild/netbsd-arm64": "0.25.9",
+ "@esbuild/netbsd-x64": "0.25.9",
+ "@esbuild/openbsd-arm64": "0.25.9",
+ "@esbuild/openbsd-x64": "0.25.9",
+ "@esbuild/openharmony-arm64": "0.25.9",
+ "@esbuild/sunos-x64": "0.25.9",
+ "@esbuild/win32-arm64": "0.25.9",
+ "@esbuild/win32-ia32": "0.25.9",
+ "@esbuild/win32-x64": "0.25.9"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.0.4.tgz",
+ "integrity": "sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@next/eslint-plugin-next": "14.0.4",
+ "@rushstack/eslint-patch": "^1.3.3",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.28.1",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
+ "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.4.0",
+ "get-tsconfig": "^4.10.0",
+ "is-bun-module": "^2.0.0",
+ "stable-hash": "^0.0.5",
+ "tinyglobby": "^0.2.13",
+ "unrs-resolver": "^1.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
+ "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.32.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
+ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.9",
+ "array.prototype.findlastindex": "^1.2.6",
+ "array.prototype.flat": "^1.3.3",
+ "array.prototype.flatmap": "^1.3.3",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.1",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.16.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.1",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.9",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
+ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aria-query": "^5.3.2",
+ "array-includes": "^3.1.8",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "^4.10.0",
+ "axobject-query": "^4.1.0",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.0.0-canary-7118f5dd7-20230705",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz",
+ "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/framer-motion": {
+ "version": "10.18.0",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.18.0.tgz",
+ "integrity": "sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ },
+ "optionalDependencies": {
+ "@emotion/is-prop-valid": "^0.8.2"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generate-function": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+ "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-property": "^1.0.2"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
+ "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globals/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/goober": {
+ "version": "2.1.16",
+ "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz",
+ "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==",
+ "license": "MIT",
+ "peerDependencies": {
+ "csstype": "^3.0.10"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/highlight.js": {
+ "version": "11.11.1",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
+ "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bun-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.7.1"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
+ "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.0",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
+ "license": "MIT"
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/jose": {
+ "version": "4.15.9",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
+ "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/klona": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
+ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
+ "node_modules/linkifyjs": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz",
+ "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/lru.min": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz",
+ "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==",
+ "license": "MIT",
+ "engines": {
+ "bun": ">=1.0.0",
+ "deno": ">=1.30.0",
+ "node": ">=8.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wellwelwel"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.303.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.303.0.tgz",
+ "integrity": "sha512-B0B9T3dLEFBYPCUlnUS1mvAhW1craSbF9HO+JfBjAtpFUJ7gMIqmEwNSclikY3RiN2OnCkj/V1ReAQpaHae8Bg==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/markdown-it": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
+ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.mjs"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/monaco-editor": {
+ "version": "0.52.2",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
+ "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mysql2": {
+ "version": "3.14.3",
+ "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.3.tgz",
+ "integrity": "sha512-fD6MLV8XJ1KiNFIF0bS7Msl8eZyhlTDCDl75ajU5SJtpdx9ZPEACulJcqJWr1Y8OYyxsFc4j3+nflpmhxCU5aQ==",
+ "license": "MIT",
+ "dependencies": {
+ "aws-ssl-profiles": "^1.1.1",
+ "denque": "^2.1.0",
+ "generate-function": "^2.3.1",
+ "iconv-lite": "^0.6.3",
+ "long": "^5.2.1",
+ "lru.min": "^1.0.0",
+ "named-placeholders": "^1.1.3",
+ "seq-queue": "^0.0.5",
+ "sqlstring": "^2.3.2"
+ },
+ "engines": {
+ "node": ">= 8.0"
+ }
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/named-placeholders": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
+ "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
+ "license": "MIT",
+ "dependencies": {
+ "lru-cache": "^7.14.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/named-placeholders/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-postinstall": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz",
+ "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/next": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/next/-/next-14.0.4.tgz",
+ "integrity": "sha512-qbwypnM7327SadwFtxXnQdGiKpkuhaRLE2uq62/nRul9cj9KhQ5LhHmlziTNqUidZotw/Q1I9OjirBROdUJNgA==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "14.0.4",
+ "@swc/helpers": "0.5.2",
+ "busboy": "1.6.0",
+ "caniuse-lite": "^1.0.30001406",
+ "graceful-fs": "^4.2.11",
+ "postcss": "8.4.31",
+ "styled-jsx": "5.1.1",
+ "watchpack": "2.4.0"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=18.17.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-darwin-arm64": "14.0.4",
+ "@next/swc-darwin-x64": "14.0.4",
+ "@next/swc-linux-arm64-gnu": "14.0.4",
+ "@next/swc-linux-arm64-musl": "14.0.4",
+ "@next/swc-linux-x64-gnu": "14.0.4",
+ "@next/swc-linux-x64-musl": "14.0.4",
+ "@next/swc-win32-arm64-msvc": "14.0.4",
+ "@next/swc-win32-ia32-msvc": "14.0.4",
+ "@next/swc-win32-x64-msvc": "14.0.4"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/next-auth": {
+ "version": "4.24.11",
+ "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz",
+ "integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==",
+ "license": "ISC",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "@panva/hkdf": "^1.0.2",
+ "cookie": "^0.7.0",
+ "jose": "^4.15.5",
+ "oauth": "^0.9.15",
+ "openid-client": "^5.4.0",
+ "preact": "^10.6.3",
+ "preact-render-to-string": "^5.1.19",
+ "uuid": "^8.3.2"
+ },
+ "peerDependencies": {
+ "@auth/core": "0.34.2",
+ "next": "^12.2.5 || ^13 || ^14 || ^15",
+ "nodemailer": "^6.6.5",
+ "react": "^17.0.2 || ^18 || ^19",
+ "react-dom": "^17.0.2 || ^18 || ^19"
+ },
+ "peerDependenciesMeta": {
+ "@auth/core": {
+ "optional": true
+ },
+ "nodemailer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/next/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/oauth": {
+ "version": "0.9.15",
+ "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
+ "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==",
+ "license": "MIT"
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/oidc-token-hash": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.1.tgz",
+ "integrity": "sha512-D7EmwxJV6DsEB6vOFLrBM2OzsVgQzgPWyHlV2OOAVj772n+WTXpudC9e9u5BVKQnYwaD30Ivhi9b+4UeBcGu9g==",
+ "license": "MIT",
+ "engines": {
+ "node": "^10.13.0 || >=12.0.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/openid-client": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz",
+ "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==",
+ "license": "MIT",
+ "dependencies": {
+ "jose": "^4.15.9",
+ "lru-cache": "^6.0.0",
+ "object-hash": "^2.2.0",
+ "oidc-token-hash": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/openid-client/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/openid-client/node_modules/object-hash": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
+ "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/orderedmap": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
+ "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/preact": {
+ "version": "10.27.1",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.1.tgz",
+ "integrity": "sha512-V79raXEWch/rbqoNc7nT9E4ep7lu+mI3+sBmfRD4i1M73R3WLYcCtdI0ibxGVf4eQL8ZIz2nFacqEC+rmnOORQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/preact-render-to-string": {
+ "version": "5.2.6",
+ "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz",
+ "integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==",
+ "license": "MIT",
+ "dependencies": {
+ "pretty-format": "^3.8.0"
+ },
+ "peerDependencies": {
+ "preact": ">=10"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
+ "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==",
+ "license": "MIT"
+ },
+ "node_modules/prisma": {
+ "version": "5.22.0",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz",
+ "integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==",
+ "devOptional": true,
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/engines": "5.22.0"
+ },
+ "bin": {
+ "prisma": "build/index.js"
+ },
+ "engines": {
+ "node": ">=16.13"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.3"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prosemirror-changeset": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz",
+ "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-collab": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz",
+ "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-state": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-commands": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz",
+ "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.10.2"
+ }
+ },
+ "node_modules/prosemirror-dropcursor": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz",
+ "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0",
+ "prosemirror-view": "^1.1.0"
+ }
+ },
+ "node_modules/prosemirror-gapcursor": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz",
+ "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-keymap": "^1.0.0",
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-view": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-history": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz",
+ "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-state": "^1.2.2",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.31.0",
+ "rope-sequence": "^1.3.0"
+ }
+ },
+ "node_modules/prosemirror-inputrules": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz",
+ "integrity": "sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-keymap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz",
+ "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "w3c-keyname": "^2.2.0"
+ }
+ },
+ "node_modules/prosemirror-markdown": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz",
+ "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/markdown-it": "^14.0.0",
+ "markdown-it": "^14.0.0",
+ "prosemirror-model": "^1.25.0"
+ }
+ },
+ "node_modules/prosemirror-menu": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz",
+ "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "crelt": "^1.0.0",
+ "prosemirror-commands": "^1.0.0",
+ "prosemirror-history": "^1.0.0",
+ "prosemirror-state": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-model": {
+ "version": "1.25.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.3.tgz",
+ "integrity": "sha512-dY2HdaNXlARknJbrManZ1WyUtos+AP97AmvqdOQtWtrrC5g4mohVX5DTi9rXNFSk09eczLq9GuNTtq3EfMeMGA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "orderedmap": "^2.0.0"
+ }
+ },
+ "node_modules/prosemirror-schema-basic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz",
+ "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-model": "^1.25.0"
+ }
+ },
+ "node_modules/prosemirror-schema-list": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz",
+ "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.7.3"
+ }
+ },
+ "node_modules/prosemirror-state": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz",
+ "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.27.0"
+ }
+ },
+ "node_modules/prosemirror-tables": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.1.tgz",
+ "integrity": "sha512-DAgDoUYHCcc6tOGpLVPSU1k84kCUWTWnfWX3UDy2Delv4ryH0KqTD6RBI6k4yi9j9I8gl3j8MkPpRD/vWPZbug==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-keymap": "^1.2.2",
+ "prosemirror-model": "^1.25.0",
+ "prosemirror-state": "^1.4.3",
+ "prosemirror-transform": "^1.10.3",
+ "prosemirror-view": "^1.39.1"
+ }
+ },
+ "node_modules/prosemirror-trailing-node": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz",
+ "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@remirror/core-constants": "3.0.0",
+ "escape-string-regexp": "^4.0.0"
+ },
+ "peerDependencies": {
+ "prosemirror-model": "^1.22.1",
+ "prosemirror-state": "^1.4.2",
+ "prosemirror-view": "^1.33.8"
+ }
+ },
+ "node_modules/prosemirror-transform": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.4.tgz",
+ "integrity": "sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-model": "^1.21.0"
+ }
+ },
+ "node_modules/prosemirror-view": {
+ "version": "1.40.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.40.1.tgz",
+ "integrity": "sha512-pbwUjt3G7TlsQQHDiYSupWBhJswpLVB09xXm1YiJPdkjkh9Pe7Y51XdLh5VWIZmROLY8UpUpG03lkdhm9lzIBA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "prosemirror-model": "^1.20.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-dropzone-esm": {
+ "version": "15.2.0",
+ "resolved": "https://registry.npmjs.org/react-dropzone-esm/-/react-dropzone-esm-15.2.0.tgz",
+ "integrity": "sha512-pPwR8xWVL+tFLnbAb8KVH5f6Vtl397tck8dINkZ1cPMxHWH+l9dFmIgRWgbh7V7jbjIcuKXCsVrXbhQz68+dVA==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "engines": {
+ "node": ">= 10.13"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8 || 18.0.0"
+ }
+ },
+ "node_modules/react-hot-toast": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz",
+ "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.1.3",
+ "goober": "^2.1.16"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
+ "node_modules/react-number-format": {
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz",
+ "integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/react-remove-scroll": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
+ "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
+ "dependencies": {
+ "react-style-singleton": "^2.2.2",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-style-singleton": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-textarea-autosize": {
+ "version": "8.5.9",
+ "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
+ "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "use-composed-ref": "^1.3.0",
+ "use-latest": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.10",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+ "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rope-sequence": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
+ "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+ "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/seq-queue": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
+ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sqlstring": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
+ "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/stable-hash": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
+ "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/state-local": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
+ "license": "MIT"
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz",
+ "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string.prototype.includes": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
+ "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
+ "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "license": "MIT",
+ "dependencies": {
+ "client-only": "0.0.1"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
+ "license": "MIT"
+ },
+ "node_modules/tailwind-merge": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz",
+ "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.17",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
+ "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.6",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
+ "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tsx": {
+ "version": "4.20.5",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz",
+ "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.25.0",
+ "get-tsconfig": "^4.7.5"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
+ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unrs-resolver": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
+ "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.3.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unrs-resolver"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-android-arm-eabi": "1.11.1",
+ "@unrs/resolver-binding-android-arm64": "1.11.1",
+ "@unrs/resolver-binding-darwin-arm64": "1.11.1",
+ "@unrs/resolver-binding-darwin-x64": "1.11.1",
+ "@unrs/resolver-binding-freebsd-x64": "1.11.1",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.11.1",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-x64-musl": "1.11.1",
+ "@unrs/resolver-binding-wasm32-wasi": "1.11.1",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-callback-ref": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-composed-ref": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz",
+ "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz",
+ "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-latest": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz",
+ "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "use-isomorphic-layout-effect": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/watchpack": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
+ "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
+ "license": "MIT",
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+ "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz",
+ "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/yaml": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
+ "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zustand": {
+ "version": "4.5.7",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz",
+ "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==",
+ "license": "MIT",
+ "dependencies": {
+ "use-sync-external-store": "^1.2.2"
+ },
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8",
+ "immer": ">=9.0.6",
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b975c51
--- /dev/null
+++ b/package.json
@@ -0,0 +1,55 @@
+{
+ "name": "promptforge",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "type-check": "tsc --noEmit",
+ "db:generate": "prisma generate",
+ "db:push": "prisma db push",
+ "db:migrate": "prisma migrate dev",
+ "db:studio": "prisma studio",
+ "db:seed": "tsx prisma/seed.ts"
+ },
+ "dependencies": {
+ "@mantine/code-highlight": "^7.3.2",
+ "@mantine/core": "^7.3.2",
+ "@mantine/dropzone": "^7.3.2",
+ "@mantine/form": "^7.3.2",
+ "@mantine/hooks": "^7.3.2",
+ "@mantine/notifications": "^7.3.2",
+ "@mantine/tiptap": "^7.3.2",
+ "@monaco-editor/react": "^4.6.0",
+ "@prisma/client": "^5.7.1",
+ "@tabler/icons-react": "^2.44.0",
+ "bcryptjs": "^2.4.3",
+ "clsx": "^2.0.0",
+ "framer-motion": "^10.16.16",
+ "lucide-react": "^0.303.0",
+ "mysql2": "^3.14.3",
+ "next": "14.0.4",
+ "next-auth": "^4.24.5",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-hot-toast": "^2.4.1",
+ "tailwind-merge": "^2.2.0",
+ "zustand": "^4.4.7"
+ },
+ "devDependencies": {
+ "@types/bcryptjs": "^2.4.6",
+ "@types/node": "^20.10.5",
+ "@types/react": "^18.2.45",
+ "@types/react-dom": "^18.2.18",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "14.0.4",
+ "postcss": "^8.4.32",
+ "prisma": "^5.7.1",
+ "tailwindcss": "^3.4.0",
+ "tsx": "^4.7.0",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..33ad091
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000..8e3a69e
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,123 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "mysql"
+ url = env("DATABASE_URL")
+}
+
+// 用户表
+model User {
+ id String @id @default(cuid())
+ email String @unique
+ name String?
+ avatar String?
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ // 关联关系
+ templates Template[]
+ favorites Favorite[]
+ comments Comment[]
+
+ @@map("users")
+}
+
+// 提示词模板表
+model Template {
+ id String @id @default(cuid())
+ title String
+ description String?
+ category String
+ tags String // JSON 格式存储标签数组
+ role String
+ task String
+ context String?
+ constraints String // JSON 格式存储约束数组
+ outputFormat String
+ variables String // JSON 格式存储变量数组
+ examples String? // JSON 格式存储示例数组
+
+ // 元数据
+ authorId String
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
+ isPublic Boolean @default(true)
+ isFeatured Boolean @default(false)
+
+ // 统计信息
+ usageCount Int @default(0)
+ rating Float @default(0)
+ ratingCount Int @default(0)
+
+ // 时间戳
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ // 关联关系
+ favorites Favorite[]
+ comments Comment[]
+ tests Test[]
+
+ @@map("templates")
+}
+
+// 收藏表
+model Favorite {
+ id String @id @default(cuid())
+ userId String
+ templateId String
+ createdAt DateTime @default(now())
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+ template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
+
+ @@unique([userId, templateId])
+ @@map("favorites")
+}
+
+// 评论表
+model Comment {
+ id String @id @default(cuid())
+ content String
+ rating Int? // 1-5 星评分
+ userId String
+ templateId String
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+ template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
+
+ @@map("comments")
+}
+
+// 测试记录表
+model Test {
+ id String @id @default(cuid())
+ templateId String
+ input String // JSON 格式存储输入变量
+ output String? // 测试输出结果
+ model String // 使用的模型
+ parameters String // JSON 格式存储模型参数
+ status String // success, error, pending
+ duration Int? // 执行时间(毫秒)
+ createdAt DateTime @default(now())
+
+ template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
+
+ @@map("tests")
+}
+
+// 系统配置表
+model SystemConfig {
+ id String @id @default(cuid())
+ key String @unique
+ value String
+ type String @default("string") // string, number, boolean, json
+
+ @@map("system_configs")
+}
diff --git a/prisma/seed.ts b/prisma/seed.ts
new file mode 100644
index 0000000..71d324a
--- /dev/null
+++ b/prisma/seed.ts
@@ -0,0 +1,170 @@
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+async function main() {
+ console.log('🌱 开始初始化数据库...')
+
+ // 创建示例用户
+ const user = await prisma.user.upsert({
+ where: { email: 'admin@promptforge.com' },
+ update: {},
+ create: {
+ email: 'admin@promptforge.com',
+ name: 'PromptForge Admin',
+ avatar: 'https://avatars.githubusercontent.com/u/1234567?v=4',
+ },
+ })
+
+ console.log('✅ 创建用户:', user.email)
+
+ // 创建示例模板
+ const templates = [
+ {
+ title: 'API设计文档生成器',
+ description: '生成完整的API设计文档,包含端点、参数、响应格式等',
+ category: 'programming',
+ tags: JSON.stringify(['api', 'documentation', 'backend']),
+ role: '你是一位资深软件架构师,拥有丰富的API设计经验。',
+ task: '我的任务是生成一个关于{{topic}}的API设计文档。',
+ context: '这个API将用于{{useCase}}场景,需要支持{{features}}功能。',
+ constraints: JSON.stringify([
+ { id: '1', text: '使用RESTful设计原则', category: 'quality' },
+ { id: '2', text: '包含完整的错误处理', category: 'safety' },
+ { id: '3', text: '提供OpenAPI 3.0规范', category: 'format' },
+ ]),
+ outputFormat: 'markdown',
+ variables: JSON.stringify([
+ { name: 'topic', type: 'text', required: true, description: 'API主题' },
+ { name: 'useCase', type: 'text', required: true, description: '使用场景' },
+ { name: 'features', type: 'text', required: false, description: '核心功能' },
+ ]),
+ examples: JSON.stringify([
+ {
+ input: { topic: '用户管理', useCase: '电商平台', features: '注册、登录、信息修改' },
+ output: '# 用户管理 API 设计文档\n\n## 概述\n用户管理API提供完整的用户账户管理功能...'
+ }
+ ]),
+ authorId: user.id,
+ isPublic: true,
+ isFeatured: true,
+ usageCount: 156,
+ rating: 4.8,
+ ratingCount: 23,
+ },
+ {
+ title: '营销文案优化器',
+ description: '优化营销文案,提升转化率和用户 engagement',
+ category: 'marketing',
+ tags: JSON.stringify(['marketing', 'copywriting', 'conversion']),
+ role: '你是一位经验丰富的营销文案专家,擅长AIDA模型和情感营销。',
+ task: '请优化以下营销文案,使其更具吸引力和转化力:{{originalCopy}}',
+ context: '目标受众是{{targetAudience}},产品是{{product}},主要卖点是{{valueProposition}}。',
+ constraints: JSON.stringify([
+ { id: '1', text: '保持品牌调性一致', category: 'quality' },
+ { id: '2', text: '包含明确的行动号召', category: 'format' },
+ { id: '3', text: '字数控制在{{wordLimit}}字以内', category: 'performance' },
+ ]),
+ outputFormat: 'plain-text',
+ variables: JSON.stringify([
+ { name: 'originalCopy', type: 'text', required: true, description: '原始文案' },
+ { name: 'targetAudience', type: 'text', required: true, description: '目标受众' },
+ { name: 'product', type: 'text', required: true, description: '产品名称' },
+ { name: 'valueProposition', type: 'text', required: true, description: '价值主张' },
+ { name: 'wordLimit', type: 'number', required: false, defaultValue: 200, description: '字数限制' },
+ ]),
+ examples: JSON.stringify([
+ {
+ input: {
+ originalCopy: '我们的产品很好用',
+ targetAudience: '年轻白领',
+ product: '智能办公助手',
+ valueProposition: '提升工作效率50%'
+ },
+ output: '🚀 告别加班!智能办公助手让年轻白领工作效率提升50%,每天节省2小时,享受生活!立即体验 →'
+ }
+ ]),
+ authorId: user.id,
+ isPublic: true,
+ isFeatured: true,
+ usageCount: 89,
+ rating: 4.6,
+ ratingCount: 15,
+ },
+ {
+ title: '技术文档翻译器',
+ description: '将技术文档翻译成多种语言,保持专业性和准确性',
+ category: 'translation',
+ tags: JSON.stringify(['translation', 'technical', 'documentation']),
+ role: '你是一位专业的技术文档翻译专家,精通多种语言和技术术语。',
+ task: '请将以下技术文档翻译成{{targetLanguage}}:{{originalText}}',
+ context: '这是一份{{documentType}}文档,目标读者是{{audienceLevel}}。',
+ constraints: JSON.stringify([
+ { id: '1', text: '保持技术术语的准确性', category: 'quality' },
+ { id: '2', text: '使用{{targetLanguage}}的专业表达', category: 'style' },
+ { id: '3', text: '保持原文的格式结构', category: 'format' },
+ ]),
+ outputFormat: 'markdown',
+ variables: JSON.stringify([
+ { name: 'originalText', type: 'text', required: true, description: '原文内容' },
+ { name: 'targetLanguage', type: 'select', required: true, description: '目标语言', options: ['英语', '日语', '韩语', '法语', '德语', '西班牙语'] },
+ { name: 'documentType', type: 'text', required: true, description: '文档类型' },
+ { name: 'audienceLevel', type: 'select', required: true, description: '读者水平', options: ['初学者', '中级', '高级', '专家'] },
+ ]),
+ examples: JSON.stringify([
+ {
+ input: {
+ originalText: 'API 接口返回 JSON 格式数据',
+ targetLanguage: '英语',
+ documentType: 'API文档',
+ audienceLevel: '中级'
+ },
+ output: 'The API endpoint returns data in JSON format'
+ }
+ ]),
+ authorId: user.id,
+ isPublic: true,
+ isFeatured: false,
+ usageCount: 67,
+ rating: 4.7,
+ ratingCount: 12,
+ }
+ ]
+
+ for (const templateData of templates) {
+ const template = await prisma.template.upsert({
+ where: { title: templateData.title },
+ update: {},
+ create: templateData,
+ })
+ console.log('✅ 创建模板:', template.title)
+ }
+
+ // 创建系统配置
+ const configs = [
+ { key: 'site_name', value: 'PromptForge', type: 'string' },
+ { key: 'site_description', value: '专为大模型提示词系统优化的平台', type: 'string' },
+ { key: 'max_templates_per_user', value: '100', type: 'number' },
+ { key: 'enable_registration', value: 'true', type: 'boolean' },
+ ]
+
+ for (const config of configs) {
+ await prisma.systemConfig.upsert({
+ where: { key: config.key },
+ update: {},
+ create: config,
+ })
+ console.log('✅ 创建配置:', config.key)
+ }
+
+ console.log('🎉 数据库初始化完成!')
+}
+
+main()
+ .catch((e) => {
+ console.error('❌ 数据库初始化失败:', e)
+ process.exit(1)
+ })
+ .finally(async () => {
+ await prisma.$disconnect()
+ })
diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts
new file mode 100644
index 0000000..de9abd8
--- /dev/null
+++ b/src/app/api/auth/login/route.ts
@@ -0,0 +1,50 @@
+import { NextRequest, NextResponse } from 'next/server'
+import bcrypt from 'bcryptjs'
+import { db } from '@/lib/database'
+
+export async function POST(request: NextRequest) {
+ try {
+ const { email, password } = await request.json()
+
+ // 验证输入
+ if (!email || !password) {
+ return NextResponse.json(
+ { error: '请提供邮箱和密码' },
+ { status: 400 }
+ )
+ }
+
+ // 查找用户
+ const user = await db.getUserByEmail(email)
+ if (!user) {
+ return NextResponse.json(
+ { error: '邮箱或密码错误' },
+ { status: 401 }
+ )
+ }
+
+ // 验证密码
+ const isPasswordValid = await bcrypt.compare(password, user.password)
+ if (!isPasswordValid) {
+ return NextResponse.json(
+ { error: '邮箱或密码错误' },
+ { status: 401 }
+ )
+ }
+
+ // 返回用户信息(不包含密码)
+ const { password: _, ...userWithoutPassword } = user
+
+ return NextResponse.json({
+ message: '登录成功',
+ user: userWithoutPassword
+ })
+
+ } catch (error) {
+ console.error('登录失败:', error)
+ return NextResponse.json(
+ { error: '登录失败,请稍后重试' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts
new file mode 100644
index 0000000..4c8462e
--- /dev/null
+++ b/src/app/api/auth/register/route.ts
@@ -0,0 +1,74 @@
+import { NextRequest, NextResponse } from 'next/server'
+import bcrypt from 'bcryptjs'
+import { db } from '@/lib/database'
+import { generateId } from '@/lib/utils'
+
+export async function POST(request: NextRequest) {
+ try {
+ const { email, password, name } = await request.json()
+
+ // 验证输入
+ if (!email || !password || !name) {
+ return NextResponse.json(
+ { error: '请提供邮箱、密码和姓名' },
+ { status: 400 }
+ )
+ }
+
+ // 验证邮箱格式
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
+ if (!emailRegex.test(email)) {
+ return NextResponse.json(
+ { error: '邮箱格式不正确' },
+ { status: 400 }
+ )
+ }
+
+ // 验证密码强度
+ if (password.length < 6) {
+ return NextResponse.json(
+ { error: '密码至少需要6个字符' },
+ { status: 400 }
+ )
+ }
+
+ // 检查邮箱是否已存在
+ const existingUser = await db.getUserByEmail(email)
+ if (existingUser) {
+ return NextResponse.json(
+ { error: '该邮箱已被注册' },
+ { status: 409 }
+ )
+ }
+
+ // 加密密码
+ const hashedPassword = await bcrypt.hash(password, 12)
+
+ // 创建用户
+ const userId = generateId()
+ const userData = {
+ id: userId,
+ email,
+ name,
+ password: hashedPassword,
+ avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${email}`
+ }
+
+ await db.createUser(userData)
+
+ // 返回用户信息(不包含密码)
+ const { password: _, ...userWithoutPassword } = userData
+
+ return NextResponse.json({
+ message: '注册成功',
+ user: userWithoutPassword
+ }, { status: 201 })
+
+ } catch (error) {
+ console.error('注册失败:', error)
+ return NextResponse.json(
+ { error: '注册失败,请稍后重试' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/api/templates/[id]/copy/route.ts b/src/app/api/templates/[id]/copy/route.ts
new file mode 100644
index 0000000..98f1045
--- /dev/null
+++ b/src/app/api/templates/[id]/copy/route.ts
@@ -0,0 +1,119 @@
+import { NextRequest, NextResponse } from 'next/server'
+import { db } from '@/lib/database'
+import { generateId } from '@/lib/utils'
+
+// 复制模板
+export async function POST(
+ request: NextRequest,
+ { params }: { params: { id: string } }
+) {
+ try {
+ const { id } = params
+ const body = await request.json()
+ const { userId } = body
+
+ if (!userId) {
+ return NextResponse.json(
+ { success: false, error: '用户ID为必填项' },
+ { status: 400 }
+ )
+ }
+
+ // 获取原模板
+ const originalTemplate = await db.getTemplateById(id)
+ if (!originalTemplate) {
+ return NextResponse.json(
+ { success: false, error: '模板不存在' },
+ { status: 404 }
+ )
+ }
+
+ // 检查模板是否公开
+ if (!originalTemplate.isPublic) {
+ return NextResponse.json(
+ { success: false, error: '无法复制私有模板' },
+ { status: 403 }
+ )
+ }
+
+ // 处理约束条件数据格式
+ let constraints = []
+ try {
+ if (typeof originalTemplate.constraints === 'string') {
+ // 如果是 JSON 字符串,解析为数组
+ const parsedConstraints = JSON.parse(originalTemplate.constraints)
+ if (Array.isArray(parsedConstraints)) {
+ // 如果是字符串数组,转换为对象数组
+ constraints = parsedConstraints.map((constraint, index) => {
+ if (typeof constraint === 'string') {
+ return {
+ id: generateId(),
+ text: constraint,
+ category: 'quality'
+ }
+ }
+ return constraint
+ })
+ }
+ } else if (Array.isArray(originalTemplate.constraints)) {
+ constraints = originalTemplate.constraints
+ }
+ } catch (error) {
+ console.error('解析约束条件失败:', error)
+ constraints = []
+ }
+
+ // 处理变量数据格式
+ let variables = []
+ try {
+ if (typeof originalTemplate.variables === 'string') {
+ variables = JSON.parse(originalTemplate.variables)
+ } else if (Array.isArray(originalTemplate.variables)) {
+ variables = originalTemplate.variables
+ }
+ } catch (error) {
+ console.error('解析变量失败:', error)
+ variables = []
+ }
+
+ // 创建复制的模板
+ const copiedTemplate = {
+ id: generateId(),
+ title: `${originalTemplate.title} (副本)`,
+ description: originalTemplate.description,
+ category: originalTemplate.category,
+ role: originalTemplate.role,
+ task: originalTemplate.task,
+ context: originalTemplate.context,
+ constraints: JSON.stringify(constraints), // 转换为 JSON 字符串存储
+ variables: JSON.stringify(variables), // 转换为 JSON 字符串存储
+ outputFormat: originalTemplate.outputFormat,
+ authorId: userId,
+ isPublic: false, // 复制的模板默认为私有
+ usageCount: 0,
+ rating: 0,
+ ratingCount: 0,
+ createdAt: new Date().toISOString().slice(0, 19).replace('T', ' '),
+ updatedAt: new Date().toISOString().slice(0, 19).replace('T', ' ')
+ }
+
+ // 保存复制的模板
+ const result = await db.createTemplate(copiedTemplate)
+
+ return NextResponse.json({
+ success: true,
+ data: {
+ ...copiedTemplate,
+ constraints: constraints, // 返回解析后的对象数组
+ variables: variables // 返回解析后的对象数组
+ },
+ message: '模板复制成功'
+ })
+ } catch (error) {
+ console.error('复制模板失败:', error)
+ return NextResponse.json(
+ { success: false, error: '复制模板失败' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/api/templates/[id]/route.ts b/src/app/api/templates/[id]/route.ts
new file mode 100644
index 0000000..90c7507
--- /dev/null
+++ b/src/app/api/templates/[id]/route.ts
@@ -0,0 +1,154 @@
+import { NextRequest, NextResponse } from 'next/server'
+import { db } from '@/lib/database'
+import { generateId } from '@/lib/utils'
+
+// 获取单个模板
+export async function GET(
+ request: NextRequest,
+ { params }: { params: { id: string } }
+) {
+ try {
+ const template = await db.getTemplateById(params.id)
+
+ if (!template) {
+ return NextResponse.json(
+ { success: false, error: '模板不存在' },
+ { status: 404 }
+ )
+ }
+
+ // 处理约束条件数据格式
+ let constraints = []
+ try {
+ if (typeof template.constraints === 'string') {
+ const parsedConstraints = JSON.parse(template.constraints)
+ if (Array.isArray(parsedConstraints)) {
+ constraints = parsedConstraints.map((constraint, index) => {
+ if (typeof constraint === 'string') {
+ return {
+ id: `constraint_${index}`,
+ text: constraint,
+ category: 'quality'
+ }
+ }
+ return constraint
+ })
+ }
+ } else if (Array.isArray(template.constraints)) {
+ constraints = template.constraints
+ }
+ } catch (error) {
+ console.error('解析约束条件失败:', error)
+ constraints = []
+ }
+
+ // 处理变量数据格式
+ let variables = []
+ try {
+ if (typeof template.variables === 'string') {
+ variables = JSON.parse(template.variables)
+ } else if (Array.isArray(template.variables)) {
+ variables = template.variables
+ }
+ } catch (error) {
+ console.error('解析变量失败:', error)
+ variables = []
+ }
+
+ return NextResponse.json({
+ success: true,
+ data: {
+ ...template,
+ constraints: constraints,
+ variables: variables
+ }
+ })
+ } catch (error) {
+ console.error('获取模板失败:', error)
+ return NextResponse.json(
+ { success: false, error: '获取模板失败' },
+ { status: 500 }
+ )
+ }
+}
+
+// 更新模板
+export async function PUT(
+ request: NextRequest,
+ { params }: { params: { id: string } }
+) {
+ try {
+ const body = await request.json()
+ const { title, description, category, role, task, context, constraints, variables, outputFormat, isPublic } = body
+
+ // 验证必填字段
+ if (!title || !category) {
+ return NextResponse.json(
+ { success: false, error: '标题和分类为必填项' },
+ { status: 400 }
+ )
+ }
+
+ const updateData = {
+ title,
+ description: description || '',
+ category,
+ role: role || '',
+ task: task || '',
+ context: context || '',
+ constraints: constraints || '',
+ variables: JSON.stringify(variables || []),
+ outputFormat: outputFormat || '',
+ is_public: isPublic || false,
+ updated_at: new Date().toISOString()
+ }
+
+ const result = await db.updateTemplate(params.id, updateData)
+
+ if (!result) {
+ return NextResponse.json(
+ { success: false, error: '模板不存在或更新失败' },
+ { status: 404 }
+ )
+ }
+
+ return NextResponse.json({
+ success: true,
+ message: '模板更新成功'
+ })
+ } catch (error) {
+ console.error('更新模板失败:', error)
+ return NextResponse.json(
+ { success: false, error: '更新模板失败' },
+ { status: 500 }
+ )
+ }
+}
+
+// 删除模板
+export async function DELETE(
+ request: NextRequest,
+ { params }: { params: { id: string } }
+) {
+ try {
+ const result = await db.deleteTemplate(params.id)
+
+ if (!result) {
+ return NextResponse.json(
+ { success: false, error: '模板不存在或删除失败' },
+ { status: 404 }
+ )
+ }
+
+ return NextResponse.json({
+ success: true,
+ message: '模板删除成功'
+ })
+ } catch (error) {
+ console.error('删除模板失败:', error)
+ return NextResponse.json(
+ { success: false, error: '删除模板失败' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/api/templates/[id]/share/route.ts b/src/app/api/templates/[id]/share/route.ts
new file mode 100644
index 0000000..da54e3a
--- /dev/null
+++ b/src/app/api/templates/[id]/share/route.ts
@@ -0,0 +1,38 @@
+import { NextRequest, NextResponse } from 'next/server'
+import { db } from '@/lib/database'
+
+// 切换模板的公开/私有状态
+export async function PATCH(
+ request: NextRequest,
+ { params }: { params: { id: string } }
+) {
+ try {
+ const { id } = params
+ const body = await request.json()
+ const { isPublic } = body
+
+ // 验证模板是否存在
+ const template = await db.getTemplateById(id)
+ if (!template) {
+ return NextResponse.json(
+ { success: false, error: '模板不存在' },
+ { status: 404 }
+ )
+ }
+
+ // 更新模板的公开状态
+ const result = await db.updateTemplate(id, { isPublic })
+
+ return NextResponse.json({
+ success: true,
+ data: { isPublic },
+ message: isPublic ? '模板已设为公开' : '模板已设为私有'
+ })
+ } catch (error) {
+ console.error('更新模板分享状态失败:', error)
+ return NextResponse.json(
+ { success: false, error: '更新分享状态失败' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/api/templates/route.ts b/src/app/api/templates/route.ts
new file mode 100644
index 0000000..9deea4a
--- /dev/null
+++ b/src/app/api/templates/route.ts
@@ -0,0 +1,149 @@
+import { NextRequest, NextResponse } from 'next/server'
+import { query } from '@/lib/database'
+
+// 获取模板列表
+export async function GET(request: NextRequest) {
+ try {
+ const { searchParams } = new URL(request.url)
+ const category = searchParams.get('category')
+ const search = searchParams.get('search')
+ const authorId = searchParams.get('authorId')
+ const userId = searchParams.get('userId')
+
+ let sqlQuery = 'SELECT * FROM promptforge_templates WHERE 1=1'
+ const queryParams: any[] = []
+
+ // 添加筛选条件
+ if (category && category !== 'all') {
+ sqlQuery += ' AND category = ?'
+ queryParams.push(category)
+ }
+
+ if (search) {
+ sqlQuery += ' AND (title LIKE ? OR description LIKE ?)'
+ queryParams.push(`%${search}%`, `%${search}%`)
+ }
+
+ if (authorId) {
+ sqlQuery += ' AND authorId = ?'
+ queryParams.push(authorId)
+ }
+
+ if (userId) {
+ sqlQuery += ' AND authorId = ?'
+ queryParams.push(userId)
+ }
+
+ // 添加排序
+ sqlQuery += ' ORDER BY createdAt DESC'
+
+ const templates = await query(sqlQuery, queryParams)
+
+ // 处理每个模板的数据格式
+ const processedTemplates = (templates as any[]).map(template => {
+ // 处理约束条件
+ let constraints = []
+ try {
+ if (typeof template.constraints === 'string') {
+ const parsedConstraints = JSON.parse(template.constraints)
+ if (Array.isArray(parsedConstraints)) {
+ constraints = parsedConstraints.map((constraint: any, index: number) => {
+ if (typeof constraint === 'string') {
+ return {
+ id: `constraint_${index}`,
+ text: constraint,
+ category: 'quality'
+ }
+ }
+ return constraint
+ })
+ }
+ } else if (Array.isArray(template.constraints)) {
+ constraints = template.constraints
+ }
+ } catch (error) {
+ console.error('解析约束条件失败:', error)
+ constraints = []
+ }
+
+ // 处理变量
+ let variables = []
+ try {
+ if (typeof template.variables === 'string') {
+ variables = JSON.parse(template.variables)
+ } else if (Array.isArray(template.variables)) {
+ variables = template.variables
+ }
+ } catch (error) {
+ console.error('解析变量失败:', error)
+ variables = []
+ }
+
+ return {
+ ...template,
+ constraints: constraints,
+ variables: variables
+ }
+ })
+
+ return NextResponse.json({
+ success: true,
+ data: processedTemplates
+ })
+ } catch (error) {
+ console.error('获取模板列表失败:', error)
+ return NextResponse.json(
+ { success: false, error: '获取模板列表失败' },
+ { status: 500 }
+ )
+ }
+}
+
+// 创建新模板
+export async function POST(request: NextRequest) {
+ try {
+ const body = await request.json()
+ const { title, description, category, role, task, context, constraints, variables, outputFormat, userId } = body
+
+ // 验证必填字段
+ if (!title || !category || !userId) {
+ return NextResponse.json(
+ { success: false, error: '标题、分类和用户ID为必填项' },
+ { status: 400 }
+ )
+ }
+
+ const templateData = {
+ id: `template_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
+ title,
+ description: description || '',
+ category,
+ role: role || '',
+ task: task || '',
+ context: context || '',
+ constraints: constraints || '',
+ variables: JSON.stringify(variables || []),
+ outputFormat: outputFormat || '',
+ user_id: userId,
+ is_public: false,
+ likes: 0,
+ downloads: 0,
+ created_at: new Date().toISOString(),
+ updated_at: new Date().toISOString()
+ }
+
+ const result = await db.createTemplate(templateData)
+
+ return NextResponse.json({
+ success: true,
+ data: templateData,
+ message: '模板创建成功'
+ })
+ } catch (error) {
+ console.error('创建模板失败:', error)
+ return NextResponse.json(
+ { success: false, error: '创建模板失败' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/api/test/batch/route.ts b/src/app/api/test/batch/route.ts
new file mode 100644
index 0000000..a7db2ca
--- /dev/null
+++ b/src/app/api/test/batch/route.ts
@@ -0,0 +1,262 @@
+import { NextRequest, NextResponse } from 'next/server';
+
+// DeepSeek API 配置
+const DEEPSEEK_API_URL = 'https://api.deepseek.com/v1/chat/completions';
+const DEEPSEEK_API_KEY = process.env.DEEPSEEK_API_KEY || 'sk-fdf7cc1c73504e628ec0119b7e11b8cc';
+
+// OpenAI API 配置
+const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';
+const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
+
+// Anthropic API 配置
+const ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
+
+interface BatchTestRequest {
+ prompt: string;
+ models: string[];
+ temperature?: number;
+ maxTokens?: number;
+ variables?: Record
;
+}
+
+interface BatchTestResult {
+ model: string;
+ provider: string;
+ result: string;
+ success: boolean;
+ error?: string;
+ responseTime: number;
+}
+
+export async function POST(request: NextRequest) {
+ try {
+ const body: BatchTestRequest = await request.json();
+ const { prompt, models, temperature = 0.7, maxTokens = 1000 } = body;
+
+ if (!prompt) {
+ return NextResponse.json(
+ { success: false, error: '提示词不能为空' },
+ { status: 400 }
+ );
+ }
+
+ if (!models || models.length === 0) {
+ return NextResponse.json(
+ { success: false, error: '至少选择一个模型' },
+ { status: 400 }
+ );
+ }
+
+ // 并行测试所有模型
+ const testPromises = models.map(async (model) => {
+ const startTime = Date.now();
+
+ try {
+ let result: string;
+ let provider: string;
+
+ // 根据模型选择对应的 API
+ if (model.startsWith('deepseek')) {
+ result = await callDeepSeekAPI(prompt, model, temperature, maxTokens);
+ provider = 'DeepSeek';
+ } else if (model.startsWith('gpt')) {
+ result = await callOpenAIAPI(prompt, model, temperature, maxTokens);
+ provider = 'OpenAI';
+ } else if (model.startsWith('claude')) {
+ result = await callAnthropicAPI(prompt, model, temperature, maxTokens);
+ provider = 'Anthropic';
+ } else {
+ // 模拟其他模型
+ result = await simulateAPI(prompt, model, temperature, maxTokens);
+ provider = 'Simulated';
+ }
+
+ const responseTime = Date.now() - startTime;
+
+ return {
+ model,
+ provider,
+ result,
+ success: true,
+ responseTime
+ } as BatchTestResult;
+
+ } catch (error) {
+ const responseTime = Date.now() - startTime;
+
+ return {
+ model,
+ provider: 'Error',
+ result: '',
+ success: false,
+ error: error instanceof Error ? error.message : '未知错误',
+ responseTime
+ } as BatchTestResult;
+ }
+ });
+
+ const results = await Promise.all(testPromises);
+
+ return NextResponse.json({
+ success: true,
+ data: {
+ results,
+ prompt,
+ timestamp: new Date().toISOString(),
+ totalModels: models.length,
+ successfulTests: results.filter(r => r.success).length
+ }
+ });
+
+ } catch (error) {
+ console.error('批量测试 API 错误:', error);
+ return NextResponse.json(
+ { success: false, error: '批量测试失败,请检查配置和网络连接' },
+ { status: 500 }
+ );
+ }
+}
+
+async function callDeepSeekAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ if (!DEEPSEEK_API_KEY) {
+ throw new Error('DeepSeek API 密钥未配置');
+ }
+
+ const modelMapping: Record = {
+ 'deepseek-coder': 'deepseek-coder',
+ 'deepseek-chat': 'deepseek-chat',
+ 'deepseek-vision': 'deepseek-vision'
+ };
+
+ const actualModel = modelMapping[model] || 'deepseek-chat';
+
+ const response = await fetch(DEEPSEEK_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${DEEPSEEK_API_KEY}`,
+ },
+ body: JSON.stringify({
+ model: actualModel,
+ messages: [
+ {
+ role: 'user',
+ content: prompt
+ }
+ ],
+ temperature: temperature,
+ max_tokens: maxTokens,
+ stream: false
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ throw new Error(`DeepSeek API 错误: ${response.status} ${response.statusText}`);
+ }
+
+ const data = await response.json();
+ return data.choices[0]?.message?.content || '无响应内容';
+}
+
+async function callOpenAIAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ if (!OPENAI_API_KEY) {
+ throw new Error('OpenAI API 密钥未配置');
+ }
+
+ const response = await fetch(OPENAI_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${OPENAI_API_KEY}`,
+ },
+ body: JSON.stringify({
+ model: model,
+ messages: [
+ {
+ role: 'user',
+ content: prompt
+ }
+ ],
+ temperature: temperature,
+ max_tokens: maxTokens,
+ stream: false
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ throw new Error(`OpenAI API 错误: ${error}`);
+ }
+
+ const data = await response.json();
+ return data.choices[0]?.message?.content || '无响应内容';
+}
+
+async function callAnthropicAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ if (!ANTHROPIC_API_KEY) {
+ throw new Error('Anthropic API 密钥未配置');
+ }
+
+ const response = await fetch(ANTHROPIC_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'x-api-key': ANTHROPIC_API_KEY,
+ 'anthropic-version': '2023-06-01'
+ },
+ body: JSON.stringify({
+ model: model,
+ messages: [
+ {
+ role: 'user',
+ content: prompt
+ }
+ ],
+ temperature: temperature,
+ max_tokens: maxTokens
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ throw new Error(`Anthropic API 错误: ${error}`);
+ }
+
+ const data = await response.json();
+ return data.content[0]?.text || '无响应内容';
+}
+
+async function simulateAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ // 模拟 API 调用延迟
+ await new Promise(resolve => setTimeout(resolve, 500 + Math.random() * 1000));
+
+ let response = '';
+
+ if (model.includes('coder') || model.includes('code')) {
+ response = `// 模拟 ${model} 的代码生成响应
+function exampleFunction() {
+ console.log("Hello from ${model}!");
+ return "Generated by ${model}";
+}`;
+ } else if (model.includes('vision')) {
+ response = `[模拟 ${model} 视觉模型响应]
+
+根据您提供的图像和提示词,我识别到以下内容:
+1. 图像类型:示例图像
+2. 主要内容:示例内容
+3. 分析结果:这是一个模拟的视觉分析结果`;
+ } else {
+ response = `这是 ${model} 的模拟响应。
+
+根据您的提示词:"${prompt.substring(0, 100)}${prompt.length > 100 ? '...' : ''}"
+
+我生成了以下内容:
+1. 分析结果:这是一个模拟的分析结果
+2. 建议:基于提示词的模拟建议
+3. 总结:模拟的总结内容`;
+ }
+
+ return response;
+}
diff --git a/src/app/api/test/route.ts b/src/app/api/test/route.ts
new file mode 100644
index 0000000..fe8f059
--- /dev/null
+++ b/src/app/api/test/route.ts
@@ -0,0 +1,228 @@
+import { NextRequest, NextResponse } from 'next/server';
+
+// DeepSeek API 配置
+const DEEPSEEK_API_URL = 'https://api.deepseek.com/v1/chat/completions';
+const DEEPSEEK_API_KEY = process.env.DEEPSEEK_API_KEY || 'sk-fdf7cc1c73504e628ec0119b7e11b8cc';
+
+// OpenAI API 配置
+const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';
+const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
+
+// Anthropic API 配置
+const ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
+
+interface TestRequest {
+ prompt: string;
+ model: string;
+ temperature?: number;
+ maxTokens?: number;
+ variables?: Record;
+}
+
+export async function POST(request: NextRequest) {
+ try {
+ const body: TestRequest = await request.json();
+ const { prompt, model, temperature = 0.7, maxTokens = 1000 } = body;
+
+ if (!prompt) {
+ return NextResponse.json(
+ { success: false, error: '提示词不能为空' },
+ { status: 400 }
+ );
+ }
+
+ let result: string;
+ let provider: string;
+
+ // 根据模型选择对应的 API
+ if (model.startsWith('deepseek')) {
+ result = await callDeepSeekAPI(prompt, model, temperature, maxTokens);
+ provider = 'DeepSeek';
+ } else if (model.startsWith('gpt')) {
+ result = await callOpenAIAPI(prompt, model, temperature, maxTokens);
+ provider = 'OpenAI';
+ } else if (model.startsWith('claude')) {
+ result = await callAnthropicAPI(prompt, model, temperature, maxTokens);
+ provider = 'Anthropic';
+ } else {
+ // 模拟其他模型
+ result = await simulateAPI(prompt, model, temperature, maxTokens);
+ provider = 'Simulated';
+ }
+
+ return NextResponse.json({
+ success: true,
+ data: {
+ result,
+ provider,
+ model,
+ prompt,
+ timestamp: new Date().toISOString()
+ }
+ });
+
+ } catch (error) {
+ console.error('测试 API 错误:', error);
+ return NextResponse.json(
+ { success: false, error: '测试失败,请检查配置和网络连接' },
+ { status: 500 }
+ );
+ }
+}
+
+async function callDeepSeekAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ if (!DEEPSEEK_API_KEY) {
+ throw new Error('DeepSeek API 密钥未配置');
+ }
+
+ // 将 DeepSeek 模型名称映射到实际的 API 模型名称
+ const modelMapping: Record = {
+ 'deepseek-coder': 'deepseek-coder',
+ 'deepseek-chat': 'deepseek-chat',
+ 'deepseek-vision': 'deepseek-vision'
+ };
+
+ const actualModel = modelMapping[model] || 'deepseek-chat';
+
+ const response = await fetch(DEEPSEEK_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${DEEPSEEK_API_KEY}`,
+ },
+ body: JSON.stringify({
+ model: actualModel,
+ messages: [
+ {
+ role: 'user',
+ content: prompt
+ }
+ ],
+ temperature: temperature,
+ max_tokens: maxTokens,
+ stream: false
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ console.error('DeepSeek API 错误详情:', error);
+ throw new Error(`DeepSeek API 错误: ${response.status} ${response.statusText}`);
+ }
+
+ const data = await response.json();
+ return data.choices[0]?.message?.content || '无响应内容';
+}
+
+async function callOpenAIAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ if (!OPENAI_API_KEY) {
+ throw new Error('OpenAI API 密钥未配置');
+ }
+
+ const response = await fetch(OPENAI_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${OPENAI_API_KEY}`,
+ },
+ body: JSON.stringify({
+ model: model,
+ messages: [
+ {
+ role: 'user',
+ content: prompt
+ }
+ ],
+ temperature: temperature,
+ max_tokens: maxTokens,
+ stream: false
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ throw new Error(`OpenAI API 错误: ${error}`);
+ }
+
+ const data = await response.json();
+ return data.choices[0]?.message?.content || '无响应内容';
+}
+
+async function callAnthropicAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ if (!ANTHROPIC_API_KEY) {
+ throw new Error('Anthropic API 密钥未配置');
+ }
+
+ const response = await fetch(ANTHROPIC_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'x-api-key': ANTHROPIC_API_KEY,
+ 'anthropic-version': '2023-06-01'
+ },
+ body: JSON.stringify({
+ model: model,
+ messages: [
+ {
+ role: 'user',
+ content: prompt
+ }
+ ],
+ temperature: temperature,
+ max_tokens: maxTokens
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ throw new Error(`Anthropic API 错误: ${error}`);
+ }
+
+ const data = await response.json();
+ return data.content[0]?.text || '无响应内容';
+}
+
+async function simulateAPI(prompt: string, model: string, temperature: number, maxTokens: number): Promise {
+ // 模拟 API 调用延迟
+ await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));
+
+ // 根据模型类型生成不同的模拟响应
+ let response = '';
+
+ if (model.includes('coder') || model.includes('code')) {
+ response = `// 模拟 ${model} 的代码生成响应
+function exampleFunction() {
+ // 这是一个示例函数
+ console.log("Hello from ${model}!");
+ return "Generated by ${model}";
+}
+
+// 根据您的提示词生成的代码示例
+// 实际使用时,这里会是真实的代码生成结果`;
+ } else if (model.includes('vision')) {
+ response = `[模拟 ${model} 视觉模型响应]
+
+根据您提供的图像和提示词,我识别到以下内容:
+
+1. 图像类型:示例图像
+2. 主要内容:示例内容
+3. 分析结果:这是一个模拟的视觉分析结果
+
+注意:这是模拟响应,实际使用时需要真实的图像输入。`;
+ } else {
+ response = `这是 ${model} 的模拟响应。
+
+根据您的提示词:"${prompt.substring(0, 100)}${prompt.length > 100 ? '...' : ''}"
+
+我生成了以下内容:
+
+1. 分析结果:这是一个模拟的分析结果
+2. 建议:基于提示词的模拟建议
+3. 总结:模拟的总结内容
+
+注意:这是模拟响应,实际使用时需要配置真实的 API 密钥。`;
+ }
+
+ return response;
+}
diff --git a/src/app/api/user/profile/route.ts b/src/app/api/user/profile/route.ts
new file mode 100644
index 0000000..d945473
--- /dev/null
+++ b/src/app/api/user/profile/route.ts
@@ -0,0 +1,83 @@
+import { NextRequest, NextResponse } from 'next/server'
+import { db } from '@/lib/database'
+
+export async function GET(request: NextRequest) {
+ try {
+ const { searchParams } = new URL(request.url)
+ const userId = searchParams.get('userId')
+
+ if (!userId) {
+ return NextResponse.json(
+ { error: '用户ID不能为空' },
+ { status: 400 }
+ )
+ }
+
+ const user = await db.getUserById(userId)
+ if (!user) {
+ return NextResponse.json(
+ { error: '用户不存在' },
+ { status: 404 }
+ )
+ }
+
+ // 返回用户信息(不包含密码)
+ const { password, ...userWithoutPassword } = user
+
+ return NextResponse.json({
+ user: userWithoutPassword
+ })
+
+ } catch (error) {
+ console.error('获取用户资料失败:', error)
+ return NextResponse.json(
+ { error: '获取用户资料失败' },
+ { status: 500 }
+ )
+ }
+}
+
+export async function PUT(request: NextRequest) {
+ try {
+ const { userId, name, avatar } = await request.json()
+
+ if (!userId) {
+ return NextResponse.json(
+ { error: '用户ID不能为空' },
+ { status: 400 }
+ )
+ }
+
+ // 验证用户是否存在
+ const existingUser = await db.getUserById(userId)
+ if (!existingUser) {
+ return NextResponse.json(
+ { error: '用户不存在' },
+ { status: 404 }
+ )
+ }
+
+ // 更新用户信息
+ const updateData: any = {}
+ if (name) updateData.name = name
+ if (avatar) updateData.avatar = avatar
+
+ await db.updateUser(userId, updateData)
+
+ // 获取更新后的用户信息
+ const updatedUser = await db.getUserById(userId)
+ const { password, ...userWithoutPassword } = updatedUser
+
+ return NextResponse.json({
+ message: '资料更新成功',
+ user: userWithoutPassword
+ })
+
+ } catch (error) {
+ console.error('更新用户资料失败:', error)
+ return NextResponse.json(
+ { error: '更新用户资料失败' },
+ { status: 500 }
+ )
+ }
+}
diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx
new file mode 100644
index 0000000..aaf272e
--- /dev/null
+++ b/src/app/auth/login/page.tsx
@@ -0,0 +1,152 @@
+'use client'
+
+import { useState } from 'react'
+import { useRouter } from 'next/navigation'
+import Link from 'next/link'
+import { useAuth } from '@/contexts/AuthContext'
+import { Eye, EyeOff, Mail, Lock, ArrowRight } from 'lucide-react'
+
+export default function LoginPage() {
+ const [email, setEmail] = useState('')
+ const [password, setPassword] = useState('')
+ const [showPassword, setShowPassword] = useState(false)
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState('')
+
+ const { login } = useAuth()
+ const router = useRouter()
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+ setLoading(true)
+ setError('')
+
+ const result = await login(email, password)
+
+ if (result.success) {
+ router.push('/')
+ } else {
+ setError(result.error || '登录失败')
+ }
+
+ setLoading(false)
+ }
+
+ return (
+
+
+
+
+ P
+
+
+ 登录到 PromptForge
+
+
+ 或者{' '}
+
+ 注册新账户
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/auth/register/page.tsx b/src/app/auth/register/page.tsx
new file mode 100644
index 0000000..245d263
--- /dev/null
+++ b/src/app/auth/register/page.tsx
@@ -0,0 +1,232 @@
+'use client'
+
+import { useState } from 'react'
+import { useRouter } from 'next/navigation'
+import Link from 'next/link'
+import { useAuth } from '@/contexts/AuthContext'
+import { Eye, EyeOff, Mail, Lock, User, ArrowRight } from 'lucide-react'
+
+export default function RegisterPage() {
+ const [formData, setFormData] = useState({
+ name: '',
+ email: '',
+ password: '',
+ confirmPassword: ''
+ })
+ const [showPassword, setShowPassword] = useState(false)
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false)
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState('')
+
+ const { register } = useAuth()
+ const router = useRouter()
+
+ const handleChange = (e: React.ChangeEvent) => {
+ setFormData({
+ ...formData,
+ [e.target.name]: e.target.value
+ })
+ }
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+ setLoading(true)
+ setError('')
+
+ // 验证密码
+ if (formData.password !== formData.confirmPassword) {
+ setError('两次输入的密码不一致')
+ setLoading(false)
+ return
+ }
+
+ if (formData.password.length < 6) {
+ setError('密码至少需要6个字符')
+ setLoading(false)
+ return
+ }
+
+ const result = await register(formData.email, formData.password, formData.name)
+
+ if (result.success) {
+ router.push('/')
+ } else {
+ setError(result.error || '注册失败')
+ }
+
+ setLoading(false)
+ }
+
+ return (
+
+
+
+
+ P
+
+
+ 注册 PromptForge 账户
+
+
+ 或者{' '}
+
+ 登录现有账户
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/deploy/page.tsx b/src/app/deploy/page.tsx
new file mode 100644
index 0000000..14448b7
--- /dev/null
+++ b/src/app/deploy/page.tsx
@@ -0,0 +1,900 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import {
+ Cloud,
+ Server,
+ Globe,
+ Code,
+ Download,
+ Copy,
+ Check,
+ Settings,
+ Play,
+ Zap,
+ Database,
+ Shield,
+ Monitor,
+ Package
+} from 'lucide-react';
+import { useAuth } from '@/contexts/AuthContext';
+import { PromptTemplate } from '@/types/prompt';
+
+interface DeploymentConfig {
+ platform: string;
+ language: string;
+ framework: string;
+ database: string;
+ hosting: string;
+ monitoring: boolean;
+ security: boolean;
+ scaling: boolean;
+}
+
+interface DeploymentTemplate {
+ id: string;
+ name: string;
+ description: string;
+ icon: any;
+ config: DeploymentConfig;
+ code: string;
+ instructions: string[];
+}
+
+export default function DeployPage() {
+ const { user } = useAuth();
+ const [selectedTemplate, setSelectedTemplate] = useState('');
+ const [deploymentConfig, setDeploymentConfig] = useState({
+ platform: 'openai',
+ language: 'python',
+ framework: 'fastapi',
+ database: 'postgresql',
+ hosting: 'vercel',
+ monitoring: true,
+ security: true,
+ scaling: false
+ });
+ const [templates, setTemplates] = useState([]);
+ const [selectedTemplateId, setSelectedTemplateId] = useState('');
+ const [copied, setCopied] = useState(null);
+ const [generatedCode, setGeneratedCode] = useState('');
+
+ // 部署模板配置
+ const deploymentTemplates: DeploymentTemplate[] = [
+ {
+ id: 'web-app',
+ name: 'Web 应用',
+ description: '构建现代化的 Web 应用',
+ icon: Globe,
+ config: {
+ platform: 'openai',
+ language: 'python',
+ framework: 'fastapi',
+ database: 'postgresql',
+ hosting: 'vercel',
+ monitoring: true,
+ security: true,
+ scaling: false
+ },
+ code: '',
+ instructions: [
+ '安装依赖包',
+ '配置环境变量',
+ '设置数据库连接',
+ '部署到 Vercel',
+ '配置域名和 SSL'
+ ]
+ },
+ {
+ id: 'api-service',
+ name: 'API 服务',
+ description: '构建高性能的 API 服务',
+ icon: Server,
+ config: {
+ platform: 'openai',
+ language: 'python',
+ framework: 'fastapi',
+ database: 'postgresql',
+ hosting: 'railway',
+ monitoring: true,
+ security: true,
+ scaling: true
+ },
+ code: '',
+ instructions: [
+ '安装 FastAPI 和依赖',
+ '配置数据库连接',
+ '设置 API 密钥',
+ '部署到 Railway',
+ '配置监控和日志'
+ ]
+ },
+ {
+ id: 'mobile-backend',
+ name: '移动端后端',
+ description: '为移动应用提供后端服务',
+ icon: Package,
+ config: {
+ platform: 'openai',
+ language: 'javascript',
+ framework: 'express',
+ database: 'mongodb',
+ hosting: 'heroku',
+ monitoring: true,
+ security: true,
+ scaling: true
+ },
+ code: '',
+ instructions: [
+ '安装 Node.js 依赖',
+ '配置 MongoDB 连接',
+ '设置 JWT 认证',
+ '部署到 Heroku',
+ '配置推送通知'
+ ]
+ },
+ {
+ id: 'desktop-app',
+ name: '桌面应用',
+ description: '构建跨平台桌面应用',
+ icon: Monitor,
+ config: {
+ platform: 'openai',
+ language: 'javascript',
+ framework: 'electron',
+ database: 'sqlite',
+ hosting: 'local',
+ monitoring: false,
+ security: true,
+ scaling: false
+ },
+ code: '',
+ instructions: [
+ '安装 Electron 依赖',
+ '配置本地数据库',
+ '设置应用打包',
+ '生成安装包',
+ '配置自动更新'
+ ]
+ }
+ ];
+
+ useEffect(() => {
+ // 加载用户的模板
+ fetchUserTemplates();
+ }, []);
+
+ const fetchUserTemplates = async () => {
+ try {
+ const response = await fetch('/api/templates?authorId=' + user?.id);
+ const data = await response.json();
+ if (data.success) {
+ setTemplates(data.data);
+ }
+ } catch (error) {
+ console.error('加载模板失败:', error);
+ }
+ };
+
+ const handleConfigChange = (key: keyof DeploymentConfig, value: any) => {
+ setDeploymentConfig(prev => ({
+ ...prev,
+ [key]: value
+ }));
+ };
+
+ const generateDeploymentCode = () => {
+ if (!selectedTemplateId) return;
+
+ const template = templates.find(t => t.id === selectedTemplateId);
+ if (!template) return;
+
+ const selectedDeployTemplate = deploymentTemplates.find(dt => dt.id === selectedTemplate);
+ if (!selectedDeployTemplate) return;
+
+ let code = '';
+
+ switch (deploymentConfig.language) {
+ case 'python':
+ code = generatePythonCode(template, deploymentConfig);
+ break;
+ case 'javascript':
+ code = generateJavaScriptCode(template, deploymentConfig);
+ break;
+ case 'typescript':
+ code = generateTypeScriptCode(template, deploymentConfig);
+ break;
+ default:
+ code = generatePythonCode(template, deploymentConfig);
+ }
+
+ setGeneratedCode(code);
+ };
+
+ const generatePythonCode = (template: PromptTemplate, config: DeploymentConfig): string => {
+ const variables = (template.variables || []).map(v => v.name).join(', ');
+ const promptText = (template.role || '') + '\n\n' + (template.task || '');
+
+ let code = `# ${template.title} - 部署代码
+# 平台: ${config.platform}
+# 框架: ${config.framework}
+# 数据库: ${config.database}
+
+import os
+import json
+import requests
+from typing import Dict, Any
+`;
+
+ if (config.framework === 'fastapi') {
+ code += `
+from fastapi import FastAPI, HTTPException
+from fastapi.middleware.cors import CORSMiddleware
+from pydantic import BaseModel
+import uvicorn
+
+app = FastAPI(title="${template.title}", version="1.0.0")
+
+# 配置 CORS
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
+class PromptRequest(BaseModel):
+ ${(template.variables || []).map(v => `${v.name}: str`).join(',\n ')}
+
+class PromptResponse(BaseModel):
+ result: str
+ model: str
+ timestamp: str
+
+# API 配置
+${config.platform.toUpperCase()}_API_KEY = os.getenv("${config.platform.toUpperCase()}_API_KEY")
+${config.platform.toUpperCase()}_API_URL = os.getenv("${config.platform.toUpperCase()}_API_URL", "https://api.${config.platform}.com/v1/chat/completions")
+
+def generate_with_prompt(${variables}):
+ """使用 ${template.title} 生成内容"""
+ prompt = f"""${promptText}"""
+
+ headers = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {${config.platform.toUpperCase()}_API_KEY}"
+ }
+
+ data = {
+ "model": "${config.platform}-chat",
+ "messages": [{"role": "user", "content": prompt}],
+ "temperature": 0.7,
+ "max_tokens": 1000
+ }
+
+ try:
+ response = requests.post(${config.platform.toUpperCase()}_API_URL, headers=headers, json=data)
+ response.raise_for_status()
+ result = response.json()
+ return result["choices"][0]["message"]["content"]
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=f"API 调用失败: {str(e)}")
+
+@app.post("/generate", response_model=PromptResponse)
+async def generate_content(request: PromptRequest):
+ """生成内容接口"""
+ try:
+ result = generate_with_prompt(${(template.variables || []).map(v => `request.${v.name}`).join(', ')})
+ return PromptResponse(
+ result=result,
+ model="${config.platform}-chat",
+ timestamp=datetime.now().isoformat()
+ )
+ except Exception as e:
+ raise HTTPException(status_code=500, detail=str(e))
+
+@app.get("/health")
+async def health_check():
+ """健康检查接口"""
+ return {"status": "healthy", "service": "${template.title}"}
+
+if __name__ == "__main__":
+ uvicorn.run(app, host="0.0.0.0", port=8000)
+`;
+ }
+
+ // 添加依赖文件
+ code += `
+
+# requirements.txt
+fastapi==0.104.1
+uvicorn==0.24.0
+requests==2.31.0
+pydantic==2.5.0
+python-dotenv==1.0.0
+
+# .env 文件
+${config.platform.toUpperCase()}_API_KEY=your_api_key_here
+${config.platform.toUpperCase()}_API_URL=https://api.${config.platform}.com/v1/chat/completions
+
+# 部署说明
+# 1. 安装依赖: pip install -r requirements.txt
+# 2. 配置环境变量
+# 3. 运行服务: python main.py
+# 4. 访问接口: http://localhost:8000/docs
+`;
+
+ return code;
+ };
+
+ const generateJavaScriptCode = (template: PromptTemplate, config: DeploymentConfig): string => {
+ const variables = (template.variables || []).map(v => v.name).join(', ');
+ const promptText = (template.role || '') + '\n\n' + (template.task || '');
+
+ let code = `// ${template.title} - 部署代码
+// 平台: ${config.platform}
+// 框架: ${config.framework}
+// 数据库: ${config.database}
+
+const express = require('express');
+const cors = require('cors');
+const fetch = require('node-fetch');
+require('dotenv').config();
+
+const app = express();
+const PORT = process.env.PORT || 3000;
+
+// 中间件
+app.use(cors());
+app.use(express.json());
+
+// API 配置
+const ${config.platform.toUpperCase()}_API_KEY = process.env.${config.platform.toUpperCase()}_API_KEY;
+const ${config.platform.toUpperCase()}_API_URL = process.env.${config.platform.toUpperCase()}_API_URL || 'https://api.${config.platform}.com/v1/chat/completions';
+
+async function generateWithPrompt(${variables}) {
+ const prompt = \`${promptText}\`;
+
+ const response = await fetch(${config.platform.toUpperCase()}_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': \`Bearer \${${config.platform.toUpperCase()}_API_KEY}\`
+ },
+ body: JSON.stringify({
+ model: '${config.platform}-chat',
+ messages: [{ role: 'user', content: prompt }],
+ temperature: 0.7,
+ max_tokens: 1000
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(\`API 调用失败: \${response.statusText}\`);
+ }
+
+ const data = await response.json();
+ return data.choices[0].message.content;
+}
+
+// 生成内容接口
+app.post('/generate', async (req, res) => {
+ try {
+ const { ${(template.variables || []).map(v => v.name).join(', ')} } = req.body;
+
+ if (!${(template.variables || []).map(v => v.name).join(' || !')}) {
+ return res.status(400).json({ error: '缺少必要参数' });
+ }
+
+ const result = await generateWithPrompt(${(template.variables || []).map(v => v.name).join(', ')});
+
+ res.json({
+ result,
+ model: '${config.platform}-chat',
+ timestamp: new Date().toISOString()
+ });
+ } catch (error) {
+ res.status(500).json({ error: error.message });
+ }
+});
+
+// 健康检查接口
+app.get('/health', (req, res) => {
+ res.json({ status: 'healthy', service: '${template.title}' });
+});
+
+app.listen(PORT, () => {
+ console.log(\`服务运行在端口 \${PORT}\`);
+});
+
+// package.json
+{
+ "name": "${template.title.toLowerCase().replace(/\s+/g, '-')}",
+ "version": "1.0.0",
+ "main": "index.js",
+ "scripts": {
+ "start": "node index.js",
+ "dev": "nodemon index.js"
+ },
+ "dependencies": {
+ "express": "^4.18.2",
+ "cors": "^2.8.5",
+ "node-fetch": "^2.7.0",
+ "dotenv": "^16.3.1"
+ },
+ "devDependencies": {
+ "nodemon": "^3.0.2"
+ }
+}
+
+// .env 文件
+${config.platform.toUpperCase()}_API_KEY=your_api_key_here
+${config.platform.toUpperCase()}_API_URL=https://api.${config.platform}.com/v1/chat/completions
+
+// 部署说明
+// 1. 安装依赖: npm install
+// 2. 配置环境变量
+// 3. 运行服务: npm start
+// 4. 访问接口: http://localhost:3000
+`;
+
+ return code;
+ };
+
+ const generateTypeScriptCode = (template: PromptTemplate, config: DeploymentConfig): string => {
+ const variables = (template.variables || []).map(v => v.name).join(', ');
+ const promptText = (template.role || '') + '\n\n' + (template.task || '');
+
+ let code = `// ${template.title} - TypeScript 部署代码
+// 平台: ${config.platform}
+// 框架: ${config.framework}
+// 数据库: ${config.database}
+
+import express, { Request, Response } from 'express';
+import cors from 'cors';
+import fetch from 'node-fetch';
+import dotenv from 'dotenv';
+
+dotenv.config();
+
+const app = express();
+const PORT = process.env.PORT || 3000;
+
+// 中间件
+app.use(cors());
+app.use(express.json());
+
+// 类型定义
+interface PromptRequest {
+ ${(template.variables || []).map(v => `${v.name}: string`).join(';\n ')}
+}
+
+interface PromptResponse {
+ result: string;
+ model: string;
+ timestamp: string;
+}
+
+// API 配置
+const ${config.platform.toUpperCase()}_API_KEY = process.env.${config.platform.toUpperCase()}_API_KEY;
+const ${config.platform.toUpperCase()}_API_URL = process.env.${config.platform.toUpperCase()}_API_URL || 'https://api.${config.platform}.com/v1/chat/completions';
+
+async function generateWithPrompt(${variables}: string): Promise {
+ const prompt = \`${promptText}\`;
+
+ const response = await fetch(${config.platform.toUpperCase()}_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': \`Bearer \${${config.platform.toUpperCase()}_API_KEY}\`
+ },
+ body: JSON.stringify({
+ model: '${config.platform}-chat',
+ messages: [{ role: 'user', content: prompt }],
+ temperature: 0.7,
+ max_tokens: 1000
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(\`API 调用失败: \${response.statusText}\`);
+ }
+
+ const data = await response.json();
+ return data.choices[0].message.content;
+}
+
+// 生成内容接口
+app.post('/generate', async (req: Request<{}, {}, PromptRequest>, res: Response) => {
+ try {
+ const { ${(template.variables || []).map(v => v.name).join(', ')} } = req.body;
+
+ if (!${(template.variables || []).map(v => v.name).join(' || !')}) {
+ return res.status(400).json({ error: '缺少必要参数' });
+ }
+
+ const result = await generateWithPrompt(${(template.variables || []).map(v => v.name).join(', ')});
+
+ res.json({
+ result,
+ model: '${config.platform}-chat',
+ timestamp: new Date().toISOString()
+ });
+ } catch (error) {
+ res.status(500).json({ error: error instanceof Error ? error.message : '未知错误' });
+ }
+});
+
+// 健康检查接口
+app.get('/health', (req: Request, res: Response) => {
+ res.json({ status: 'healthy', service: '${template.title}' });
+});
+
+app.listen(PORT, () => {
+ console.log(\`服务运行在端口 \${PORT}\`);
+});
+
+// package.json
+{
+ "name": "${template.title.toLowerCase().replace(/\s+/g, '-')}",
+ "version": "1.0.0",
+ "main": "dist/index.js",
+ "scripts": {
+ "build": "tsc",
+ "start": "node dist/index.js",
+ "dev": "ts-node src/index.ts"
+ },
+ "dependencies": {
+ "express": "^4.18.2",
+ "cors": "^2.8.5",
+ "node-fetch": "^2.7.0",
+ "dotenv": "^16.3.1"
+ },
+ "devDependencies": {
+ "@types/express": "^4.17.21",
+ "@types/cors": "^2.8.17",
+ "@types/node": "^20.10.0",
+ "typescript": "^5.3.0",
+ "ts-node": "^10.9.0"
+ }
+}
+
+// tsconfig.json
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "commonjs",
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules"]
+}
+
+// .env 文件
+${config.platform.toUpperCase()}_API_KEY=your_api_key_here
+${config.platform.toUpperCase()}_API_URL=https://api.${config.platform}.com/v1/chat/completions
+
+// 部署说明
+// 1. 安装依赖: npm install
+// 2. 配置环境变量
+// 3. 编译代码: npm run build
+// 4. 运行服务: npm start
+// 5. 访问接口: http://localhost:3000
+`;
+
+ return code;
+ };
+
+ const handleCopy = async (text: string, type: string) => {
+ await navigator.clipboard.writeText(text);
+ setCopied(type);
+ setTimeout(() => setCopied(null), 2000);
+ };
+
+ const handleDownload = (content: string, filename: string) => {
+ const blob = new Blob([content], { type: 'text/plain' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = filename;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+ 部署中心
+
+
+ 将您的提示词模板部署为可用的服务
+
+
+
+
+ {/* 左侧配置面板 */}
+
+ {/* 模板选择 */}
+
+
+ 选择模板
+
+
+
+
+ {/* 部署模板 */}
+
+
+ 部署模板
+
+
+ {deploymentTemplates.map((template) => {
+ const Icon = template.icon;
+ return (
+
+ );
+ })}
+
+
+
+ {/* 部署配置 */}
+
+
+ 部署配置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* 生成按钮 */}
+
+
+
+
+
+ {/* 中间代码预览 */}
+
+ {/* 代码预览 */}
+
+
+
+ 部署代码
+
+
+
+
+
+
+
+
+ {generatedCode || '// 选择模板和配置后点击"生成部署代码"按钮'}
+
+
+
+
+ {/* 部署说明 */}
+ {selectedTemplate && (
+
+
+ 部署说明
+
+
+ {deploymentTemplates.find(t => t.id === selectedTemplate)?.instructions.map((instruction, index) => (
+
+
+ {index + 1}
+
+
{instruction}
+
+ ))}
+
+
+ )}
+
+ {/* 部署选项 */}
+
+
+ 快速部署
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/docs/first-template/page.tsx b/src/app/docs/first-template/page.tsx
new file mode 100644
index 0000000..19aefd2
--- /dev/null
+++ b/src/app/docs/first-template/page.tsx
@@ -0,0 +1,411 @@
+'use client'
+
+import { useState } from 'react'
+import {
+ Play,
+ CheckCircle,
+ ArrowRight,
+ Code,
+ Eye,
+ Settings,
+ Zap,
+ Copy,
+ ExternalLink
+} from 'lucide-react'
+
+const STEPS = [
+ {
+ id: 1,
+ title: '访问编辑器',
+ description: '点击导航栏中的"编辑器"按钮,进入 PromptForge 的智能编辑器。',
+ icon: Code,
+ content: (
+
+
+ 在 PromptForge 的主页面,您会看到导航栏中有一个"编辑器"按钮。点击它即可进入我们的智能编辑器界面。
+
+
+
+ )
+ },
+ {
+ id: 2,
+ title: '创建新模板',
+ description: '编辑器会自动为您创建一个新的空白模板,您可以开始填写基本信息。',
+ icon: Settings,
+ content: (
+
+
+ 进入编辑器后,系统会自动创建一个新的空白模板。您需要先填写模板的基本信息:
+
+
+ -
+
+ 标题:为您的模板起一个描述性的名称
+
+ -
+
+ 描述:简要说明模板的用途和功能
+
+ -
+
+ 分类:选择合适的分类,便于后续管理和发现
+
+ -
+
+ 标签:添加相关标签,提高模板的可发现性
+
+
+
+ )
+ },
+ {
+ id: 3,
+ title: '定义角色和任务',
+ description: '明确指定 AI 的角色和需要完成的具体任务。',
+ icon: Zap,
+ content: (
+
+
+ 这是提示词的核心部分,需要明确定义 AI 应该扮演什么角色,以及需要完成什么任务。
+
+
+
+
角色定义示例:
+
+ "你是一位经验丰富的技术写作专家,擅长将复杂的技术概念转化为清晰易懂的内容。"
+
+
+
+
+
任务描述示例:
+
+ "请将以下技术文档改写为面向初学者的教程,使用简单的语言和具体的例子。"
+
+
+
+
+
提示:
+
+ - • 角色要具体明确,避免模糊的描述
+ - • 任务要清晰可执行,包含具体的输出要求
+ - • 考虑目标受众,调整语言风格
+
+
+
+ )
+ },
+ {
+ id: 4,
+ title: '添加上下文和约束',
+ description: '提供必要的背景信息和限制条件,确保输出质量。',
+ icon: Eye,
+ content: (
+
+
+ 上下文和约束条件帮助 AI 更好地理解您的需求,并确保输出符合预期。
+
+
+
+
+
上下文示例:
+
+ - • 目标受众:初学者/专家
+ - • 使用场景:技术文档/营销文案
+ - • 行业背景:科技/教育/金融
+ - • 特殊要求:合规性/品牌调性
+
+
+
+
+
约束条件示例:
+
+ - • 字数限制:不超过 500 字
+ - • 格式要求:Markdown/HTML
+ - • 语言风格:正式/轻松/专业
+ - • 禁止内容:敏感信息/版权内容
+
+
+
+
+ )
+ },
+ {
+ id: 5,
+ title: '设置变量和输出格式',
+ description: '定义动态变量和期望的输出格式,使模板更加灵活。',
+ icon: Code,
+ content: (
+
+
+ 变量让您的模板更加灵活,输出格式确保 AI 按照您期望的方式返回结果。
+
+
+
+
变量系统:
+
+
+
+ {{topic}}
+
+ - 文章主题
+
+
+
+ {{audience}}
+
+ - 目标受众
+
+
+
+ {{tone}}
+
+ - 语言风格
+
+
+
+
+
+
输出格式示例:
+
+{`# {{topic}}
+
+## 概述
+[简要介绍]
+
+## 主要内容
+[详细内容]
+
+## 总结
+[关键要点]`}
+
+
+
+ )
+ },
+ {
+ id: 6,
+ title: '测试和优化',
+ description: '使用内置的测试工具验证模板效果,并根据需要进行优化。',
+ icon: Play,
+ content: (
+
+
+ 测试是确保模板质量的关键步骤。PromptForge 提供了强大的测试工具来帮助您验证和优化模板。
+
+
+
+
+
测试功能:
+
+ - • 实时预览渲染结果
+ - • 变量值输入和验证
+ - • 模型参数配置
+ - • 批量测试支持
+
+
+
+
+
优化建议:
+
+ - • 检查提示词长度
+ - • 验证变量定义
+ - • 分析复杂度评分
+ - • 获取 AI 优化建议
+
+
+
+
+
+
测试步骤:
+
+ - 1. 切换到"测试"标签页
+ - 2. 输入变量值
+ - 3. 配置模型参数
+ - 4. 点击"运行测试"
+ - 5. 分析结果并优化
+
+
+
+ )
+ }
+]
+
+export default function FirstTemplatePage() {
+ const [activeStep, setActiveStep] = useState(1)
+
+ return (
+
+
+
+
+ {/* Header */}
+
+
+ 创建您的第一个模板
+
+
+ 跟随这个详细的教程,在几分钟内创建您的第一个 PromptForge 模板。
+
+
+
+
+ {/* Steps Navigation */}
+
+
+
+ 步骤导航
+
+
+
+ {/* Quick Actions */}
+
+
+
+
+ {/* Step Content */}
+
+ {STEPS.map((step) => (
+
+
+
+
+
+
+
+ 步骤 {step.id}: {step.title}
+
+
+ {step.description}
+
+
+
+
+
+ {step.content}
+
+
+ {/* Navigation */}
+
+
+
+
+ {step.id}
+ /
+ {STEPS.length}
+
+
+
+
+
+ ))}
+
+
+
+ {/* Next Steps */}
+
+
+
+ 准备开始创建?
+
+
+ 现在您已经了解了创建模板的基本步骤,是时候开始实践了!
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/docs/introduction/page.tsx b/src/app/docs/introduction/page.tsx
new file mode 100644
index 0000000..865fa6d
--- /dev/null
+++ b/src/app/docs/introduction/page.tsx
@@ -0,0 +1,295 @@
+'use client'
+
+import {
+ Zap,
+ Shield,
+ Users,
+ Code,
+ BarChart3,
+ GitBranch,
+ ArrowRight,
+ CheckCircle
+} from 'lucide-react'
+
+export default function IntroductionPage() {
+ return (
+
+
+
+
+
+ {/* Header */}
+
+
+ PromptForge 介绍
+
+
+ PromptForge 是一个专为大模型提示词系统优化的综合平台,旨在成为提示词工程师和 AI 应用开发者的核心工具。
+
+
+
+ {/* What is PromptForge */}
+
+
+ 什么是 PromptForge?
+
+
+
+ PromptForge 是一个现代化的提示词工程平台,它涵盖了从创建到部署的完整生命周期。我们的目标是降低高质量提示词创建的门槛,
+ 通过社区和工具链增强可靠性和可重用性。
+
+
+ 无论您是经验丰富的提示词工程师,还是刚刚开始探索 AI 应用的开发者,PromptForge 都能为您提供所需的工具和资源。
+
+
+
+
+ {/* Core Goals */}
+
+
+ 核心目标
+
+
+
+
+
+ 成为核心工具
+
+
+ 成为提示词工程师和 AI 应用开发者的首选平台,覆盖创建-优化-测试-部署的完整流程。
+
+
+
+
+
+
+ 降低门槛
+
+
+ 通过智能工具和结构化指导,让任何人都能创建高质量的提示词模板。
+
+
+
+
+
+
+ 社区驱动
+
+
+ 通过社区分享和协作,增强提示词的可靠性和可重用性。
+
+
+
+
+
+
+ 工具链集成
+
+
+ 提供完整的工具链,从开发到生产环境的无缝集成。
+
+
+
+
+
+ {/* Key Features */}
+
+
+ 核心功能
+
+
+
+
+
+
+
+
+ 智能编辑器
+
+
+ 提供结构化的表单引导,包括角色定义、任务描述、上下文设置、约束条件、输出格式和示例。
+ 支持变量系统({{}} 语法)和实时预览功能。
+
+
+ -
+
+ 结构化表单引导
+
+ -
+
+ 变量系统管理
+
+ -
+
+ 实时预览功能
+
+
+
+
+
+
+
+
+
+
+
+ 模板库与社区
+
+
+ 提供丰富的模板库,支持分类、排序、筛选和搜索。用户可以分享、评分和讨论模板,
+ 构建活跃的社区生态。
+
+
+ -
+
+ 模板发现和分享
+
+ -
+
+ 社区反馈系统
+
+ -
+
+ 分类和标签系统
+
+
+
+
+
+
+
+
+
+
+
+ 提示词优化工具
+
+
+ 提供静态分析和 AI 辅助优化功能,包括长度检查、复杂度分析、可读性评分和智能建议。
+ 支持 A/B 测试和性能对比。
+
+
+ -
+
+ 静态分析检查
+
+ -
+
+ AI 辅助优化
+
+ -
+
+ A/B 测试支持
+
+
+
+
+
+
+
+
+
+
+
+ API 集成与部署
+
+
+ 支持多种 AI 平台和编程语言,提供代码生成器和部署指南。
+ 支持 FastAPI、Cloudflare Worker、LangChain 等集成方案。
+
+
+ -
+
+ 多平台支持
+
+ -
+
+ 代码生成器
+
+ -
+
+ 部署指南
+
+
+
+
+
+
+
+ {/* Why Choose PromptForge */}
+
+
+ 为什么选择 PromptForge?
+
+
+
+
+
+
+
+ 高效开发
+
+
+ 智能工具和模板库让您快速创建高质量的提示词
+
+
+
+
+
+
+
+
+ 质量保证
+
+
+ 内置优化工具和测试功能确保提示词的质量和可靠性
+
+
+
+
+
+
+
+
+ 社区支持
+
+
+ 活跃的社区和丰富的资源帮助您学习和成长
+
+
+
+
+
+ {/* Get Started */}
+
+
+
+ 准备开始使用 PromptForge?
+
+
+ 立即开始创建您的第一个提示词模板,体验现代化的提示词工程工作流。
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/docs/page.tsx b/src/app/docs/page.tsx
new file mode 100644
index 0000000..8efe7ba
--- /dev/null
+++ b/src/app/docs/page.tsx
@@ -0,0 +1,301 @@
+'use client'
+
+import { useState } from 'react'
+import { usePromptStore } from '@/store/promptStore'
+import {
+ BookOpen,
+ FileText,
+ Code,
+ Lightbulb,
+ Users,
+ Settings,
+ ChevronRight,
+ Search,
+ ExternalLink
+} from 'lucide-react'
+
+const DOCS_SECTIONS = [
+ {
+ id: 'getting-started',
+ title: '快速开始',
+ icon: BookOpen,
+ items: [
+ { id: 'introduction', title: '介绍', path: '/docs/introduction' },
+ { id: 'installation', title: '安装指南', path: '/docs/installation' },
+ { id: 'first-template', title: '创建第一个模板', path: '/docs/first-template' },
+ ]
+ },
+ {
+ id: 'core-concepts',
+ title: '核心概念',
+ icon: Lightbulb,
+ items: [
+ { id: 'prompt-structure', title: '提示词结构', path: '/docs/prompt-structure' },
+ { id: 'variables', title: '变量系统', path: '/docs/variables' },
+ { id: 'constraints', title: '约束条件', path: '/docs/constraints' },
+ { id: 'output-formats', title: '输出格式', path: '/docs/output-formats' },
+ ]
+ },
+ {
+ id: 'features',
+ title: '功能特性',
+ icon: Settings,
+ items: [
+ { id: 'editor', title: '智能编辑器', path: '/docs/editor' },
+ { id: 'optimization', title: '提示词优化', path: '/docs/optimization' },
+ { id: 'testing', title: '测试与验证', path: '/docs/testing' },
+ { id: 'deployment', title: '部署集成', path: '/docs/deployment' },
+ ]
+ },
+ {
+ id: 'api',
+ title: 'API 参考',
+ icon: Code,
+ items: [
+ { id: 'rest-api', title: 'REST API', path: '/docs/rest-api' },
+ { id: 'sdk', title: 'SDK 使用', path: '/docs/sdk' },
+ { id: 'webhooks', title: 'Webhooks', path: '/docs/webhooks' },
+ ]
+ },
+ {
+ id: 'community',
+ title: '社区',
+ icon: Users,
+ items: [
+ { id: 'templates', title: '模板库', path: '/docs/templates' },
+ { id: 'contributing', title: '贡献指南', path: '/docs/contributing' },
+ { id: 'faq', title: '常见问题', path: '/docs/faq' },
+ ]
+ }
+]
+
+export default function DocsPage() {
+ const [searchQuery, setSearchQuery] = useState('')
+ const [activeSection, setActiveSection] = useState('getting-started')
+ const { theme } = usePromptStore()
+
+ const filteredSections = DOCS_SECTIONS.map(section => ({
+ ...section,
+ items: section.items.filter(item =>
+ item.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ section.title.toLowerCase().includes(searchQuery.toLowerCase())
+ )
+ })).filter(section => section.items.length > 0)
+
+ return (
+
+ {/* Header */}
+
+
+
+
+
+
+
+ PromptForge 文档
+
+
+ 完整的提示词工程指南
+
+
+
+
+
+
+
+
+
+
+ {/* Sidebar */}
+
+
+ {/* Search */}
+
+
+
+ setSearchQuery(e.target.value)}
+ className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+ />
+
+
+
+ {/* Navigation */}
+
+
+
+
+ {/* Main Content */}
+
+
+
+
+
+ 欢迎使用 PromptForge 文档
+
+
+
+ PromptForge 是一个专为大模型提示词系统优化的平台,帮助您创建、优化、测试和部署高质量的提示词模板。
+
+
+ {/* Quick Start Cards */}
+
+
+
+
+ 快速开始
+
+
+ 在几分钟内创建您的第一个提示词模板
+
+
+ 开始使用
+
+
+
+
+
+
+
+ API 集成
+
+
+ 了解如何将 PromptForge 集成到您的应用中
+
+
+ 查看 API
+
+
+
+
+
+ {/* Features Overview */}
+
+
+ 核心功能
+
+
+
+
+
+
+
+
+ 智能编辑器
+
+
+ 结构化编辑,实时预览,变量管理
+
+
+
+
+
+
+
+
+ 提示词优化
+
+
+ AI 辅助优化,性能分析,最佳实践
+
+
+
+
+
+
+
+
+ 测试部署
+
+
+ 沙盒测试,批量验证,一键部署
+
+
+
+
+
+ {/* Getting Help */}
+
+
+ 需要帮助?
+
+
+ 如果您在使用过程中遇到问题,可以查看我们的常见问题或联系支持团队。
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/editor/page.tsx b/src/app/editor/page.tsx
new file mode 100644
index 0000000..4bc3dd7
--- /dev/null
+++ b/src/app/editor/page.tsx
@@ -0,0 +1,342 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
+import { useAuth } from '@/contexts/AuthContext';
+import {
+ Save,
+ Eye,
+ Code,
+ TestTube,
+ Download,
+ Settings,
+ Plus,
+ Trash2,
+ Copy,
+ Check,
+ Share2,
+ Globe,
+ Lock
+} from 'lucide-react';
+import { usePromptStore } from '@/store/promptStore';
+import { PromptEditor } from '@/components/editor/prompt-editor';
+import { PromptPreview } from '@/components/editor/prompt-preview';
+import { VariablesPanel } from '@/components/editor/variables-panel';
+import { TestPanel } from '@/components/editor/test-panel';
+import { DeployPanel } from '@/components/editor/deploy-panel';
+import { generateId } from '@/lib/utils';
+import { PromptTemplate, PromptVariable, PromptConstraint } from '@/types/prompt';
+import { CATEGORIES, OUTPUT_FORMATS } from '@/lib/constants';
+
+export default function EditorPage() {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const { user } = useAuth();
+
+ const {
+ currentTemplate,
+ setCurrentTemplate,
+ updateTemplate,
+ addTemplate,
+ activeTab,
+ setActiveTab
+ } = usePromptStore();
+
+ const [isSaved, setIsSaved] = useState(false);
+ const [isSaving, setIsSaving] = useState(false);
+ const [showShareModal, setShowShareModal] = useState(false);
+ const [shareUrl, setShareUrl] = useState('');
+
+ // Initialize new template or load existing template
+ useEffect(() => {
+ const templateId = searchParams.get('template');
+
+ if (templateId) {
+ // Load existing template
+ fetchTemplate(templateId);
+ } else if (!currentTemplate) {
+ // Create new template
+ const newTemplate: PromptTemplate = {
+ id: generateId(),
+ title: '新提示词模板',
+ description: '',
+ category: 'programming',
+ tags: [],
+ role: '',
+ task: '',
+ context: '',
+ constraints: [],
+ outputFormat: 'plain-text',
+ variables: [],
+ examples: [],
+ author: user?.name || '用户',
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ usageCount: 0,
+ rating: 0,
+ ratingCount: 0,
+ compatibleModels: [],
+ isPublic: false,
+ isFeatured: false,
+ };
+ setCurrentTemplate(newTemplate);
+ }
+ }, [currentTemplate, setCurrentTemplate, searchParams, user]);
+
+ const fetchTemplate = async (templateId: string) => {
+ try {
+ const response = await fetch(`/api/templates/${templateId}`);
+ const data = await response.json();
+
+ if (data.success) {
+ setCurrentTemplate(data.data);
+ } else {
+ console.error('获取模板失败:', data.error);
+ }
+ } catch (error) {
+ console.error('获取模板失败:', error);
+ }
+ };
+
+ const handleSave = async () => {
+ if (!currentTemplate || !user) return;
+
+ setIsSaving(true);
+ try {
+ const templateData = {
+ ...currentTemplate,
+ authorId: user.id,
+ updatedAt: new Date().toISOString()
+ };
+
+ const response = await fetch('/api/templates', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(templateData),
+ });
+
+ const data = await response.json();
+
+ if (data.success) {
+ setIsSaved(true);
+ setTimeout(() => setIsSaved(false), 2000);
+ console.log('模板保存成功');
+ } else {
+ console.error('保存失败:', data.error);
+ }
+ } catch (error) {
+ console.error('保存模板失败:', error);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ const handleShare = () => {
+ if (currentTemplate) {
+ const url = `${window.location.origin}/templates/${currentTemplate.id}`;
+ setShareUrl(url);
+ setShowShareModal(true);
+ }
+ };
+
+ const copyToClipboard = async (text: string) => {
+ try {
+ await navigator.clipboard.writeText(text);
+ // 可以添加一个提示
+ } catch (error) {
+ console.error('复制失败:', error);
+ }
+ };
+
+ const handleAddVariable = () => {
+ if (currentTemplate) {
+ // 生成唯一的变量名
+ let variableName = `variable_1`;
+ let counter = 1;
+ while (currentTemplate.variables.some(v => v.name === variableName)) {
+ counter++;
+ variableName = `variable_${counter}`;
+ }
+
+ const newVariable: PromptVariable = {
+ name: variableName,
+ type: 'text',
+ required: true,
+ description: '',
+ };
+ updateTemplate({
+ variables: [...currentTemplate.variables, newVariable]
+ });
+ }
+ };
+
+ const handleAddConstraint = () => {
+ if (currentTemplate) {
+ const newConstraint: PromptConstraint = {
+ id: generateId(),
+ text: '',
+ category: 'quality',
+ };
+ updateTemplate({
+ constraints: [...currentTemplate.constraints, newConstraint]
+ });
+ }
+ };
+
+ if (!currentTemplate) {
+ return (
+
+ );
+ }
+
+ return (
+
+ {/* Header */}
+
+
+
+ updateTemplate({ title: e.target.value })}
+ className="text-2xl font-bold text-gray-900 dark:text-white bg-transparent border-none outline-none focus:ring-0"
+ placeholder="输入模板标题..."
+ />
+
+
+
+
+
+
+
+
+
+
+ {/* Tabs */}
+
+
+ {[
+ { id: 'editor', label: '编辑器', icon: Code },
+ { id: 'preview', label: '预览', icon: Eye },
+ { id: 'variables', label: '变量', icon: Settings },
+ { id: 'test', label: '测试', icon: TestTube },
+ { id: 'deploy', label: '部署', icon: Download },
+ ].map((tab) => {
+ const Icon = tab.icon;
+ return (
+
+ );
+ })}
+
+
+
+ {/* Content */}
+
+ {activeTab === 'editor' && (
+
+ )}
+
+ {activeTab === 'preview' && (
+
+ )}
+
+ {activeTab === 'variables' && (
+
+ )}
+
+ {activeTab === 'test' && (
+
+ )}
+
+ {activeTab === 'deploy' && (
+
+ )}
+
+
+ {/* 分享模态框 */}
+ {showShareModal && (
+
+
+
+ 分享模板
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/app/globals.css b/src/app/globals.css
new file mode 100644
index 0000000..4751328
--- /dev/null
+++ b/src/app/globals.css
@@ -0,0 +1,210 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+ --primary: 221.2 83.2% 53.3%;
+ --primary-foreground: 210 40% 98%;
+ --secondary: 210 40% 96%;
+ --secondary-foreground: 222.2 84% 4.9%;
+ --muted: 210 40% 96%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+ --accent: 210 40% 96%;
+ --accent-foreground: 222.2 84% 4.9%;
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 210 40% 98%;
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+ --ring: 221.2 83.2% 53.3%;
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+ --primary: 217.2 91.2% 59.8%;
+ --primary-foreground: 222.2 84% 4.9%;
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 210 40% 98%;
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+ --ring: 224.3 76.3% 94.1%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-gray-200 dark:border-gray-700;
+ }
+ body {
+ @apply bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100;
+ }
+}
+
+@layer components {
+ .btn {
+ @apply inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none;
+ }
+
+ .btn-primary {
+ @apply btn bg-blue-600 text-white hover:bg-blue-700;
+ }
+
+ .btn-secondary {
+ @apply btn bg-gray-200 text-gray-900 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600;
+ }
+
+ .btn-outline {
+ @apply btn border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-800;
+ }
+
+ .btn-ghost {
+ @apply btn hover:bg-gray-100 dark:hover:bg-gray-800;
+ }
+
+ .btn-sm {
+ @apply h-8 px-3 text-xs;
+ }
+
+ .btn-md {
+ @apply h-10 px-4 py-2;
+ }
+
+ .btn-lg {
+ @apply h-12 px-8;
+ }
+
+ .input {
+ @apply flex h-10 w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-gray-500 dark:placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
+ }
+
+ .textarea {
+ @apply flex min-h-[80px] w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-3 py-2 text-sm placeholder:text-gray-500 dark:placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
+ }
+
+ .card {
+ @apply rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-sm;
+ }
+
+ .card-header {
+ @apply flex flex-col space-y-1.5 p-6;
+ }
+
+ .card-title {
+ @apply text-2xl font-semibold leading-none tracking-tight;
+ }
+
+ .card-description {
+ @apply text-sm text-gray-600 dark:text-gray-400;
+ }
+
+ .card-content {
+ @apply p-6 pt-0;
+ }
+
+ .card-footer {
+ @apply flex items-center p-6 pt-0;
+ }
+}
+
+/* Custom scrollbar */
+::-webkit-scrollbar {
+ width: 6px;
+ height: 6px;
+}
+
+::-webkit-scrollbar-track {
+ background: transparent;
+}
+
+::-webkit-scrollbar-thumb {
+ background: #cbd5e1;
+ border-radius: 3px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: #94a3b8;
+}
+
+.dark ::-webkit-scrollbar-thumb {
+ background: #475569;
+}
+
+.dark ::-webkit-scrollbar-thumb:hover {
+ background: #64748b;
+}
+
+/* Monaco Editor customizations */
+.monaco-editor {
+ border-radius: 0.5rem;
+ overflow: hidden;
+}
+
+.monaco-editor .margin {
+ background-color: transparent !important;
+}
+
+/* Animation classes */
+.animate-fade-in {
+ animation: fadeIn 0.5s ease-in-out;
+}
+
+.animate-slide-up {
+ animation: slideUp 0.3s ease-out;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes slideUp {
+ from {
+ transform: translateY(10px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+/* Code highlighting */
+.hljs {
+ background: transparent !important;
+}
+
+/* Variable highlighting */
+.variable-highlight {
+ background-color: rgba(59, 130, 246, 0.1);
+ border: 1px solid rgba(59, 130, 246, 0.3);
+ border-radius: 3px;
+ padding: 1px 3px;
+ font-weight: 500;
+}
+
+.dark .variable-highlight {
+ background-color: rgba(59, 130, 246, 0.2);
+ border-color: rgba(59, 130, 246, 0.4);
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
new file mode 100644
index 0000000..3b7acb3
--- /dev/null
+++ b/src/app/layout.tsx
@@ -0,0 +1,43 @@
+import type { Metadata } from 'next';
+import { Inter } from 'next/font/google';
+import './globals.css';
+import { Providers } from '@/components/providers';
+import { AuthProvider } from '@/contexts/AuthContext';
+import { Sidebar } from '@/components/layout/sidebar';
+import { Header } from '@/components/layout/header';
+
+const inter = Inter({ subsets: ['latin'] });
+
+export const metadata: Metadata = {
+ title: 'PromptForge - 专业的提示词工程平台',
+ description: 'PromptForge 是一个专为大模型提示词系统优化的平台,提供模板库、编辑器、测试台和部署工具,让提示词工程更简单高效。',
+ keywords: '提示词工程, AI, 大模型, 模板, 编辑器, 测试台',
+ authors: [{ name: 'PromptForge Team' }],
+ viewport: 'width=device-width, initial-scale=1',
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/page.tsx b/src/app/page.tsx
new file mode 100644
index 0000000..b556ef9
--- /dev/null
+++ b/src/app/page.tsx
@@ -0,0 +1,259 @@
+'use client';
+
+import { useEffect } from 'react';
+import Link from 'next/link';
+import {
+ ArrowRight,
+ Sparkles,
+ Code,
+ TestTube,
+ Rocket,
+ Star,
+ Users,
+ Zap
+} from 'lucide-react';
+import { usePromptStore } from '@/store/promptStore';
+import { SAMPLE_TEMPLATES } from '@/lib/constants';
+import { getCategoryIcon, getCategoryColor, formatRelativeTime } from '@/lib/utils';
+import { cn } from '@/lib/utils';
+
+export default function HomePage() {
+ const { templates, setTemplates } = usePromptStore();
+
+ useEffect(() => {
+ if (templates.length === 0) {
+ setTemplates(SAMPLE_TEMPLATES);
+ }
+ }, [templates.length, setTemplates]);
+
+ const featuredTemplates = templates.filter(t => t.isFeatured).slice(0, 6);
+
+ return (
+
+ {/* Hero Section */}
+
+
+
+
+
+
+ PromptForge
+
+
+
+ 专业的提示词工程平台,让AI应用开发更简单高效。
+ 从模板库到编辑器,从测试台到部署,一站式解决提示词全生命周期管理。
+
+
+
+ 探索模板库
+
+
+
+ 开始创建
+
+
+
+
+
+
+ {/* Features Section */}
+
+
+
+
+ 核心功能
+
+
+ 专为提示词工程师设计的强大工具集
+
+
+
+
+
+
+
+
+
+ 智能编辑器
+
+
+ 结构化表单引导,变量系统,实时预览,让提示词创作更高效
+
+
+
+
+
+
+
+
+ 测试台
+
+
+ 交互式测试,批量验证,A/B测试,确保提示词质量
+
+
+
+
+
+
+
+
+ 优化工具
+
+
+ AI辅助优化,静态分析,最佳实践建议,持续改进
+
+
+
+
+
+
+
+
+ 一键部署
+
+
+ 代码生成,API集成,多平台支持,快速上线
+
+
+
+
+
+
+ {/* Featured Templates */}
+
+
+
+
+
+ 精选模板
+
+
+ 社区精选的高质量提示词模板
+
+
+
+ 查看全部
+
+
+
+
+
+ {featuredTemplates.map((template) => (
+
+
+
+ {getCategoryIcon(template.category)}
+
+ {template.category}
+
+
+
+
+ {template.rating.toFixed(1)}
+
+
+
+
+ {template.title}
+
+
+ {template.description}
+
+
+
+
+
+ {template.usageCount} 次使用
+
+
+ 查看详情
+
+
+
+
+ ))}
+
+
+
+
+ {/* Stats Section */}
+
+
+
+
+
+ {templates.length}+
+
+
优质模板
+
+
+
+
+
+
+
+
+ {/* CTA Section */}
+
+
+
+ 开始你的提示词工程之旅
+
+
+ 加入数千名开发者的行列,使用 PromptForge 构建更智能的AI应用
+
+
+
+
+ 立即开始
+
+
+ 查看文档
+
+
+
+
+
+ );
+}
diff --git a/src/app/playground/page.tsx b/src/app/playground/page.tsx
new file mode 100644
index 0000000..11b47b9
--- /dev/null
+++ b/src/app/playground/page.tsx
@@ -0,0 +1,616 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { Play, Settings, History, Save, Loader2, Zap, Code, MessageSquare, Image, FileText, Layers, BarChart3 } from 'lucide-react';
+import { AI_MODELS } from '@/lib/constants';
+import { useAuth } from '@/contexts/AuthContext';
+import { ResultComparison } from '@/components/playground/result-comparison';
+
+interface TestResult {
+ id: string;
+ prompt: string;
+ result: string;
+ model: string;
+ provider: string;
+ timestamp: string;
+ variables?: Record;
+ temperature?: number;
+ maxTokens?: number;
+}
+
+interface BatchTestResult {
+ model: string;
+ provider: string;
+ result: string;
+ success: boolean;
+ error?: string;
+ responseTime: number;
+}
+
+export default function PlaygroundPage() {
+ const { user } = useAuth();
+ const [activeTab, setActiveTab] = useState('chat');
+ const [prompt, setPrompt] = useState('');
+ const [model, setModel] = useState('deepseek-chat');
+ const [temperature, setTemperature] = useState(0.7);
+ const [maxTokens, setMaxTokens] = useState(1000);
+ const [isLoading, setIsLoading] = useState(false);
+ const [results, setResults] = useState([]);
+ const [batchResults, setBatchResults] = useState([]);
+ const [variables, setVariables] = useState>({});
+ const [variableInputs, setVariableInputs] = useState<{ name: string; value: string }[]>([]);
+ const [selectedModels, setSelectedModels] = useState(['deepseek-chat']);
+ const [showComparison, setShowComparison] = useState(false);
+
+ // 预设的测试场景
+ const testScenarios = {
+ chat: {
+ title: '通用对话',
+ icon: MessageSquare,
+ prompts: [
+ '你好,请介绍一下你自己',
+ '解释一下什么是人工智能',
+ '写一个关于春天的短诗',
+ '帮我制定一个学习计划'
+ ]
+ },
+ code: {
+ title: '代码生成',
+ icon: Code,
+ prompts: [
+ '用Python写一个计算斐波那契数列的函数',
+ '用JavaScript实现一个简单的待办事项应用',
+ '写一个SQL查询来获取用户订单信息',
+ '用React创建一个计数器组件'
+ ]
+ },
+ analysis: {
+ title: '数据分析',
+ icon: FileText,
+ prompts: [
+ '分析一下电商平台的用户行为数据',
+ '帮我解读这份销售报表',
+ '生成一个数据可视化的建议',
+ '分析用户留存率下降的原因'
+ ]
+ },
+ creative: {
+ title: '创意写作',
+ icon: Zap,
+ prompts: [
+ '写一个科幻小说的开头',
+ '创作一首关于友谊的诗歌',
+ '写一个产品营销文案',
+ '创作一个童话故事'
+ ]
+ }
+ };
+
+ const handleTest = async () => {
+ if (!(prompt || '').trim()) return;
+
+ setIsLoading(true);
+ const testId = Date.now().toString();
+
+ try {
+ const response = await fetch('/api/test', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ prompt: prompt || '',
+ model: model,
+ temperature: temperature,
+ maxTokens: maxTokens,
+ variables: variables
+ }),
+ });
+
+ const data = await response.json();
+
+ if (data.success) {
+ const newResult: TestResult = {
+ id: testId,
+ prompt: prompt || '',
+ result: data.data.result,
+ model: data.data.model,
+ provider: data.data.provider,
+ timestamp: data.data.timestamp,
+ variables: variables,
+ temperature: temperature,
+ maxTokens: maxTokens
+ };
+
+ setResults(prev => [newResult, ...prev]);
+ setPrompt(''); // 清空输入框
+ } else {
+ // 显示错误结果
+ const errorResult: TestResult = {
+ id: testId,
+ prompt: prompt || '',
+ result: `❌ 测试失败:${data.error}`,
+ model: model,
+ provider: 'Error',
+ timestamp: new Date().toISOString(),
+ variables: variables,
+ temperature: temperature,
+ maxTokens: maxTokens
+ };
+ setResults(prev => [errorResult, ...prev]);
+ }
+ } catch (error) {
+ const errorResult: TestResult = {
+ id: testId,
+ prompt: prompt || '',
+ result: `❌ 网络错误:${error}`,
+ model: model,
+ provider: 'Error',
+ timestamp: new Date().toISOString(),
+ variables: variables,
+ temperature: temperature,
+ maxTokens: maxTokens
+ };
+ setResults(prev => [errorResult, ...prev]);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const handleBatchTest = async () => {
+ if (!(prompt || '').trim() || selectedModels.length === 0) return;
+
+ setIsLoading(true);
+ setShowComparison(false);
+
+ try {
+ const response = await fetch('/api/test/batch', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ prompt: prompt || '',
+ models: selectedModels,
+ temperature: temperature,
+ maxTokens: maxTokens,
+ variables: variables
+ }),
+ });
+
+ const data = await response.json();
+
+ if (data.success) {
+ setBatchResults(data.data.results);
+ setShowComparison(true);
+
+ // 同时添加到单个结果列表
+ data.data.results.forEach((result: BatchTestResult) => {
+ if (result.success) {
+ const newResult: TestResult = {
+ id: Date.now().toString() + result.model,
+ prompt: prompt || '',
+ result: result.result,
+ model: result.model,
+ provider: result.provider,
+ timestamp: data.data.timestamp,
+ variables: variables,
+ temperature: temperature,
+ maxTokens: maxTokens
+ };
+ setResults(prev => [newResult, ...prev]);
+ }
+ });
+ } else {
+ alert(`批量测试失败:${data.error}`);
+ }
+ } catch (error) {
+ alert(`批量测试错误:${error}`);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const handleModelSelection = (modelValue: string) => {
+ setSelectedModels(prev => {
+ if (prev.includes(modelValue)) {
+ return prev.filter(m => m !== modelValue);
+ } else {
+ return [...prev, modelValue];
+ }
+ });
+ };
+
+ const handleQuickTest = (quickPrompt: string) => {
+ setPrompt(quickPrompt);
+ };
+
+ const handleSaveResult = (result: TestResult) => {
+ // 保存到本地存储
+ const savedResults = JSON.parse(localStorage.getItem('playground-results') || '[]');
+ savedResults.push(result);
+ localStorage.setItem('playground-results', JSON.stringify(savedResults));
+ alert('测试结果已保存到本地存储');
+ };
+
+ const handleLoadResults = () => {
+ const savedResults = JSON.parse(localStorage.getItem('playground-results') || '[]');
+ setResults(savedResults);
+ };
+
+ const handleClearResults = () => {
+ setResults([]);
+ };
+
+ const addVariable = () => {
+ setVariableInputs(prev => [...prev, { name: '', value: '' }]);
+ };
+
+ const updateVariable = (index: number, field: 'name' | 'value', value: string) => {
+ setVariableInputs(prev => prev.map((item, i) =>
+ i === index ? { ...item, [field]: value } : item
+ ));
+ };
+
+ const removeVariable = (index: number) => {
+ setVariableInputs(prev => prev.filter((_, i) => i !== index));
+ };
+
+ const applyVariables = () => {
+ const newVariables: Record = {};
+ variableInputs.forEach(input => {
+ if (input.name && input.value) {
+ newVariables[input.name] = input.value;
+ }
+ });
+ setVariables(newVariables);
+ };
+
+ useEffect(() => {
+ // 加载保存的结果
+ handleLoadResults();
+ }, []);
+
+ return (
+
+
+ {/* Header */}
+
+
+ AI 测试台
+
+
+ 测试和调试各种 AI 模型,快速验证提示词效果
+
+
+
+
+ {/* 左侧控制面板 */}
+
+ {/* 测试场景选择 */}
+
+
+ 测试场景
+
+
+ {Object.entries(testScenarios).map(([key, scenario]) => {
+ const Icon = scenario.icon;
+ return (
+
+ );
+ })}
+
+
+
+ {/* 模型设置 */}
+
+
+ 模型设置
+
+
+
+
+
+
+
+
+
+
+ {AI_MODELS.map((m) => (
+
+ ))}
+
+
+
+
+
+ setTemperature(Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+
+ setMaxTokens(Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+
+ {/* 变量设置 */}
+
+
+
+ 变量设置
+
+
+
+
+
+
+ {/* 快捷提示词 */}
+
+
+ 快捷提示词
+
+
+ {testScenarios[activeTab as keyof typeof testScenarios]?.prompts.map((prompt, index) => (
+
+ ))}
+
+
+
+
+ {/* 中间输入区域 */}
+
+ {/* 提示词输入 */}
+
+
+
+ 提示词输入
+
+
+
+
+
+
+
+
+ {/* 当前变量显示 */}
+ {Object.keys(variables).length > 0 && (
+
+
+ 当前变量
+
+
+ {Object.entries(variables).map(([key, value]) => (
+
+ {key}:
+
+ {typeof value === 'object' && value !== null
+ ? JSON.stringify(value)
+ : String(value)}
+
+
+ ))}
+
+
+ )}
+
+
+ {/* 右侧结果区域 */}
+
+ {/* 批量测试结果比较 */}
+ {showComparison && batchResults.length > 0 && (
+
+ )}
+
+ {/* 单个测试结果 */}
+
+
+ 测试结果
+
+
+ {results.length === 0 ? (
+
+
+
还没有测试结果
+
输入提示词并点击"运行测试"开始
+
+ ) : (
+ results.map((result) => (
+
+
+
+
+ {result.provider || '未知'}
+
+
+ {result.model || '未知'}
+
+
+
+
+
+ {result.timestamp ? new Date(result.timestamp).toLocaleTimeString() : '未知时间'}
+
+
+
+
+
提示词:
+
+ {result.prompt || '无提示词'}
+
+
+
+
响应:
+
+ {result.result || '无响应内容'}
+
+
+
+ ))
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx
new file mode 100644
index 0000000..ecc095b
--- /dev/null
+++ b/src/app/profile/page.tsx
@@ -0,0 +1,227 @@
+'use client'
+
+import { useState, useEffect } from 'react'
+import { useRouter } from 'next/navigation'
+import { useAuth } from '@/contexts/AuthContext'
+import { ProtectedRoute } from '@/components/auth/ProtectedRoute'
+import { User, Mail, Calendar, Save, Camera, ArrowLeft } from 'lucide-react'
+import Link from 'next/link'
+
+export default function ProfilePage() {
+ const { user, updateProfile, logout } = useAuth()
+ const router = useRouter()
+
+ const [formData, setFormData] = useState({
+ name: '',
+ avatar: ''
+ })
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState('')
+ const [success, setSuccess] = useState('')
+
+ useEffect(() => {
+ if (!user) {
+ router.push('/auth/login')
+ return
+ }
+
+ setFormData({
+ name: user.name || '',
+ avatar: user.avatar || ''
+ })
+ }, [user, router])
+
+ const handleChange = (e: React.ChangeEvent) => {
+ setFormData({
+ ...formData,
+ [e.target.name]: e.target.value
+ })
+ }
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+ setLoading(true)
+ setError('')
+ setSuccess('')
+
+ const result = await updateProfile(formData)
+
+ if (result.success) {
+ setSuccess('资料更新成功!')
+ } else {
+ setError(result.error || '更新失败')
+ }
+
+ setLoading(false)
+ }
+
+ const handleLogout = () => {
+ logout()
+ router.push('/')
+ }
+
+ return (
+
+
+
+ {/* 头部 */}
+
+
+
+ 返回首页
+
+
个人资料
+
管理您的账户信息和设置
+
+
+
+ {/* 侧边栏 */}
+
+
+
+
+

+
+
+
+
+
+ {user.name}
+
+
{user.email}
+
+
+
+
+ 注册时间:{new Date(user.createdAt).toLocaleDateString()}
+
+
+
+
+
+
+
+
+ {/* 主要内容 */}
+
+
+
+
+
+ )
+}
diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx
new file mode 100644
index 0000000..001035c
--- /dev/null
+++ b/src/app/settings/page.tsx
@@ -0,0 +1,694 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import {
+ Settings,
+ User,
+ Key,
+ Palette,
+ Bell,
+ Shield,
+ Database,
+ Save,
+ Loader2,
+ Check,
+ Eye,
+ EyeOff,
+ Trash2,
+ Plus,
+ Globe,
+ Moon,
+ Sun,
+ Monitor
+} from 'lucide-react';
+import { useAuth } from '@/contexts/AuthContext';
+
+interface UserSettings {
+ theme: 'light' | 'dark' | 'system';
+ language: string;
+ notifications: {
+ email: boolean;
+ push: boolean;
+ updates: boolean;
+ };
+ privacy: {
+ profileVisibility: 'public' | 'private';
+ showEmail: boolean;
+ allowAnalytics: boolean;
+ };
+ apiKeys: {
+ openai?: string;
+ anthropic?: string;
+ deepseek?: string;
+ };
+ preferences: {
+ autoSave: boolean;
+ defaultModel: string;
+ maxTokens: number;
+ temperature: number;
+ };
+}
+
+export default function SettingsPage() {
+ const { user } = useAuth();
+ const [activeTab, setActiveTab] = useState('profile');
+ const [isLoading, setIsLoading] = useState(false);
+ const [isSaving, setIsSaving] = useState(false);
+ const [showApiKeys, setShowApiKeys] = useState(false);
+ const [settings, setSettings] = useState({
+ theme: 'system',
+ language: 'zh-CN',
+ notifications: {
+ email: true,
+ push: false,
+ updates: true
+ },
+ privacy: {
+ profileVisibility: 'public',
+ showEmail: false,
+ allowAnalytics: true
+ },
+ apiKeys: {
+ openai: '',
+ anthropic: '',
+ deepseek: ''
+ },
+ preferences: {
+ autoSave: true,
+ defaultModel: 'deepseek-chat',
+ maxTokens: 1000,
+ temperature: 0.7
+ }
+ });
+
+ useEffect(() => {
+ loadSettings();
+ }, []);
+
+ const loadSettings = async () => {
+ try {
+ const savedSettings = localStorage.getItem('user-settings');
+ if (savedSettings) {
+ setSettings(JSON.parse(savedSettings));
+ }
+ } catch (error) {
+ console.error('加载设置失败:', error);
+ }
+ };
+
+ const saveSettings = async () => {
+ setIsSaving(true);
+ try {
+ localStorage.setItem('user-settings', JSON.stringify(settings));
+ // 应用主题设置
+ applyTheme(settings.theme);
+ await new Promise(resolve => setTimeout(resolve, 1000)); // 模拟保存延迟
+ } catch (error) {
+ console.error('保存设置失败:', error);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ const applyTheme = (theme: string) => {
+ const root = document.documentElement;
+ if (theme === 'dark' || (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
+ root.classList.add('dark');
+ } else {
+ root.classList.remove('dark');
+ }
+ };
+
+ const updateSettings = (key: string, value: any) => {
+ setSettings(prev => ({
+ ...prev,
+ [key]: value
+ }));
+ };
+
+ const updateNestedSettings = (parentKey: string, childKey: string, value: any) => {
+ setSettings(prev => ({
+ ...prev,
+ [parentKey]: {
+ ...prev[parentKey as keyof UserSettings],
+ [childKey]: value
+ }
+ }));
+ };
+
+ const handleApiKeyChange = (provider: string, value: string) => {
+ setSettings(prev => ({
+ ...prev,
+ apiKeys: {
+ ...prev.apiKeys,
+ [provider]: value
+ }
+ }));
+ };
+
+ const testApiKey = async (provider: string) => {
+ const apiKey = settings.apiKeys[provider as keyof typeof settings.apiKeys];
+ if (!apiKey) {
+ alert('请先输入 API 密钥');
+ return;
+ }
+
+ setIsLoading(true);
+ try {
+ // 模拟 API 测试
+ await new Promise(resolve => setTimeout(resolve, 2000));
+ alert(`${provider} API 密钥测试成功!`);
+ } catch (error) {
+ alert(`${provider} API 密钥测试失败:${error}`);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const resetSettings = () => {
+ if (confirm('确定要重置所有设置吗?此操作不可撤销。')) {
+ const defaultSettings: UserSettings = {
+ theme: 'system',
+ language: 'zh-CN',
+ notifications: {
+ email: true,
+ push: false,
+ updates: true
+ },
+ privacy: {
+ profileVisibility: 'public',
+ showEmail: false,
+ allowAnalytics: true
+ },
+ apiKeys: {
+ openai: '',
+ anthropic: '',
+ deepseek: ''
+ },
+ preferences: {
+ autoSave: true,
+ defaultModel: 'deepseek-chat',
+ maxTokens: 1000,
+ temperature: 0.7
+ }
+ };
+ setSettings(defaultSettings);
+ localStorage.removeItem('user-settings');
+ }
+ };
+
+ const tabs = [
+ { id: 'profile', name: '个人资料', icon: User },
+ { id: 'api', name: 'API 配置', icon: Key },
+ { id: 'appearance', name: '外观设置', icon: Palette },
+ { id: 'notifications', name: '通知设置', icon: Bell },
+ { id: 'privacy', name: '隐私设置', icon: Shield },
+ { id: 'preferences', name: '偏好设置', icon: Settings }
+ ];
+
+ return (
+
+
+ {/* Header */}
+
+
+ 设置
+
+
+ 管理您的账户设置和偏好
+
+
+
+
+ {/* 左侧导航 */}
+
+
+
+
+
+
+ {/* 右侧内容 */}
+
+
+ {/* 个人资料设置 */}
+ {activeTab === 'profile' && (
+
+
+ 个人资料
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ {/* API 配置设置 */}
+ {activeTab === 'api' && (
+
+
+
+ API 配置
+
+
+
+
+
+ {/* OpenAI API */}
+
+
+
+ OpenAI API
+
+
+
+
handleApiKeyChange('openai', e.target.value)}
+ className="w-full input"
+ placeholder="输入 OpenAI API 密钥"
+ />
+
+ 用于访问 GPT-4, GPT-3.5 等模型
+
+
+
+ {/* Anthropic API */}
+
+
+
+ Anthropic API
+
+
+
+
handleApiKeyChange('anthropic', e.target.value)}
+ className="w-full input"
+ placeholder="输入 Anthropic API 密钥"
+ />
+
+ 用于访问 Claude 3 系列模型
+
+
+
+ {/* DeepSeek API */}
+
+
+
+ DeepSeek API
+
+
+
+
handleApiKeyChange('deepseek', e.target.value)}
+ className="w-full input"
+ placeholder="输入 DeepSeek API 密钥"
+ />
+
+ 用于访问 DeepSeek Chat, Coder, Vision 等模型
+
+
+
+
+ )}
+
+ {/* 外观设置 */}
+ {activeTab === 'appearance' && (
+
+
+ 外观设置
+
+
+
+
+
+
+ {[
+ { value: 'light', label: '浅色', icon: Sun },
+ { value: 'dark', label: '深色', icon: Moon },
+ { value: 'system', label: '跟随系统', icon: Monitor }
+ ].map((theme) => {
+ const Icon = theme.icon;
+ return (
+
+ );
+ })}
+
+
+
+
+
+
+
+
+
+ )}
+
+ {/* 通知设置 */}
+ {activeTab === 'notifications' && (
+
+
+ 通知设置
+
+
+
+
+
+
邮件通知
+
+ 接收重要更新和活动通知
+
+
+
+
+
+
+
+
+
+
+
+
+
更新通知
+
+ 接收产品更新和新功能通知
+
+
+
+
+
+
+ )}
+
+ {/* 隐私设置 */}
+ {activeTab === 'privacy' && (
+
+
+ 隐私设置
+
+
+
+
+
+
+
+
+
+
+
显示邮箱
+
+ 允许其他用户查看您的邮箱地址
+
+
+
+
+
+
+
+
数据分析
+
+ 允许收集匿名使用数据以改进产品
+
+
+
+
+
+
+ )}
+
+ {/* 偏好设置 */}
+ {activeTab === 'preferences' && (
+
+
+ 偏好设置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ updateNestedSettings('preferences', 'maxTokens', Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+
+ updateNestedSettings('preferences', 'temperature', Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+ )}
+
+ {/* 操作按钮 */}
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/templates/[id]/page.tsx b/src/app/templates/[id]/page.tsx
new file mode 100644
index 0000000..388a74e
--- /dev/null
+++ b/src/app/templates/[id]/page.tsx
@@ -0,0 +1,454 @@
+'use client'
+
+import { useState, useEffect } from 'react'
+import { useParams, useRouter } from 'next/navigation'
+import { useAuth } from '@/contexts/AuthContext'
+import { ArrowLeft, Edit, Trash2, Share2, Copy, Download } from 'lucide-react'
+import Link from 'next/link'
+
+interface Template {
+ id: string
+ title: string
+ description: string
+ category: string
+ role: string
+ task: string
+ context: string
+ constraints: Array<{id: string, text: string, category?: string} | string>
+ variables: any[]
+ outputFormat: string
+ authorId: string
+ isPublic: boolean
+ usageCount: number
+ rating: number
+ ratingCount: number
+ createdAt?: string
+ updatedAt?: string
+}
+
+export default function TemplateDetailPage() {
+ const params = useParams()
+ const router = useRouter()
+ const { user } = useAuth()
+
+ const [template, setTemplate] = useState(null)
+ const [loading, setLoading] = useState(true)
+ const [error, setError] = useState('')
+ const [showDeleteModal, setShowDeleteModal] = useState(false)
+ const [showShareModal, setShowShareModal] = useState(false)
+ const [shareUrl, setShareUrl] = useState('')
+ const [isCopying, setIsCopying] = useState(false)
+
+ useEffect(() => {
+ if (params.id) {
+ fetchTemplate()
+ }
+ }, [params.id])
+
+ const fetchTemplate = async () => {
+ try {
+ const response = await fetch(`/api/templates/${params.id}`)
+ const data = await response.json()
+
+ if (data.success) {
+ setTemplate(data.data)
+ } else {
+ setError(data.error || '模板不存在')
+ }
+ } catch (error) {
+ console.error('获取模板失败:', error)
+ setError('获取模板失败')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const handleDeleteTemplate = async () => {
+ try {
+ const response = await fetch(`/api/templates/${params.id}`, {
+ method: 'DELETE'
+ })
+
+ if (response.ok) {
+ router.push('/templates/manage')
+ }
+ } catch (error) {
+ console.error('删除模板失败:', error)
+ }
+ }
+
+ const copyToClipboard = async (text: string) => {
+ try {
+ await navigator.clipboard.writeText(text)
+ // 可以添加一个提示
+ } catch (error) {
+ console.error('复制失败:', error)
+ }
+ }
+
+ const handleShareTemplate = () => {
+ if (template) {
+ const url = `${window.location.origin}/templates/${template.id}`
+ setShareUrl(url)
+ setShowShareModal(true)
+ }
+ }
+
+ const handleCopyTemplate = async () => {
+ if (!template || !user) return
+
+ setIsCopying(true)
+ try {
+ const response = await fetch(`/api/templates/${template.id}/copy`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ userId: user.id }),
+ })
+
+ const data = await response.json()
+
+ if (data.success) {
+ // 跳转到复制的模板
+ router.push(`/templates/${data.data.id}`)
+ } else {
+ console.error('复制失败:', data.error)
+ }
+ } catch (error) {
+ console.error('复制模板失败:', error)
+ } finally {
+ setIsCopying(false)
+ }
+ }
+
+ const getCategoryIcon = (category: string) => {
+ const icons: { [key: string]: string } = {
+ 'customer-service': '🎧',
+ 'content-creation': '✍️',
+ 'programming': '💻',
+ 'data-analysis': '📊',
+ 'marketing': '📈',
+ 'education': '📚',
+ 'creative-writing': '🖋️',
+ 'project-management': '📋'
+ }
+ return icons[category] || '📄'
+ }
+
+ const getCategoryName = (category: string) => {
+ const names: { [key: string]: string } = {
+ 'customer-service': '客服',
+ 'content-creation': '内容创作',
+ 'programming': '编程',
+ 'data-analysis': '数据分析',
+ 'marketing': '营销',
+ 'education': '教育',
+ 'creative-writing': '创意写作',
+ 'project-management': '项目管理'
+ }
+ return names[category] || category
+ }
+
+ if (loading) {
+ return (
+
+ )
+ }
+
+ if (error || !template) {
+ return (
+
+
+
+ {error || '模板不存在'}
+
+
+
+ 返回模板库
+
+
+
+ )
+ }
+
+ return (
+
+
+ {/* 头部 */}
+
+
+
+ 返回模板库
+
+
+
+
+
{getCategoryIcon(template.category)}
+
+
+ {template.title}
+
+
+ {getCategoryName(template.category)} • 创建于 {new Date(template.createdAt || template.created_at).toLocaleDateString()}
+
+
+
+
+
+
+
+ {user && template.authorId !== user.id && (
+
+ )}
+
+ {user && template.authorId === user.id && (
+ <>
+
+
+ >
+ )}
+
+
+
+
+
+ {/* 主要内容 */}
+
+ {/* 描述 */}
+
+
描述
+
{template.description}
+
+
+ {/* 角色定义 */}
+
+
角色定义
+
{template.role}
+
+
+ {/* 任务 */}
+
+
+ {/* 上下文 */}
+ {template.context && (
+
+
上下文
+
{template.context}
+
+ )}
+
+ {/* 约束条件 */}
+ {template.constraints && template.constraints.length > 0 && (
+
+
约束条件
+
+ {template.constraints.map((constraint, index) => {
+ // 处理约束条件的不同格式
+ let constraintText = '';
+ if (typeof constraint === 'string') {
+ constraintText = constraint;
+ } else if (constraint && typeof constraint === 'object') {
+ constraintText = constraint.text || constraint.toString();
+ } else {
+ constraintText = String(constraint);
+ }
+ return - {constraintText}
;
+ })}
+
+
+ )}
+
+ {/* 变量 */}
+ {template.variables && template.variables.length > 0 && (
+
+
变量
+
+ {(template.variables || []).map((variable, index) => (
+
+
+ {variable.name}
+
+ {variable.type}
+
+
+
{variable.description}
+
+ ))}
+
+
+ )}
+
+ {/* 输出格式 */}
+
+
输出格式
+
{template.outputFormat}
+
+
+
+ {/* 侧边栏 */}
+
+ {/* 统计信息 */}
+
+
统计信息
+
+
+ 使用次数
+ {template.usageCount || 0}
+
+
+ 评分
+ {template.rating || 0}
+
+
+ 评分人数
+ {template.ratingCount || 0}
+
+
+ 状态
+
+ {template.isPublic ? '公开' : '私有'}
+
+
+
+
+
+ {/* 操作按钮 */}
+
+
操作
+
+
+
+
+
+
+
+
+
+
+ {/* 删除确认模态框 */}
+ {showDeleteModal && (
+
+
+
+ 确认删除
+
+
+ 您确定要删除这个模板吗?此操作无法撤销。
+
+
+
+
+
+
+
+ )}
+
+ {/* 分享模态框 */}
+ {showShareModal && (
+
+
+
+ 分享模板
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ )
+}
diff --git a/src/app/templates/manage/page.tsx b/src/app/templates/manage/page.tsx
new file mode 100644
index 0000000..4eaa047
--- /dev/null
+++ b/src/app/templates/manage/page.tsx
@@ -0,0 +1,444 @@
+'use client'
+
+import { useState, useEffect } from 'react'
+import { useRouter } from 'next/navigation'
+import { useAuth } from '@/contexts/AuthContext'
+import { ProtectedRoute } from '@/components/auth/ProtectedRoute'
+import { Plus, Edit, Trash2, Eye, Share2, Search, Filter, Copy } from 'lucide-react'
+import Link from 'next/link'
+
+interface Template {
+ id: string
+ title: string
+ description: string
+ category: string
+ isPublic: boolean
+ usageCount: number
+ rating: number
+ createdAt?: string
+ updatedAt?: string
+}
+
+export default function ManageTemplatesPage() {
+ const { user } = useAuth()
+ const router = useRouter()
+
+ const [templates, setTemplates] = useState([])
+ const [loading, setLoading] = useState(true)
+ const [searchQuery, setSearchQuery] = useState('')
+ const [selectedCategory, setSelectedCategory] = useState('all')
+ const [showDeleteModal, setShowDeleteModal] = useState(false)
+ const [templateToDelete, setTemplateToDelete] = useState(null)
+ const [showShareModal, setShowShareModal] = useState(false)
+ const [templateToShare, setTemplateToShare] = useState(null)
+ const [shareUrl, setShareUrl] = useState('')
+ const [selectedTemplates, setSelectedTemplates] = useState([])
+ const [showBulkActions, setShowBulkActions] = useState(false)
+
+ useEffect(() => {
+ if (user) {
+ fetchTemplates()
+ }
+ }, [user])
+
+ const fetchTemplates = async () => {
+ try {
+ const response = await fetch(`/api/templates?userId=${user?.id}`)
+ const data = await response.json()
+
+ if (data.success) {
+ setTemplates(data.data)
+ }
+ } catch (error) {
+ console.error('获取模板失败:', error)
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const handleDeleteTemplate = async (templateId: string) => {
+ try {
+ const response = await fetch(`/api/templates/${templateId}`, {
+ method: 'DELETE'
+ })
+
+ if (response.ok) {
+ setTemplates(templates.filter(t => t.id !== templateId))
+ setShowDeleteModal(false)
+ setTemplateToDelete(null)
+ }
+ } catch (error) {
+ console.error('删除模板失败:', error)
+ }
+ }
+
+ const handleShareTemplate = (template: Template) => {
+ const url = `${window.location.origin}/templates/${template.id}`
+ setShareUrl(url)
+ setTemplateToShare(template)
+ setShowShareModal(true)
+ }
+
+ const copyToClipboard = async (text: string) => {
+ try {
+ await navigator.clipboard.writeText(text)
+ // 可以添加一个提示
+ } catch (error) {
+ console.error('复制失败:', error)
+ }
+ }
+
+ const handleToggleTemplateSelection = (templateId: string) => {
+ setSelectedTemplates(prev =>
+ prev.includes(templateId)
+ ? prev.filter(id => id !== templateId)
+ : [...prev, templateId]
+ )
+ }
+
+ const handleBulkDelete = async () => {
+ if (selectedTemplates.length === 0) return
+
+ try {
+ const promises = selectedTemplates.map(templateId =>
+ fetch(`/api/templates/${templateId}`, { method: 'DELETE' })
+ )
+
+ await Promise.all(promises)
+ setTemplates(templates.filter(t => !selectedTemplates.includes(t.id)))
+ setSelectedTemplates([])
+ setShowBulkActions(false)
+ } catch (error) {
+ console.error('批量删除失败:', error)
+ }
+ }
+
+ const handleBulkShare = () => {
+ if (selectedTemplates.length === 0) return
+
+ const urls = selectedTemplates.map(templateId =>
+ `${window.location.origin}/templates/${templateId}`
+ ).join('\n')
+
+ setShareUrl(urls)
+ setShowShareModal(true)
+ }
+
+ const filteredTemplates = templates.filter(template => {
+ const matchesSearch = template.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ template.description.toLowerCase().includes(searchQuery.toLowerCase())
+ const matchesCategory = selectedCategory === 'all' || template.category === selectedCategory
+ return matchesSearch && matchesCategory
+ })
+
+ const getCategoryIcon = (category: string) => {
+ const icons: { [key: string]: string } = {
+ 'customer-service': '🎧',
+ 'content-creation': '✍️',
+ 'programming': '💻',
+ 'data-analysis': '📊',
+ 'marketing': '📈',
+ 'education': '📚',
+ 'creative-writing': '🖋️',
+ 'project-management': '📋'
+ }
+ return icons[category] || '📄'
+ }
+
+ const getCategoryName = (category: string) => {
+ const names: { [key: string]: string } = {
+ 'customer-service': '客服',
+ 'content-creation': '内容创作',
+ 'programming': '编程',
+ 'data-analysis': '数据分析',
+ 'marketing': '营销',
+ 'education': '教育',
+ 'creative-writing': '创意写作',
+ 'project-management': '项目管理'
+ }
+ return names[category] || category
+ }
+
+ if (loading) {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ {/* 头部 */}
+
+
+ {/* 搜索和筛选 */}
+
+
+
+
+ setSearchQuery(e.target.value)}
+ className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-blue-500 focus:border-blue-500"
+ />
+
+
+
+
+
+
+
+ {/* 批量操作 */}
+ {selectedTemplates.length > 0 && (
+
+
+
+ 已选择 {selectedTemplates.length} 个模板
+
+
+
+
+
+
+
+ )}
+
+
+ {/* 模板列表 */}
+
+ {filteredTemplates.map((template) => (
+
+
+
+
+
handleToggleTemplateSelection(template.id)}
+ className="mr-3 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
+ />
+
{getCategoryIcon(template.category)}
+
+
+ {template.title}
+
+
+ {getCategoryName(template.category)}
+
+
+
+
+
+
+
+
+
+
+
+
+ {template.description}
+
+
+
+
+ 使用 {template.usageCount || 0} 次
+ 评分 {template.rating || 0}
+
+
+ {template.isPublic ? (
+
+
+ 公开
+
+ ) : (
+
+ 私有
+
+ )}
+
+
+
+
+ ))}
+
+
+ {filteredTemplates.length === 0 && !loading && (
+
+
+
+
+
+ 没有找到模板
+
+
+ {searchQuery || selectedCategory !== 'all'
+ ? '尝试调整搜索条件或筛选器'
+ : '开始创建您的第一个模板'
+ }
+
+ {!searchQuery && selectedCategory === 'all' && (
+
+
+ 创建模板
+
+ )}
+
+ )}
+
+
+ {/* 删除确认模态框 */}
+ {showDeleteModal && (
+
+
+
+ 确认删除
+
+
+ 您确定要删除这个模板吗?此操作无法撤销。
+
+
+
+
+
+
+
+ )}
+
+ {/* 分享模态框 */}
+ {showShareModal && (
+
+
+
+ 分享模板
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+ )
+}
diff --git a/src/app/templates/page.tsx b/src/app/templates/page.tsx
new file mode 100644
index 0000000..f988a94
--- /dev/null
+++ b/src/app/templates/page.tsx
@@ -0,0 +1,360 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import Link from 'next/link';
+import {
+ Search,
+ Filter,
+ Grid,
+ List,
+ Star,
+ Users,
+ Clock,
+ ArrowUpDown
+} from 'lucide-react';
+import { CATEGORIES } from '@/lib/constants';
+import { getCategoryIcon, getCategoryColor, formatRelativeTime } from '@/lib/utils';
+import { cn } from '@/lib/utils';
+
+interface Template {
+ id: string;
+ title: string;
+ description: string;
+ category: string;
+ role: string;
+ task: string;
+ context: string;
+ constraints: Array<{id: string, text: string, category?: string} | string>;
+ variables: any[];
+ outputFormat: string;
+ authorId: string;
+ isPublic: boolean;
+ usageCount: number;
+ rating: number;
+ ratingCount: number;
+ createdAt?: string;
+ updatedAt?: string;
+}
+
+export default function TemplatesPage() {
+ const [templates, setTemplates] = useState([]);
+ const [filteredTemplates, setFilteredTemplates] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [selectedCategory, setSelectedCategory] = useState(null);
+ const [searchQuery, setSearchQuery] = useState('');
+ const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
+ const [sortBy, setSortBy] = useState<'popular' | 'latest' | 'rating'>('popular');
+
+ // 获取模板数据
+ useEffect(() => {
+ fetchTemplates();
+ }, []);
+
+ const fetchTemplates = async () => {
+ try {
+ const response = await fetch('/api/templates');
+ const data = await response.json();
+
+ if (data.success) {
+ setTemplates(data.data);
+ setFilteredTemplates(data.data);
+ }
+ } catch (error) {
+ console.error('获取模板失败:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // 过滤和搜索逻辑
+ useEffect(() => {
+ let filtered = templates;
+
+ if (selectedCategory) {
+ filtered = filtered.filter(t => t.category === selectedCategory);
+ }
+
+ if (searchQuery) {
+ filtered = filtered.filter(t =>
+ t.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ t.description.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+ }
+
+ setFilteredTemplates(filtered);
+ }, [templates, selectedCategory, searchQuery]);
+
+ const handleCategoryFilter = (category: string | null) => {
+ setSelectedCategory(category);
+ };
+
+ const handleSearchChange = (query: string) => {
+ setSearchQuery(query);
+ };
+
+ const sortedTemplates = [...filteredTemplates].sort((a, b) => {
+ switch (sortBy) {
+ case 'popular':
+ return (b.usageCount || 0) - (a.usageCount || 0);
+ case 'latest':
+ return new Date(b.createdAt || b.created_at).getTime() - new Date(a.createdAt || a.created_at).getTime();
+ case 'rating':
+ return (Number(b.rating) || 0) - (Number(a.rating) || 0);
+ default:
+ return 0;
+ }
+ });
+
+ if (loading) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+ {/* Header */}
+
+
+ 模板库
+
+
+ 发现和探索高质量的提示词模板
+
+
+
+ {/* Filters and Search */}
+
+
+ {/* Search */}
+
+
+
+ handleSearchChange(e.target.value)}
+ className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+ />
+
+
+
+ {/* Sort */}
+
+
+
+
+
+ {/* View Mode */}
+
+
+
+
+
+
+
+ {/* Categories */}
+
+
+
+ {CATEGORIES.map((category) => (
+
+ ))}
+
+
+
+ {/* Results */}
+
+
+ 找到 {sortedTemplates.length} 个模板
+
+
+
+ {/* Templates Grid/List */}
+ {viewMode === 'grid' ? (
+
+ {sortedTemplates.map((template) => (
+
+ ))}
+
+ ) : (
+
+ {sortedTemplates.map((template) => (
+
+ ))}
+
+ )}
+
+ {/* Empty State */}
+ {sortedTemplates.length === 0 && (
+
+
+
+
+
+ 没有找到匹配的模板
+
+
+ 尝试调整搜索条件或浏览其他分类
+
+
+ 创建新模板
+
+
+ )}
+
+
+ );
+}
+
+function TemplateCard({ template }: { template: any }) {
+ return (
+
+
+
+ {getCategoryIcon(template.category)}
+
+ {template.category}
+
+
+
+
+ {template.rating ? Number(template.rating).toFixed(1) : '0.0'}
+
+
+
+
+ {template.title}
+
+
+ {template.description}
+
+
+
+
+
+ {template.usageCount || 0} 次使用
+
+
+
+ {formatRelativeTime(template.createdAt || template.created_at)}
+
+
+
+ );
+}
+
+function TemplateListItem({ template }: { template: any }) {
+ return (
+
+
+
+ {getCategoryIcon(template.category)}
+
+
+
+
+
+
+ {template.title}
+
+
+ {template.category}
+
+
+
+
+ {template.rating ? Number(template.rating).toFixed(1) : '0.0'}
+
+
+
+
+ {template.description}
+
+
+
+
+
+ {template.usageCount || 0} 次使用
+
+
+
+ {formatRelativeTime(template.createdAt || template.created_at)}
+
+
+ 作者: {template.author}
+
+
+
+
+
+ );
+}
diff --git a/src/components/auth/ProtectedRoute.tsx b/src/components/auth/ProtectedRoute.tsx
new file mode 100644
index 0000000..5b4f6c1
--- /dev/null
+++ b/src/components/auth/ProtectedRoute.tsx
@@ -0,0 +1,37 @@
+'use client'
+
+import { useEffect } from 'react'
+import { useRouter } from 'next/navigation'
+import { useAuth } from '@/contexts/AuthContext'
+
+interface ProtectedRouteProps {
+ children: React.ReactNode
+}
+
+export function ProtectedRoute({ children }: ProtectedRouteProps) {
+ const { user, loading } = useAuth()
+ const router = useRouter()
+
+ useEffect(() => {
+ if (!loading && !user) {
+ router.push('/auth/login')
+ }
+ }, [user, loading, router])
+
+ if (loading) {
+ return (
+
+ )
+ }
+
+ if (!user) {
+ return null
+ }
+
+ return <>{children}>
+}
diff --git a/src/components/deploy/deployment-config.tsx b/src/components/deploy/deployment-config.tsx
new file mode 100644
index 0000000..a5fef49
--- /dev/null
+++ b/src/components/deploy/deployment-config.tsx
@@ -0,0 +1,289 @@
+'use client';
+
+import { useState } from 'react';
+import { Settings, Save, Loader2, Check, X } from 'lucide-react';
+
+interface DeploymentConfig {
+ id: string;
+ name: string;
+ platform: string;
+ language: string;
+ framework: string;
+ database: string;
+ hosting: string;
+ monitoring: boolean;
+ security: boolean;
+ scaling: boolean;
+ createdAt: string;
+}
+
+interface DeploymentConfigProps {
+ config: DeploymentConfig;
+ onSave: (config: DeploymentConfig) => void;
+ onDelete: (id: string) => void;
+}
+
+export function DeploymentConfigManager({ config, onSave, onDelete }: DeploymentConfigProps) {
+ const [isEditing, setIsEditing] = useState(false);
+ const [isSaving, setIsSaving] = useState(false);
+ const [editedConfig, setEditedConfig] = useState(config);
+
+ const handleSave = async () => {
+ setIsSaving(true);
+ try {
+ await onSave(editedConfig);
+ setIsEditing(false);
+ } catch (error) {
+ console.error('保存配置失败:', error);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ const handleCancel = () => {
+ setEditedConfig(config);
+ setIsEditing(false);
+ };
+
+ const updateConfig = (key: keyof DeploymentConfig, value: any) => {
+ setEditedConfig(prev => ({
+ ...prev,
+ [key]: value
+ }));
+ };
+
+ if (isEditing) {
+ return (
+
+
+
+ 编辑部署配置
+
+
+
+
+
+
+
+
+
+
+ updateConfig('name', e.target.value)}
+ className="w-full input"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+ {config.name}
+
+
+ 创建于 {new Date(config.createdAt).toLocaleDateString()}
+
+
+
+
+
+
+
+
+
+
+ AI 平台:
+ {config.platform}
+
+
+ 编程语言:
+ {config.language}
+
+
+ 框架:
+ {config.framework}
+
+
+ 数据库:
+ {config.database}
+
+
+ 托管平台:
+ {config.hosting}
+
+
+
+
+ {config.monitoring && (
+
+ 监控
+
+ )}
+ {config.security && (
+
+ 安全
+
+ )}
+ {config.scaling && (
+
+ 扩缩容
+
+ )}
+
+
+ );
+}
diff --git a/src/components/deploy/deployment-history.tsx b/src/components/deploy/deployment-history.tsx
new file mode 100644
index 0000000..18ccdee
--- /dev/null
+++ b/src/components/deploy/deployment-history.tsx
@@ -0,0 +1,236 @@
+'use client';
+
+import { useState } from 'react';
+import { Clock, ExternalLink, Download, Trash2, Eye, CheckCircle, XCircle, AlertCircle } from 'lucide-react';
+
+interface DeploymentRecord {
+ id: string;
+ templateName: string;
+ platform: string;
+ language: string;
+ framework: string;
+ hosting: string;
+ status: 'success' | 'failed' | 'pending' | 'running';
+ deployedAt: string;
+ deployedUrl?: string;
+ logs?: string;
+ error?: string;
+}
+
+interface DeploymentHistoryProps {
+ deployments: DeploymentRecord[];
+ onViewLogs: (id: string) => void;
+ onDelete: (id: string) => void;
+ onRedeploy: (id: string) => void;
+}
+
+export function DeploymentHistory({ deployments, onViewLogs, onDelete, onRedeploy }: DeploymentHistoryProps) {
+ const [selectedStatus, setSelectedStatus] = useState('all');
+
+ const filteredDeployments = selectedStatus === 'all'
+ ? deployments
+ : deployments.filter(d => d.status === selectedStatus);
+
+ const getStatusIcon = (status: string) => {
+ switch (status) {
+ case 'success':
+ return ;
+ case 'failed':
+ return ;
+ case 'pending':
+ return ;
+ case 'running':
+ return ;
+ default:
+ return ;
+ }
+ };
+
+ const getStatusText = (status: string) => {
+ switch (status) {
+ case 'success':
+ return '部署成功';
+ case 'failed':
+ return '部署失败';
+ case 'pending':
+ return '等待部署';
+ case 'running':
+ return '部署中';
+ default:
+ return '未知状态';
+ }
+ };
+
+ const getStatusColor = (status: string) => {
+ switch (status) {
+ case 'success':
+ return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300';
+ case 'failed':
+ return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300';
+ case 'pending':
+ return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300';
+ case 'running':
+ return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300';
+ default:
+ return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300';
+ }
+ };
+
+ return (
+
+
+
+ 部署历史
+
+
+
+
+
+
+ {filteredDeployments.length === 0 ? (
+
+
+
暂无部署记录
+
开始部署您的第一个服务吧
+
+ ) : (
+
+ {filteredDeployments.map((deployment) => (
+
+
+
+ {getStatusIcon(deployment.status)}
+
+
+ {deployment.templateName}
+
+
+ {deployment.platform} • {deployment.language} • {deployment.framework}
+
+
+
+
+
+ {getStatusText(deployment.status)}
+
+
+ {new Date(deployment.deployedAt).toLocaleString()}
+
+
+
+
+
+
+ 平台:
+ {deployment.platform}
+
+
+ 语言:
+ {deployment.language}
+
+
+ 框架:
+ {deployment.framework}
+
+
+ 托管:
+ {deployment.hosting}
+
+
+
+ {deployment.error && (
+
+
+ 错误: {deployment.error}
+
+
+ )}
+
+
+
+ {deployment.deployedUrl && (
+
+
+ 访问服务
+
+ )}
+
+
+
+
+
+
+
+
+ ))}
+
+ )}
+
+ {/* 统计信息 */}
+
+
+
+
+ {deployments.filter(d => d.status === 'success').length}
+
+
部署成功
+
+
+
+ {deployments.filter(d => d.status === 'failed').length}
+
+
部署失败
+
+
+
+ {deployments.filter(d => d.status === 'running').length}
+
+
部署中
+
+
+
+ {deployments.length}
+
+
总部署数
+
+
+
+
+ );
+}
diff --git a/src/components/editor/deploy-panel.tsx b/src/components/editor/deploy-panel.tsx
new file mode 100644
index 0000000..a6f6357
--- /dev/null
+++ b/src/components/editor/deploy-panel.tsx
@@ -0,0 +1,933 @@
+'use client';
+
+import { useState } from 'react';
+import { Download, Copy, Check, Code, FileText, Settings, Play, Save } from 'lucide-react';
+import { PromptTemplate } from '@/types/prompt';
+import { CODE_PLATFORMS, PROGRAMMING_LANGUAGES } from '@/lib/constants';
+import { copyToClipboard } from '@/lib/utils';
+
+interface DeployPanelProps {
+ template: PromptTemplate;
+}
+
+interface DeploymentConfig {
+ platform: string;
+ language: string;
+ framework: string;
+ model: string;
+ temperature: number;
+ maxTokens: number;
+ includeSystemRole: boolean;
+ includeErrorHandling: boolean;
+ includeLogging: boolean;
+ includeTypeHints: boolean;
+}
+
+export function DeployPanel({ template }: DeployPanelProps) {
+ const [config, setConfig] = useState({
+ platform: 'openai',
+ language: 'python',
+ framework: 'standard',
+ model: 'gpt-4', // 默认使用OpenAI的模型
+ temperature: 0.7,
+ maxTokens: 2000,
+ includeSystemRole: true,
+ includeErrorHandling: true,
+ includeLogging: true,
+ includeTypeHints: true
+ });
+ const [copied, setCopied] = useState(false);
+ const [showAdvanced, setShowAdvanced] = useState(false);
+
+ // 当平台改变时,自动更新模型为对应平台的默认模型
+ const handlePlatformChange = (newPlatform: string) => {
+ // 临时创建一个配置来获取新平台的默认模型
+ const tempConfig = { ...config, platform: newPlatform };
+ const getTempPlatformConfig = () => {
+ switch (newPlatform) {
+ case 'openai':
+ return {
+ apiKey: 'your-openai-api-key-here',
+ baseUrl: 'https://api.openai.com/v1',
+ models: ['gpt-4', 'gpt-3.5-turbo', 'gpt-4-turbo'],
+ defaultModel: 'gpt-4'
+ };
+ case 'anthropic':
+ return {
+ apiKey: 'your-anthropic-api-key-here',
+ baseUrl: 'https://api.anthropic.com',
+ models: ['claude-3-sonnet-20240229', 'claude-3-haiku-20240307', 'claude-3-opus-20240229'],
+ defaultModel: 'claude-3-sonnet-20240229'
+ };
+ case 'deepseek':
+ return {
+ apiKey: 'sk-fdf7cc1c73504e628ec0119b7e11b8cc',
+ baseUrl: 'https://api.deepseek.com/v1',
+ models: ['deepseek-chat', 'deepseek-coder', 'deepseek-vision'],
+ defaultModel: 'deepseek-chat'
+ };
+ default:
+ return {
+ apiKey: 'your-api-key-here',
+ baseUrl: 'https://api.example.com',
+ models: ['default-model'],
+ defaultModel: 'default-model'
+ };
+ }
+ };
+
+ const platformConfig = getTempPlatformConfig();
+ setConfig({
+ ...config,
+ platform: newPlatform,
+ model: platformConfig.defaultModel
+ });
+ };
+
+ // 获取平台特定的配置
+ const getPlatformConfig = () => {
+ switch (config.platform) {
+ case 'openai':
+ return {
+ apiKey: 'your-openai-api-key-here',
+ baseUrl: 'https://api.openai.com/v1',
+ models: ['gpt-4', 'gpt-3.5-turbo', 'gpt-4-turbo'],
+ defaultModel: 'gpt-4'
+ };
+ case 'anthropic':
+ return {
+ apiKey: 'your-anthropic-api-key-here',
+ baseUrl: 'https://api.anthropic.com',
+ models: ['claude-3-sonnet-20240229', 'claude-3-haiku-20240307', 'claude-3-opus-20240229'],
+ defaultModel: 'claude-3-sonnet-20240229'
+ };
+ case 'deepseek':
+ return {
+ apiKey: 'sk-fdf7cc1c73504e628ec0119b7e11b8cc',
+ baseUrl: 'https://api.deepseek.com/v1',
+ models: ['deepseek-chat', 'deepseek-coder', 'deepseek-vision'],
+ defaultModel: 'deepseek-chat'
+ };
+ default:
+ return {
+ apiKey: 'your-api-key-here',
+ baseUrl: 'https://api.example.com',
+ models: ['default-model'],
+ defaultModel: 'default-model'
+ };
+ }
+ };
+
+ // 生成系统角色提示词
+ const generateSystemPrompt = () => {
+ const role = template.role || 'AI助手';
+ const context = template.context || '';
+ const constraints = (template.constraints || []).map(c => c.text || c).join('\n');
+
+ let systemPrompt = `你是一位专业的${role}。`;
+
+ if (context) {
+ systemPrompt += `\n\n背景信息:${context}`;
+ }
+
+ if (constraints) {
+ systemPrompt += `\n\n约束条件:\n${constraints}`;
+ }
+
+ if (template.outputFormat) {
+ systemPrompt += `\n\n输出格式:${template.outputFormat}`;
+ }
+
+ return systemPrompt;
+ };
+
+ // 生成用户提示词
+ const generateUserPrompt = () => {
+ const task = template.task || '';
+ const variables = (template.variables || []).map(v => `{{${v.name}}}`).join(', ');
+
+ let userPrompt = task;
+
+ if (variables) {
+ userPrompt += `\n\n请使用以下变量:${variables}`;
+ }
+
+ return userPrompt;
+ };
+
+ // 生成Python代码
+ const generatePythonCode = () => {
+ const platformConfig = getPlatformConfig();
+ const variables = (template.variables || []).map(v => v.name).join(', ');
+ const systemPrompt = generateSystemPrompt();
+ const userPrompt = generateUserPrompt();
+
+ let code = '';
+
+ // 导入语句
+ if (config.platform === 'openai') {
+ code += `import openai
+import json
+import logging
+from typing import Dict, Any, Optional
+`;
+ } else if (config.platform === 'anthropic') {
+ code += `import anthropic
+import json
+import logging
+from typing import Dict, Any, Optional
+`;
+ } else if (config.platform === 'deepseek') {
+ code += `import requests
+import json
+import logging
+from typing import Dict, Any, Optional
+`;
+ }
+
+ if (config.includeLogging) {
+ code += `
+# 配置日志
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+`;
+ }
+
+ // 配置部分
+ code += `
+# 配置API
+${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY = "${platformConfig.apiKey}"
+`;
+
+ if (config.platform === 'openai') {
+ code += `openai.api_key = ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY
+`;
+ } else if (config.platform === 'anthropic') {
+ code += `client = anthropic.Anthropic(api_key=${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY)
+`;
+ }
+
+ // 主函数
+ code += `
+def generate_with_prompt(${variables}${config.includeTypeHints ? ': str' : ''}) -> str:
+ """
+ 使用AI模型生成响应
+
+ Args:
+ ${(template.variables || []).map(v => `${v.name}: ${v.description || '变量'}`).join('\n ')}
+
+ Returns:
+ str: AI生成的响应
+ """
+ try:
+ ${config.includeLogging ? 'logger.info("开始生成AI响应")' : ''}
+
+ # 构建提示词
+ system_prompt = """${systemPrompt}"""
+
+ user_prompt = f"""${userPrompt}"""
+
+ # 构建消息
+ messages = []
+ ${config.includeSystemRole ? `messages.append({"role": "system", "content": system_prompt})` : ''}
+ messages.append({"role": "user", "content": user_prompt})
+
+ ${config.includeLogging ? 'logger.info(f"发送请求到 {config.platform} API")' : ''}
+
+ # 发送请求
+`;
+
+ if (config.platform === 'openai') {
+ code += ` response = openai.ChatCompletion.create(
+ model="${config.model}",
+ messages=messages,
+ temperature=${config.temperature},
+ max_tokens=${config.maxTokens}
+ )
+
+ result = response.choices[0].message.content
+`;
+ } else if (config.platform === 'anthropic') {
+ code += ` response = client.messages.create(
+ model="${config.model}",
+ messages=messages,
+ temperature=${config.temperature},
+ max_tokens=${config.maxTokens}
+ )
+
+ result = response.content[0].text
+`;
+ } else if (config.platform === 'deepseek') {
+ code += ` headers = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY}"
+ }
+
+ data = {
+ "model": "${config.model}",
+ "messages": messages,
+ "temperature": ${config.temperature},
+ "max_tokens": ${config.maxTokens}
+ }
+
+ response = requests.post("${platformConfig.baseUrl}/chat/completions", headers=headers, json=data)
+ response.raise_for_status()
+
+ result = response.json()["choices"][0]["message"]["content"]
+`;
+ }
+
+ code += `
+ ${config.includeLogging ? 'logger.info("AI响应生成成功")' : ''}
+ return result
+
+ except Exception as e:
+ ${config.includeErrorHandling ? `logger.error(f"生成AI响应时出错: {e}")
+ raise Exception(f"AI响应生成失败: {e}")` : 'raise e'}
+`;
+
+ // 使用示例
+ code += `
+
+# 使用示例
+if __name__ == "__main__":
+ try:
+ # 示例变量值
+ ${(template.variables || []).map(v => `${v.name} = "示例${v.name}"`).join('\n ')}
+
+ result = generate_with_prompt(${(template.variables || []).map(v => v.name).join(', ')})
+ print("AI响应:")
+ print(result)
+
+ except Exception as e:
+ print(f"错误: {e}")
+`;
+
+ return code;
+ };
+
+ // 生成JavaScript代码
+ const generateJavaScriptCode = () => {
+ const platformConfig = getPlatformConfig();
+ const variables = (template.variables || []).map(v => v.name).join(', ');
+ const systemPrompt = generateSystemPrompt();
+ const userPrompt = generateUserPrompt();
+
+ let code = '';
+
+ // 导入语句
+ if (config.platform === 'openai') {
+ code += `// 安装: npm install openai
+import OpenAI from 'openai';
+`;
+ } else if (config.platform === 'anthropic') {
+ code += `// 安装: npm install @anthropic-ai/sdk
+import Anthropic from '@anthropic-ai/sdk';
+`;
+ } else if (config.platform === 'deepseek') {
+ code += `// 安装: npm install node-fetch
+import fetch from 'node-fetch';
+`;
+ }
+
+ // 配置部分
+ code += `
+// 配置API
+const ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY = '${platformConfig.apiKey}';
+`;
+
+ if (config.platform === 'openai') {
+ code += `const openai = new OpenAI({
+ apiKey: ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY,
+});
+`;
+ } else if (config.platform === 'anthropic') {
+ code += `const anthropic = new Anthropic({
+ apiKey: ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY,
+});
+`;
+ }
+
+ // 主函数
+ code += `
+/**
+ * 使用AI模型生成响应
+ * @param {string} ${variables} - ${(template.variables || []).map(v => v.description || v.name).join(', ')}
+ * @returns {Promise} AI生成的响应
+ */
+async function generateWithPrompt(${variables}) {
+ try {
+ console.log('开始生成AI响应');
+
+ // 构建提示词
+ const systemPrompt = \`${systemPrompt}\`;
+ const userPrompt = \`${userPrompt}\`;
+
+ // 构建消息
+ const messages = [];
+ ${config.includeSystemRole ? 'messages.push({ role: "system", content: systemPrompt });' : ''}
+ messages.push({ role: "user", content: userPrompt });
+
+ console.log(\`发送请求到 ${config.platform} API\`);
+
+ // 发送请求
+`;
+
+ if (config.platform === 'openai') {
+ code += ` const response = await openai.chat.completions.create({
+ model: '${config.model}',
+ messages: messages,
+ temperature: ${config.temperature},
+ max_tokens: ${config.maxTokens},
+ });
+
+ const result = response.choices[0].message.content;
+`;
+ } else if (config.platform === 'anthropic') {
+ code += ` const response = await anthropic.messages.create({
+ model: '${config.model}',
+ messages: messages,
+ temperature: ${config.temperature},
+ max_tokens: ${config.maxTokens},
+ });
+
+ const result = response.content[0].text;
+`;
+ } else if (config.platform === 'deepseek') {
+ code += ` const response = await fetch('${platformConfig.baseUrl}/chat/completions', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': \`Bearer \${${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY}\`
+ },
+ body: JSON.stringify({
+ model: '${config.model}',
+ messages: messages,
+ temperature: ${config.temperature},
+ max_tokens: ${config.maxTokens}
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(\`HTTP error! status: \${response.status}\`);
+ }
+
+ const data = await response.json();
+ const result = data.choices[0].message.content;
+`;
+ }
+
+ code += `
+ console.log('AI响应生成成功');
+ return result;
+
+ } catch (error) {
+ console.error('生成AI响应时出错:', error);
+ throw new Error(\`AI响应生成失败: \${error.message}\`);
+ }
+}
+
+// 使用示例
+async function main() {
+ try {
+ // 示例变量值
+ ${(template.variables || []).map(v => `const ${v.name} = "示例${v.name}";`).join('\n ')}
+
+ const result = await generateWithPrompt(${(template.variables || []).map(v => v.name).join(', ')});
+ console.log('AI响应:');
+ console.log(result);
+
+ } catch (error) {
+ console.error('错误:', error);
+ }
+}
+
+// 运行示例
+main();
+`;
+
+ return code;
+ };
+
+ // 生成TypeScript代码
+ const generateTypeScriptCode = () => {
+ const platformConfig = getPlatformConfig();
+ const variables = (template.variables || []).map(v => v.name).join(', ');
+ const systemPrompt = generateSystemPrompt();
+ const userPrompt = generateUserPrompt();
+
+ let code = '';
+
+ // 类型定义
+ code += `// 类型定义
+interface AIMessage {
+ role: 'system' | 'user' | 'assistant';
+ content: string;
+}
+
+interface AIResponse {
+ choices: Array<{
+ message: {
+ content: string;
+ };
+ }>;
+}
+
+`;
+
+ // 导入语句
+ if (config.platform === 'openai') {
+ code += `// 安装: npm install openai
+import OpenAI from 'openai';
+`;
+ } else if (config.platform === 'anthropic') {
+ code += `// 安装: npm install @anthropic-ai/sdk
+import Anthropic from '@anthropic-ai/sdk';
+`;
+ } else if (config.platform === 'deepseek') {
+ code += `// 安装: npm install node-fetch
+import fetch from 'node-fetch';
+`;
+ }
+
+ // 配置部分
+ code += `
+// 配置API
+const ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY: string = '${platformConfig.apiKey}';
+`;
+
+ if (config.platform === 'openai') {
+ code += `const openai = new OpenAI({
+ apiKey: ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY,
+});
+`;
+ } else if (config.platform === 'anthropic') {
+ code += `const anthropic = new Anthropic({
+ apiKey: ${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY,
+});
+`;
+ }
+
+ // 主函数
+ code += `
+/**
+ * 使用AI模型生成响应
+ * @param ${(template.variables || []).map(v => `${v.name}: string`).join(', ')} - ${(template.variables || []).map(v => v.description || v.name).join(', ')}
+ * @returns Promise AI生成的响应
+ */
+async function generateWithPrompt(${(template.variables || []).map(v => `${v.name}: string`).join(', ')}): Promise {
+ try {
+ console.log('开始生成AI响应');
+
+ // 构建提示词
+ const systemPrompt: string = \`${systemPrompt}\`;
+ const userPrompt: string = \`${userPrompt}\`;
+
+ // 构建消息
+ const messages: AIMessage[] = [];
+ ${config.includeSystemRole ? 'messages.push({ role: "system", content: systemPrompt });' : ''}
+ messages.push({ role: "user", content: userPrompt });
+
+ console.log(\`发送请求到 ${config.platform} API\`);
+
+ // 发送请求
+`;
+
+ if (config.platform === 'openai') {
+ code += ` const response = await openai.chat.completions.create({
+ model: '${config.model}',
+ messages: messages,
+ temperature: ${config.temperature},
+ max_tokens: ${config.maxTokens},
+ });
+
+ const result: string = response.choices[0].message.content || '';
+`;
+ } else if (config.platform === 'anthropic') {
+ code += ` const response = await anthropic.messages.create({
+ model: '${config.model}',
+ messages: messages,
+ temperature: ${config.temperature},
+ max_tokens: ${config.maxTokens},
+ });
+
+ const result: string = response.content[0].text;
+`;
+ } else if (config.platform === 'deepseek') {
+ code += ` const response = await fetch('${platformConfig.baseUrl}/chat/completions', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': \`Bearer \${${platformConfig.apiKey.split('-')[0].toUpperCase()}_API_KEY}\`
+ },
+ body: JSON.stringify({
+ model: '${config.model}',
+ messages: messages,
+ temperature: ${config.temperature},
+ max_tokens: ${config.maxTokens}
+ })
+ });
+
+ if (!response.ok) {
+ throw new Error(\`HTTP error! status: \${response.status}\`);
+ }
+
+ const data: AIResponse = await response.json();
+ const result: string = data.choices[0].message.content;
+`;
+ }
+
+ code += `
+ console.log('AI响应生成成功');
+ return result;
+
+ } catch (error) {
+ console.error('生成AI响应时出错:', error);
+ throw new Error(\`AI响应生成失败: \${error instanceof Error ? error.message : '未知错误'}\`);
+ }
+}
+
+// 使用示例
+async function main(): Promise {
+ try {
+ // 示例变量值
+ ${(template.variables || []).map(v => `const ${v.name}: string = "示例${v.name}";`).join('\n ')}
+
+ const result: string = await generateWithPrompt(${(template.variables || []).map(v => v.name).join(', ')});
+ console.log('AI响应:');
+ console.log(result);
+
+ } catch (error) {
+ console.error('错误:', error);
+ }
+}
+
+// 运行示例
+main();
+`;
+
+ return code;
+ };
+
+ // 生成cURL命令
+ const generateCurlCode = () => {
+ const platformConfig = getPlatformConfig();
+ const systemPrompt = generateSystemPrompt();
+ const userPrompt = generateUserPrompt();
+
+ let code = '';
+
+ if (config.includeSystemRole) {
+ code += `# 使用system角色的完整请求
+curl ${platformConfig.baseUrl}/chat/completions \\
+ -H "Content-Type: application/json" \\
+ -H "Authorization: Bearer ${platformConfig.apiKey}" \\
+ -d '{
+ "model": "${config.model}",
+ "messages": [
+ {
+ "role": "system",
+ "content": "${systemPrompt.replace(/"/g, '\\"')}"
+ },
+ {
+ "role": "user",
+ "content": "${userPrompt.replace(/"/g, '\\"')}"
+ }
+ ],
+ "temperature": ${config.temperature},
+ "max_tokens": ${config.maxTokens}
+ }'`;
+ } else {
+ code += `# 仅使用user角色的简化请求
+curl ${platformConfig.baseUrl}/chat/completions \\
+ -H "Content-Type: application/json" \\
+ -H "Authorization: Bearer ${platformConfig.apiKey}" \\
+ -d '{
+ "model": "${config.model}",
+ "messages": [
+ {
+ "role": "user",
+ "content": "${userPrompt.replace(/"/g, '\\"')}"
+ }
+ ],
+ "temperature": ${config.temperature},
+ "max_tokens": ${config.maxTokens}
+ }'`;
+ }
+
+ return code;
+ };
+
+ const generateCode = () => {
+ switch (config.language) {
+ case 'python':
+ return generatePythonCode();
+ case 'javascript':
+ return generateJavaScriptCode();
+ case 'typescript':
+ return generateTypeScriptCode();
+ case 'curl':
+ return generateCurlCode();
+ default:
+ return '// 代码生成中...';
+ }
+ };
+
+ const handleCopy = async () => {
+ const code = generateCode();
+ await copyToClipboard(code);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ };
+
+ const handleDownload = () => {
+ const code = generateCode();
+ const blob = new Blob([code], { type: 'text/plain' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `prompt-${template.title || 'template'}.${config.language === 'curl' ? 'sh' : config.language}`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+ };
+
+ return (
+
+ {/* Header */}
+
+
+
+
+
+
+ 代码生成与部署
+
+
+ 生成可直接使用的代码片段
+
+
+
+
+
+
+
+
+
+ {/* Configuration */}
+
+
+ {/* Platform */}
+
+
+
+
+
+ {/* Language */}
+
+
+
+
+
+ {/* Model */}
+
+
+
+
+
+ {/* Framework */}
+
+
+
+
+
+
+ {/* Advanced Options */}
+ {showAdvanced && (
+
+ )}
+
+
+ {/* Code Preview */}
+
+
+
+
+
+
+ 生成的代码
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/editor/prompt-editor.tsx b/src/components/editor/prompt-editor.tsx
new file mode 100644
index 0000000..72aabea
--- /dev/null
+++ b/src/components/editor/prompt-editor.tsx
@@ -0,0 +1,286 @@
+'use client';
+
+import { useState } from 'react';
+import { Plus, Trash2, Copy, Check } from 'lucide-react';
+import { PromptTemplate, PromptConstraint } from '@/types/prompt';
+import { OUTPUT_FORMATS, CONSTRAINT_CATEGORIES } from '@/lib/constants';
+import { copyToClipboard } from '@/lib/utils';
+
+interface PromptEditorProps {
+ template: PromptTemplate;
+ onUpdate: (updates: Partial) => void;
+ onAddVariable: () => void;
+ onAddConstraint: () => void;
+}
+
+export function PromptEditor({ template, onUpdate, onAddVariable, onAddConstraint }: PromptEditorProps) {
+ const [copiedField, setCopiedField] = useState(null);
+
+ const handleCopy = async (text: string, field: string) => {
+ await copyToClipboard(text);
+ setCopiedField(field);
+ setTimeout(() => setCopiedField(null), 2000);
+ };
+
+ const handleRemoveConstraint = (id: string) => {
+ onUpdate({
+ constraints: (template.constraints || []).filter(c => c.id !== id)
+ });
+ };
+
+ const handleUpdateConstraint = (id: string, updates: Partial) => {
+ onUpdate({
+ constraints: (template.constraints || []).map(c =>
+ c.id === id ? { ...c, ...updates } : c
+ )
+ });
+ };
+
+ return (
+
+ {/* Main Editor */}
+
+
+ {/* Basic Info */}
+
+
+ 基本信息
+
+
+
+
+
+
+
+
+ onUpdate({ tags: e.target.value.split(',').map(t => t.trim()).filter(Boolean) })}
+ placeholder="输入标签,用逗号分隔..."
+ className="input"
+ />
+
+
+
+
+ {/* Role */}
+
+
+
+ 角色定义
+
+
+
+
+
+ {/* Task */}
+
+
+
+ 核心任务
+
+
+
+
+
+ {/* Context */}
+
+
+
+ 背景信息(可选)
+
+
+
+
+
+ {/* Constraints */}
+
+
+
+ 约束条件
+
+
+
+
+ {(template.constraints || []).map((constraint, index) => (
+
+
+
+
+
+
+
+
+ ))}
+ {(template.constraints || []).length === 0 && (
+
+
还没有添加约束条件
+
+
+ )}
+
+
+
+ {/* Output Format */}
+
+
+ 输出格式
+
+
+
+
+
+
+ {/* Sidebar */}
+
+
+ {/* Variables */}
+
+
+
+ {(template.variables || []).map((variable) => (
+
+
+ {`{{${variable.name}}}`}
+
+
+ {variable.type}
+
+
+ ))}
+ {(template.variables || []).length === 0 && (
+
+ 还没有定义变量
+
+ )}
+
+
+
+ {/* Quick Actions */}
+
+
+ 快速操作
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/editor/prompt-preview.tsx b/src/components/editor/prompt-preview.tsx
new file mode 100644
index 0000000..9dd0af4
--- /dev/null
+++ b/src/components/editor/prompt-preview.tsx
@@ -0,0 +1,239 @@
+'use client';
+
+import { useState } from 'react';
+import { Copy, Check, Eye, EyeOff } from 'lucide-react';
+import { PromptTemplate } from '@/types/prompt';
+import { renderPrompt, copyToClipboard } from '@/lib/utils';
+
+interface PromptPreviewProps {
+ template: PromptTemplate;
+}
+
+export function PromptPreview({ template }: PromptPreviewProps) {
+ const [variables, setVariables] = useState>({});
+ const [copied, setCopied] = useState(false);
+ const [showRaw, setShowRaw] = useState(false);
+
+ // Initialize variables with default values
+ useState(() => {
+ const initialVars: Record = {};
+ template.variables.forEach(variable => {
+ if (variable.defaultValue !== undefined) {
+ initialVars[variable.name] = variable.defaultValue;
+ } else {
+ switch (variable.type) {
+ case 'text':
+ initialVars[variable.name] = '';
+ break;
+ case 'number':
+ initialVars[variable.name] = 0;
+ break;
+ case 'boolean':
+ initialVars[variable.name] = false;
+ break;
+ case 'select':
+ initialVars[variable.name] = variable.options?.[0] || '';
+ break;
+ }
+ }
+ });
+ setVariables(initialVars);
+ });
+
+ const handleVariableChange = (name: string, value: any) => {
+ setVariables(prev => ({ ...prev, [name]: value }));
+ };
+
+ const handleCopy = async () => {
+ const renderedPrompt = renderPrompt(template, variables);
+ await copyToClipboard(renderedPrompt);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ };
+
+ const renderedPrompt = renderPrompt(template, variables);
+
+ return (
+
+ {/* Header */}
+
+
+
+ 提示词预览
+
+
+
+
+
+
+
+
+
+ {/* Variables Panel */}
+
+
+ 变量设置
+
+
+ {(template.variables || []).map((variable) => (
+
+
+ {variable.description && (
+
+ {variable.description}
+
+ )}
+
+ {variable.type === 'text' && (
+
handleVariableChange(variable.name, e.target.value)}
+ placeholder={`输入 ${variable.name}...`}
+ className="input"
+ />
+ )}
+
+ {variable.type === 'number' && (
+
handleVariableChange(variable.name, Number(e.target.value))}
+ placeholder={`输入 ${variable.name}...`}
+ className="input"
+ />
+ )}
+
+ {variable.type === 'boolean' && (
+
+ )}
+
+ {variable.type === 'select' && variable.options && (
+
+ )}
+
+ ))}
+
+ {template.variables.length === 0 && (
+
+ )}
+
+
+
+ {/* Preview Panel */}
+
+ {showRaw ? (
+
+
+
+ 原始模板结构
+
+
+
+
角色
+
+ {template.role || '未设置'}
+
+
+
+
+
任务
+
+ {template.task || '未设置'}
+
+
+
+ {template.context && (
+
+
背景
+
+ {template.context}
+
+
+ )}
+
+ {template.constraints && template.constraints.length > 0 && (
+
+
约束
+
+ {template.constraints.map((constraint, index) => {
+ // 处理约束条件的不同格式
+ let constraintText = '';
+ let constraintId = '';
+
+ if (typeof constraint === 'string') {
+ constraintText = constraint;
+ constraintId = `constraint_${index}`;
+ } else if (constraint && typeof constraint === 'object') {
+ constraintText = constraint.text || constraint.toString();
+ constraintId = constraint.id || `constraint_${index}`;
+ } else {
+ constraintText = String(constraint);
+ constraintId = `constraint_${index}`;
+ }
+
+ return (
+
+ {constraintText}
+
+ );
+ })}
+
+
+ )}
+
+
+
+ ) : (
+
+ )}
+
+
+
+ );
+}
diff --git a/src/components/editor/test-panel.tsx b/src/components/editor/test-panel.tsx
new file mode 100644
index 0000000..09b19b5
--- /dev/null
+++ b/src/components/editor/test-panel.tsx
@@ -0,0 +1,275 @@
+'use client';
+
+import { useState } from 'react';
+import { Play, Settings, Download, Upload } from 'lucide-react';
+import { PromptTemplate } from '@/types/prompt';
+import { renderPrompt, validateVariables } from '@/lib/utils';
+import { AI_MODELS } from '@/lib/constants';
+
+interface TestPanelProps {
+ template: PromptTemplate;
+}
+
+export function TestPanel({ template }: TestPanelProps) {
+ const [variables, setVariables] = useState>({});
+ const [model, setModel] = useState('gpt-4');
+ const [temperature, setTemperature] = useState(0.7);
+ const [maxTokens, setMaxTokens] = useState(1000);
+ const [result, setResult] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+ const [validationErrors, setValidationErrors] = useState([]);
+
+ const handleVariableChange = (name: string, value: any) => {
+ setVariables(prev => ({ ...prev, [name]: value }));
+ };
+
+ const handleTest = async () => {
+ // Validate variables
+ const validation = validateVariables(template, variables);
+ setValidationErrors(validation.errors);
+
+ if (!validation.valid) {
+ return;
+ }
+
+ setIsLoading(true);
+ setResult('');
+
+ try {
+ const renderedPrompt = renderPrompt(template, variables);
+
+ // 调用真实的 API
+ const response = await fetch('/api/test', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ prompt: renderedPrompt,
+ model: model,
+ temperature: temperature,
+ maxTokens: maxTokens,
+ variables: variables
+ }),
+ });
+
+ const data = await response.json();
+
+ if (data.success) {
+ setResult(`✅ ${data.data.provider} ${data.data.model} 响应结果:
+
+${data.data.result}
+
+---
+📝 使用的提示词:
+${data.data.prompt}
+
+⏰ 测试时间:${new Date(data.data.timestamp).toLocaleString()}`);
+ } else {
+ setResult(`❌ 测试失败:${data.error}\n\n📝 使用的提示词:\n${renderedPrompt}`);
+ }
+ } catch (error) {
+ setResult(`❌ 测试失败:${error}\n\n📝 使用的提示词:\n${renderPrompt(template, variables)}`);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return (
+
+ {/* Header */}
+
+
+
+ 测试台
+
+
+
+
+
+
+
+
+ {/* Configuration Panel */}
+
+
+ {/* Model Settings */}
+
+
+ 模型设置
+
+
+
+
+
+
+
+
+
+ setTemperature(Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+
+ setMaxTokens(Number(e.target.value))}
+ className="w-full"
+ />
+
+
+
+
+ {/* Variables */}
+
+
+ {/* Validation Errors */}
+ {validationErrors.length > 0 && (
+
+
+ 验证错误
+
+
+ {validationErrors.map((error, index) => (
+
+ • {error}
+
+ ))}
+
+
+ )}
+
+
+
+ {/* Results Panel */}
+
+
+
+
+
+ 测试结果
+
+
+
+ {isLoading ? (
+
+ ) : result ? (
+
+ {result}
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/editor/variables-panel.tsx b/src/components/editor/variables-panel.tsx
new file mode 100644
index 0000000..dde8e78
--- /dev/null
+++ b/src/components/editor/variables-panel.tsx
@@ -0,0 +1,215 @@
+'use client';
+
+import { useState } from 'react';
+import { Plus, Trash2, Save } from 'lucide-react';
+import { PromptTemplate, PromptVariable } from '@/types/prompt';
+import { VARIABLE_TYPES } from '@/lib/constants';
+
+interface VariablesPanelProps {
+ template: PromptTemplate;
+ onUpdate: (updates: Partial) => void;
+}
+
+export function VariablesPanel({ template, onUpdate }: VariablesPanelProps) {
+ const [editingVariable, setEditingVariable] = useState(null);
+
+ // 添加调试信息
+ console.log('VariablesPanel - template:', template);
+ console.log('VariablesPanel - variables:', template.variables);
+ console.log('VariablesPanel - variables length:', template.variables?.length);
+
+ const handleAddVariable = () => {
+ console.log('Adding new variable...');
+ // 生成唯一的变量名
+ let variableName = `variable_1`;
+ let counter = 1;
+ while (template.variables.some(v => v.name === variableName)) {
+ counter++;
+ variableName = `variable_${counter}`;
+ }
+
+ const newVariable: PromptVariable = {
+ name: variableName,
+ type: 'text',
+ required: true,
+ description: '',
+ };
+ console.log('New variable:', newVariable);
+
+ // 确保 template.variables 是数组
+ const currentVariables = Array.isArray(template.variables) ? template.variables : [];
+ console.log('Current variables before update:', currentVariables);
+
+ onUpdate({
+ variables: [...currentVariables, newVariable]
+ });
+ setEditingVariable(newVariable);
+ };
+
+ const handleUpdateVariable = (name: string, updates: Partial) => {
+ onUpdate({
+ variables: (template.variables || []).map(v =>
+ v.name === name ? { ...v, ...updates } : v
+ )
+ });
+ };
+
+ const handleRemoveVariable = (name: string) => {
+ onUpdate({
+ variables: template.variables.filter(v => v.name !== name)
+ });
+ };
+
+ const handleSaveVariable = () => {
+ setEditingVariable(null);
+ };
+
+ return (
+
+
+
+ {/* Header */}
+
+
+ 变量管理
+
+
+
+
+
+ {/* Variables List */}
+
+ {/* 调试信息 */}
+
+
调试信息:
+
模板ID: {template.id}
+
变量数量: {template.variables?.length || 0}
+
变量数组: {JSON.stringify(template.variables)}
+
+
+ {/* 变量列表 */}
+
+
+
+ 已定义 {template.variables?.length || 0} 个变量
+
+
+
+ {/* 显示现有变量 */}
+ {(template.variables || []).map((variable, index) => (
+
+
+ {/* Variable Name */}
+
+
+ handleUpdateVariable(variable.name, { name: e.target.value })}
+ className="input font-mono"
+ placeholder="variable_name"
+ />
+
+
+ {/* Variable Type */}
+
+
+
+
+
+ {/* Description */}
+
+
+ handleUpdateVariable(variable.name, { description: e.target.value })}
+ className="input"
+ placeholder="描述这个变量的用途..."
+ />
+
+
+ {/* Required */}
+
+
+
+
+
+ {/* Actions */}
+
+
+ 在提示词中使用:
+ {`{{${variable.name}}}`}
+
+
+
+
+
+ ))}
+
+ {/* 添加变量按钮 */}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/layout/header.tsx b/src/components/layout/header.tsx
new file mode 100644
index 0000000..cae67e3
--- /dev/null
+++ b/src/components/layout/header.tsx
@@ -0,0 +1,136 @@
+'use client';
+
+import { useState, useEffect, useRef } from 'react';
+import {
+ Search,
+ Bell,
+ User,
+ Moon,
+ Sun,
+ Settings,
+ LogOut
+} from 'lucide-react';
+import { usePromptStore } from '@/store/promptStore';
+import { useAuth } from '@/contexts/AuthContext';
+import { cn } from '@/lib/utils';
+import Link from 'next/link';
+
+export function Header() {
+ const { theme, setTheme, searchQuery, setSearchQuery } = usePromptStore();
+ const { user, logout } = useAuth();
+ const [showUserMenu, setShowUserMenu] = useState(false);
+ const userMenuRef = useRef(null);
+
+ // 点击外部关闭用户菜单
+ useEffect(() => {
+ function handleClickOutside(event: MouseEvent) {
+ if (userMenuRef.current && !userMenuRef.current.contains(event.target as Node)) {
+ setShowUserMenu(false);
+ }
+ }
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, []);
+
+ return (
+
+
+ {/* Search */}
+
+
+
+ setSearchQuery(e.target.value)}
+ className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+ />
+
+
+
+ {/* Right side */}
+
+ {/* Notifications */}
+
+
+ {/* Theme toggle */}
+
+
+ {/* User menu */}
+
+ {user ? (
+ <>
+
+
+ {showUserMenu && (
+
+
+
{user.name}
+
{user.email}
+
+
+
+ 个人资料
+
+
+
+ 设置
+
+
+
+ )}
+ >
+ ) : (
+
+
+ 登录
+
+
+ 注册
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/src/components/layout/sidebar.tsx b/src/components/layout/sidebar.tsx
new file mode 100644
index 0000000..539ab85
--- /dev/null
+++ b/src/components/layout/sidebar.tsx
@@ -0,0 +1,127 @@
+'use client';
+
+import { useState } from 'react';
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+import {
+ Home,
+ Library,
+ Edit3,
+ Play,
+ Rocket,
+ FileText,
+ ChevronLeft,
+ ChevronRight,
+ Settings,
+ Plus,
+ FolderOpen
+} from 'lucide-react';
+import { usePromptStore } from '@/store/promptStore';
+import { cn } from '@/lib/utils';
+import { NAVIGATION_ITEMS } from '@/lib/constants';
+
+const iconMap = {
+ home: Home,
+ library: Library,
+ folder: FolderOpen,
+ edit: Edit3,
+ test: Play,
+ deploy: Rocket,
+ docs: FileText,
+};
+
+export function Sidebar() {
+ const pathname = usePathname();
+ const { sidebarCollapsed, toggleSidebar, templates } = usePromptStore();
+
+ const recentTemplates = templates.slice(0, 5);
+
+ return (
+
+ {/* Header */}
+
+ {!sidebarCollapsed && (
+
+ PromptForge
+
+ )}
+
+
+
+ {/* Navigation */}
+
+
+ {/* Recent Templates */}
+ {!sidebarCollapsed && recentTemplates.length > 0 && (
+
+
+ 最近模板
+
+
+ {recentTemplates.map((template) => (
+
+ {template.title}
+
+ ))}
+
+
+ )}
+
+ {/* Footer */}
+
+
+ {!sidebarCollapsed && (
+
+
+ 设置
+
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/playground/result-comparison.tsx b/src/components/playground/result-comparison.tsx
new file mode 100644
index 0000000..fdb864d
--- /dev/null
+++ b/src/components/playground/result-comparison.tsx
@@ -0,0 +1,224 @@
+'use client';
+
+import { useState } from 'react';
+import { Download, Copy, Check, BarChart3, Clock, Zap } from 'lucide-react';
+import { copyToClipboard } from '@/lib/utils';
+
+interface ComparisonResult {
+ model: string;
+ provider: string;
+ result: string;
+ success: boolean;
+ error?: string;
+ responseTime: number;
+}
+
+interface ResultComparisonProps {
+ results: ComparisonResult[];
+ prompt: string;
+ timestamp: string;
+}
+
+export function ResultComparison({ results, prompt, timestamp }: ResultComparisonProps) {
+ const [copied, setCopied] = useState(null);
+
+ const handleCopy = async (text: string, model: string) => {
+ await copyToClipboard(text);
+ setCopied(model);
+ setTimeout(() => setCopied(null), 2000);
+ };
+
+ const handleExportResults = () => {
+ const exportData = {
+ prompt,
+ timestamp,
+ results: results.map(r => ({
+ model: r.model,
+ provider: r.provider,
+ result: r.result,
+ success: r.success,
+ responseTime: r.responseTime,
+ error: r.error
+ }))
+ };
+
+ const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `ai-test-results-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+ };
+
+ const successfulResults = results.filter(r => r.success);
+ const failedResults = results.filter(r => !r.success);
+
+ const avgResponseTime = successfulResults.length > 0
+ ? successfulResults.reduce((sum, r) => sum + r.responseTime, 0) / successfulResults.length
+ : 0;
+
+ return (
+
+ {/* Header */}
+
+
+
+ 测试结果比较
+
+
+ {new Date(timestamp).toLocaleString()} • {results.length} 个模型
+
+
+
+
+
+ {/* 统计信息 */}
+
+
+
+
+
+
成功
+
+ {successfulResults.length}
+
+
+
+
+
+
+
+
+
失败
+
+ {failedResults.length}
+
+
+
+
+
+
+
+
+
平均响应
+
+ {avgResponseTime.toFixed(0)}ms
+
+
+
+
+
+
+
+
+
成功率
+
+ {results.length > 0 ? ((successfulResults.length / results.length) * 100).toFixed(0) : 0}%
+
+
+
+
+
+
+ {/* 原始提示词 */}
+
+
+ {/* 结果比较 */}
+
+ {results.map((result, index) => (
+
+
+
+
+
+ {result.provider || '未知'}
+
+
+ {result.model || '未知模型'}
+
+
+ {result.success && (
+
+ {result.responseTime}ms
+
+ )}
+
+
+ {result.success && (
+
+ )}
+
+
+
+ {result.success ? (
+
+
响应内容
+
+ {result.result || '无响应内容'}
+
+
+ ) : (
+
+
错误信息
+
+ {result.error || '未知错误'}
+
+
+ )}
+
+ ))}
+
+
+ {/* 响应时间对比 */}
+ {successfulResults.length > 1 && (
+
+
响应时间对比
+
+ {successfulResults
+ .sort((a, b) => a.responseTime - b.responseTime)
+ .map((result, index) => (
+
+
+ {index + 1}. {result.model} ({result.provider})
+
+
+ {result.responseTime}ms
+
+
+ ))}
+
+
+ )}
+
+ );
+}
diff --git a/src/components/providers.tsx b/src/components/providers.tsx
new file mode 100644
index 0000000..106b900
--- /dev/null
+++ b/src/components/providers.tsx
@@ -0,0 +1,30 @@
+'use client';
+
+import { useEffect } from 'react';
+import { usePromptStore } from '@/store/promptStore';
+import { SAMPLE_TEMPLATES } from '@/lib/constants';
+
+export function Providers({ children }: { children: React.ReactNode }) {
+ const { setTemplates, theme, setTheme } = usePromptStore();
+
+ // Initialize sample templates on first load
+ useEffect(() => {
+ const hasInitialized = localStorage.getItem('promptforge-initialized');
+ if (!hasInitialized) {
+ setTemplates(SAMPLE_TEMPLATES);
+ localStorage.setItem('promptforge-initialized', 'true');
+ }
+ }, [setTemplates]);
+
+ // Apply theme
+ useEffect(() => {
+ const root = document.documentElement;
+ if (theme === 'dark') {
+ root.classList.add('dark');
+ } else {
+ root.classList.remove('dark');
+ }
+ }, [theme]);
+
+ return <>{children}>;
+}
diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx
new file mode 100644
index 0000000..bd7577b
--- /dev/null
+++ b/src/contexts/AuthContext.tsx
@@ -0,0 +1,149 @@
+'use client'
+
+import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'
+
+interface User {
+ id: string
+ email: string
+ name: string
+ avatar: string
+ createdAt: string
+ updatedAt: string
+}
+
+interface AuthContextType {
+ user: User | null
+ loading: boolean
+ login: (email: string, password: string) => Promise<{ success: boolean; error?: string }>
+ register: (email: string, password: string, name: string) => Promise<{ success: boolean; error?: string }>
+ logout: () => void
+ updateProfile: (data: { name?: string; avatar?: string }) => Promise<{ success: boolean; error?: string }>
+}
+
+const AuthContext = createContext(undefined)
+
+export function AuthProvider({ children }: { children: ReactNode }) {
+ const [user, setUser] = useState(null)
+ const [loading, setLoading] = useState(true)
+
+ // 检查本地存储的用户信息
+ useEffect(() => {
+ const savedUser = localStorage.getItem('promptforge_user')
+ if (savedUser) {
+ try {
+ setUser(JSON.parse(savedUser))
+ } catch (error) {
+ console.error('解析用户信息失败:', error)
+ localStorage.removeItem('promptforge_user')
+ }
+ }
+ setLoading(false)
+ }, [])
+
+ const login = async (email: string, password: string) => {
+ try {
+ const response = await fetch('/api/auth/login', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ email, password }),
+ })
+
+ const data = await response.json()
+
+ if (response.ok) {
+ setUser(data.user)
+ localStorage.setItem('promptforge_user', JSON.stringify(data.user))
+ return { success: true }
+ } else {
+ return { success: false, error: data.error }
+ }
+ } catch (error) {
+ console.error('登录失败:', error)
+ return { success: false, error: '网络错误,请稍后重试' }
+ }
+ }
+
+ const register = async (email: string, password: string, name: string) => {
+ try {
+ const response = await fetch('/api/auth/register', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ email, password, name }),
+ })
+
+ const data = await response.json()
+
+ if (response.ok) {
+ setUser(data.user)
+ localStorage.setItem('promptforge_user', JSON.stringify(data.user))
+ return { success: true }
+ } else {
+ return { success: false, error: data.error }
+ }
+ } catch (error) {
+ console.error('注册失败:', error)
+ return { success: false, error: '网络错误,请稍后重试' }
+ }
+ }
+
+ const logout = () => {
+ setUser(null)
+ localStorage.removeItem('promptforge_user')
+ }
+
+ const updateProfile = async (data: { name?: string; avatar?: string }) => {
+ if (!user) {
+ return { success: false, error: '用户未登录' }
+ }
+
+ try {
+ const response = await fetch('/api/user/profile', {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ userId: user.id, ...data }),
+ })
+
+ const responseData = await response.json()
+
+ if (response.ok) {
+ setUser(responseData.user)
+ localStorage.setItem('promptforge_user', JSON.stringify(responseData.user))
+ return { success: true }
+ } else {
+ return { success: false, error: responseData.error }
+ }
+ } catch (error) {
+ console.error('更新资料失败:', error)
+ return { success: false, error: '网络错误,请稍后重试' }
+ }
+ }
+
+ const value = {
+ user,
+ loading,
+ login,
+ register,
+ logout,
+ updateProfile,
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function useAuth() {
+ const context = useContext(AuthContext)
+ if (context === undefined) {
+ throw new Error('useAuth must be used within an AuthProvider')
+ }
+ return context
+}
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
new file mode 100644
index 0000000..d12f0a9
--- /dev/null
+++ b/src/lib/constants.ts
@@ -0,0 +1,143 @@
+import { PromptCategory, OutputFormat } from '@/types/prompt';
+
+export const CATEGORIES: { value: PromptCategory; label: string; description: string }[] = [
+ { value: 'programming', label: '编程', description: '代码生成、调试、架构设计等' },
+ { value: 'marketing', label: '营销', description: '广告文案、市场分析、品牌策略等' },
+ { value: 'project-management', label: '项目管理', description: '项目规划、任务管理、团队协作等' },
+ { value: 'creative-writing', label: '创意写作', description: '文章、报告、创意写作等' },
+ { value: 'education', label: '教育', description: '课程设计、学习材料、教学辅助等' },
+ { value: 'data-analysis', label: '数据分析', description: '数据处理、可视化、统计等' },
+ { value: 'content-creation', label: '内容创作', description: '内容生成、编辑、优化等' },
+ { value: 'customer-service', label: '客服', description: '客户服务、问题解答、沟通等' },
+];
+
+export const OUTPUT_FORMATS: { value: OutputFormat; label: string; description: string }[] = [
+ { value: 'markdown', label: 'Markdown', description: '结构化文档格式' },
+ { value: 'json', label: 'JSON', description: '结构化数据格式' },
+ { value: 'xml', label: 'XML', description: '可扩展标记语言' },
+ { value: 'plain-text', label: '纯文本', description: '简单文本格式' },
+ { value: 'html', label: 'HTML', description: '网页标记语言' },
+ { value: 'csv', label: 'CSV', description: '逗号分隔值' },
+ { value: 'yaml', label: 'YAML', description: '人类可读的数据序列化' },
+ { value: 'custom', label: '自定义', description: '自定义输出格式' },
+];
+
+export const VARIABLE_TYPES = [
+ { value: 'text', label: '文本', description: '字符串类型' },
+ { value: 'number', label: '数字', description: '数值类型' },
+ { value: 'select', label: '选择', description: '从预定义选项中选择' },
+ { value: 'boolean', label: '布尔值', description: '是/否选择' },
+];
+
+export const CONSTRAINT_CATEGORIES = [
+ { value: 'quality', label: '质量', description: '输出质量相关约束' },
+ { value: 'safety', label: '安全', description: '安全性和合规性约束' },
+ { value: 'format', label: '格式', description: '输出格式约束' },
+ { value: 'performance', label: '性能', description: '性能和效率约束' },
+];
+
+export const AI_MODELS = [
+ { value: 'gpt-4', label: 'GPT-4', provider: 'OpenAI' },
+ { value: 'gpt-4-turbo', label: 'GPT-4 Turbo', provider: 'OpenAI' },
+ { value: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo', provider: 'OpenAI' },
+ { value: 'claude-3-opus', label: 'Claude 3 Opus', provider: 'Anthropic' },
+ { value: 'claude-3-sonnet', label: 'Claude 3 Sonnet', provider: 'Anthropic' },
+ { value: 'claude-3-haiku', label: 'Claude 3 Haiku', provider: 'Anthropic' },
+ { value: 'deepseek-coder', label: 'DeepSeek Coder', provider: 'DeepSeek' },
+ { value: 'deepseek-chat', label: 'DeepSeek Chat', provider: 'DeepSeek' },
+ { value: 'deepseek-vision', label: 'DeepSeek Vision', provider: 'DeepSeek' },
+ { value: 'llama-2-70b', label: 'Llama 2 70B', provider: 'Meta' },
+ { value: 'llama-2-13b', label: 'Llama 2 13B', provider: 'Meta' },
+];
+
+export const CODE_PLATFORMS = [
+ { value: 'openai', label: 'OpenAI', description: 'OpenAI API' },
+ { value: 'anthropic', label: 'Anthropic', description: 'Anthropic Claude API' },
+ { value: 'deepseek', label: 'DeepSeek', description: 'DeepSeek API' },
+ { value: 'azure', label: 'Azure OpenAI', description: 'Microsoft Azure OpenAI' },
+ { value: 'llama', label: 'Llama', description: 'Local Llama models' },
+];
+
+export const PROGRAMMING_LANGUAGES = [
+ { value: 'python', label: 'Python', extension: '.py' },
+ { value: 'javascript', label: 'JavaScript', extension: '.js' },
+ { value: 'typescript', label: 'TypeScript', extension: '.ts' },
+ { value: 'curl', label: 'cURL', extension: '.sh' },
+ { value: 'php', label: 'PHP', extension: '.php' },
+ { value: 'java', label: 'Java', extension: '.java' },
+];
+
+export const SAMPLE_TEMPLATES = [
+ {
+ id: 'sample-1',
+ title: 'API设计文档生成器',
+ description: '生成完整的API设计文档,包含端点、参数、响应格式等',
+ category: 'programming' as PromptCategory,
+ tags: ['api', 'documentation', 'backend'],
+ role: '你是一位资深软件架构师,拥有丰富的API设计经验。',
+ task: '我的任务是生成一个关于{{topic}}的API设计文档。',
+ context: '这个API将用于{{useCase}}场景,需要支持{{features}}功能。',
+ constraints: [
+ { id: '1', text: '使用RESTful设计原则', category: 'quality' },
+ { id: '2', text: '包含完整的错误处理', category: 'safety' },
+ { id: '3', text: '提供OpenAPI 3.0规范', category: 'format' },
+ ],
+ outputFormat: 'markdown' as OutputFormat,
+ variables: [
+ { name: 'topic', type: 'text', required: true, description: 'API主题' },
+ { name: 'useCase', type: 'text', required: true, description: '使用场景' },
+ { name: 'features', type: 'text', required: false, description: '核心功能' },
+ ],
+ author: 'PromptForge',
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ usageCount: 0,
+ rating: 0,
+ ratingCount: 0,
+ compatibleModels: ['gpt-4', 'claude-3-opus'],
+ isPublic: true,
+ isFeatured: true,
+ },
+ {
+ id: 'sample-2',
+ title: '营销文案优化器',
+ description: '优化营销文案,提升转化率和用户 engagement',
+ category: 'marketing' as PromptCategory,
+ tags: ['marketing', 'copywriting', 'conversion'],
+ role: '你是一位经验丰富的营销文案专家,擅长AIDA模型和情感营销。',
+ task: '请优化以下营销文案,使其更具吸引力和转化力:{{originalCopy}}',
+ context: '目标受众是{{targetAudience}},产品是{{product}},主要卖点是{{valueProposition}}。',
+ constraints: [
+ { id: '1', text: '保持品牌调性一致', category: 'quality' },
+ { id: '2', text: '包含明确的行动号召', category: 'format' },
+ { id: '3', text: '字数控制在{{wordLimit}}字以内', category: 'performance' },
+ ],
+ outputFormat: 'plain-text' as OutputFormat,
+ variables: [
+ { name: 'originalCopy', type: 'text', required: true, description: '原始文案' },
+ { name: 'targetAudience', type: 'text', required: true, description: '目标受众' },
+ { name: 'product', type: 'text', required: true, description: '产品名称' },
+ { name: 'valueProposition', type: 'text', required: true, description: '价值主张' },
+ { name: 'wordLimit', type: 'number', required: false, defaultValue: 200, description: '字数限制' },
+ ],
+ author: 'PromptForge',
+ createdAt: new Date(),
+ updatedAt: new Date(),
+ usageCount: 0,
+ rating: 0,
+ ratingCount: 0,
+ compatibleModels: ['gpt-4', 'claude-3-sonnet'],
+ isPublic: true,
+ isFeatured: true,
+ },
+];
+
+export const NAVIGATION_ITEMS = [
+ { href: '/', label: '首页', icon: 'home' },
+ { href: '/templates', label: '模板库', icon: 'library' },
+ { href: '/templates/manage', label: '我的模板', icon: 'folder' },
+ { href: '/editor', label: '编辑器', icon: 'edit' },
+ { href: '/playground', label: '测试台', icon: 'test' },
+ { href: '/deploy', label: '部署', icon: 'deploy' },
+ { href: '/docs', label: '文档', icon: 'docs' },
+];
diff --git a/src/lib/database.ts b/src/lib/database.ts
new file mode 100644
index 0000000..17bdb7c
--- /dev/null
+++ b/src/lib/database.ts
@@ -0,0 +1,183 @@
+import mysql from 'mysql2/promise'
+
+// 数据库连接配置
+const dbConfig = {
+ host: 'gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
+ port: 24936,
+ user: 'root',
+ password: '!Rjb12191',
+ database: 'pronode_db',
+ charset: 'utf8mb4'
+}
+
+// 创建数据库连接池
+const pool = mysql.createPool({
+ ...dbConfig,
+ waitForConnections: true,
+ connectionLimit: 10,
+ queueLimit: 0
+})
+
+// 数据库连接测试
+export async function testDatabaseConnection() {
+ try {
+ const connection = await pool.getConnection()
+ await connection.ping()
+ connection.release()
+ console.log('✅ 数据库连接成功')
+ return true
+ } catch (error) {
+ console.error('❌ 数据库连接失败:', error)
+ return false
+ }
+}
+
+// 获取数据库连接
+export async function getConnection() {
+ return await pool.getConnection()
+}
+
+// 执行查询
+export async function query(sql: string, params?: any[]) {
+ const [rows] = await pool.execute(sql, params)
+ return rows
+}
+
+// 优雅关闭数据库连接
+export async function closeDatabaseConnection() {
+ await pool.end()
+}
+
+// 数据库操作函数
+export const db = {
+ // 用户相关
+ async getUserById(id: string) {
+ const [rows] = await pool.execute('SELECT * FROM promptforge_users WHERE id = ?', [id])
+ return rows[0]
+ },
+
+ async getUserByEmail(email: string) {
+ const [rows] = await pool.execute('SELECT * FROM promptforge_users WHERE email = ?', [email])
+ return rows[0]
+ },
+
+ async createUser(userData: { id: string; email: string; name?: string; avatar?: string; password?: string }) {
+ const [result] = await pool.execute(
+ 'INSERT INTO promptforge_users (id, email, name, avatar, password) VALUES (?, ?, ?, ?, ?)',
+ [userData.id, userData.email, userData.name, userData.avatar, userData.password]
+ )
+ return result
+ },
+
+ async updateUser(userId: string, updateData: { name?: string; avatar?: string }) {
+ const fields = []
+ const values = []
+
+ if (updateData.name !== undefined) {
+ fields.push('name = ?')
+ values.push(updateData.name)
+ }
+ if (updateData.avatar !== undefined) {
+ fields.push('avatar = ?')
+ values.push(updateData.avatar)
+ }
+
+ if (fields.length === 0) {
+ return null
+ }
+
+ values.push(userId)
+ const [result] = await pool.execute(
+ `UPDATE promptforge_users SET ${fields.join(', ')} WHERE id = ?`,
+ values
+ )
+ return result
+ },
+
+ // 模板相关操作
+ async createTemplate(templateData: any) {
+ const [result] = await pool.execute(
+ `INSERT INTO promptforge_templates (
+ id, title, description, category, role, task, context,
+ constraints, variables, outputFormat, authorId, isPublic,
+ usageCount, rating, createdAt, updatedAt
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
+ [
+ templateData.id,
+ templateData.title,
+ templateData.description,
+ templateData.category,
+ templateData.role,
+ templateData.task,
+ templateData.context,
+ templateData.constraints,
+ templateData.variables,
+ templateData.outputFormat,
+ templateData.user_id,
+ templateData.is_public,
+ templateData.downloads,
+ templateData.likes > 0 ? (templateData.likes / 100).toFixed(2) : 0,
+ templateData.created_at,
+ templateData.updated_at
+ ]
+ )
+ return result
+ },
+
+ async getTemplateById(templateId: string) {
+ const [rows] = await pool.execute(
+ 'SELECT * FROM promptforge_templates WHERE id = ?',
+ [templateId]
+ )
+ return (rows as any[])[0] || null
+ },
+
+ async updateTemplate(templateId: string, updateData: any) {
+ const fields = []
+ const values = []
+
+ Object.keys(updateData).forEach(key => {
+ if (updateData[key] !== undefined) {
+ fields.push(`${key} = ?`)
+ values.push(updateData[key])
+ }
+ })
+
+ if (fields.length === 0) {
+ return null
+ }
+
+ values.push(templateId)
+ const [result] = await pool.execute(
+ `UPDATE promptforge_templates SET ${fields.join(', ')} WHERE id = ?`,
+ values
+ )
+ return result
+ },
+
+ async deleteTemplate(templateId: string) {
+ const [result] = await pool.execute(
+ 'DELETE FROM promptforge_templates WHERE id = ?',
+ [templateId]
+ )
+ return result
+ },
+
+
+
+ // 系统配置相关
+ async getConfig(key: string) {
+ const [rows] = await pool.execute('SELECT * FROM promptforge_configs WHERE config_key = ?', [key])
+ return rows[0]
+ },
+
+ async setConfig(key: string, value: string, type: string = 'string') {
+ const [result] = await pool.execute(
+ 'INSERT INTO promptforge_configs (id, config_key, value, type) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE value = ?, type = ?',
+ [`config_${Date.now()}`, key, value, type, value, type]
+ )
+ return result
+ }
+}
+
+export default db
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..f8f9747
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,172 @@
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
+import { PromptTemplate, PromptVariable } from '@/types/prompt';
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+export function generateId(): string {
+ return Math.random().toString(36).substr(2, 9);
+}
+
+export function formatDate(date: Date | string): string {
+ const dateObj = typeof date === 'string' ? new Date(date) : date;
+ return new Intl.DateTimeFormat('zh-CN', {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ }).format(dateObj);
+}
+
+export function formatRelativeTime(date: Date | string): string {
+ const dateObj = typeof date === 'string' ? new Date(date) : date;
+ const now = new Date();
+ const diffInSeconds = Math.floor((now.getTime() - dateObj.getTime()) / 1000);
+
+ if (diffInSeconds < 60) return '刚刚';
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}分钟前`;
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}小时前`;
+ if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)}天前`;
+
+ return formatDate(dateObj);
+}
+
+export function renderPrompt(template: PromptTemplate, variables: Record): string {
+ let prompt = (template.role || '') + '\n\n';
+ prompt += (template.task || '') + '\n\n';
+
+ if (template.context) {
+ prompt += `背景信息:${template.context}\n\n`;
+ }
+
+ if ((template.constraints || []).length > 0) {
+ prompt += '约束条件:\n';
+ (template.constraints || []).forEach(constraint => {
+ // 处理约束条件的不同格式
+ let constraintText = '';
+ if (typeof constraint === 'string') {
+ constraintText = constraint;
+ } else if (constraint && typeof constraint === 'object') {
+ constraintText = constraint.text || constraint.toString();
+ } else {
+ constraintText = String(constraint);
+ }
+ prompt += `- ${constraintText}\n`;
+ });
+ prompt += '\n';
+ }
+
+ prompt += `输出格式:${template.outputFormat || ''}\n\n`;
+
+ // Replace variables in the prompt
+ Object.entries(variables).forEach(([key, value]) => {
+ const regex = new RegExp(`{{${key}}}`, 'g');
+ prompt = prompt.replace(regex, String(value));
+ });
+
+ return prompt;
+}
+
+export function extractVariables(text: string): string[] {
+ const regex = /{{([^}]+)}}/g;
+ const variables: string[] = [];
+ let match;
+
+ while ((match = regex.exec(text)) !== null) {
+ variables.push(match[1]);
+ }
+
+ return [...new Set(variables)];
+}
+
+export function validateVariables(
+ template: PromptTemplate,
+ variables: Record
+): { valid: boolean; errors: string[] } {
+ const errors: string[] = [];
+
+ template.variables.forEach(variable => {
+ if (variable.required && !(variable.name in variables)) {
+ errors.push(`缺少必需变量: ${variable.name}`);
+ }
+
+ if (variable.name in variables) {
+ const value = variables[variable.name];
+
+ if (variable.type === 'number' && isNaN(Number(value))) {
+ errors.push(`变量 ${variable.name} 必须是数字`);
+ }
+
+ if (variable.type === 'select' && variable.options && !variable.options.includes(String(value))) {
+ errors.push(`变量 ${variable.name} 必须是以下选项之一: ${variable.options.join(', ')}`);
+ }
+ }
+ });
+
+ return { valid: errors.length === 0, errors };
+}
+
+export function getCategoryIcon(category: string): string {
+ const icons: Record = {
+ writing: '📝',
+ programming: '💻',
+ 'data-analysis': '📊',
+ marketing: '📈',
+ education: '🎓',
+ game: '🎮',
+ business: '💼',
+ creative: '🎨',
+ research: '🔬',
+ other: '📁',
+ };
+
+ return icons[category] || icons.other;
+}
+
+export function getCategoryColor(category: string): string {
+ const colors: Record = {
+ writing: 'text-blue-600 bg-blue-50 dark:bg-blue-900/20',
+ programming: 'text-green-600 bg-green-50 dark:bg-green-900/20',
+ 'data-analysis': 'text-purple-600 bg-purple-50 dark:bg-purple-900/20',
+ marketing: 'text-orange-600 bg-orange-50 dark:bg-orange-900/20',
+ education: 'text-indigo-600 bg-indigo-50 dark:bg-indigo-900/20',
+ game: 'text-pink-600 bg-pink-50 dark:bg-pink-900/20',
+ business: 'text-gray-600 bg-gray-50 dark:bg-gray-900/20',
+ creative: 'text-yellow-600 bg-yellow-50 dark:bg-yellow-900/20',
+ research: 'text-red-600 bg-red-50 dark:bg-red-900/20',
+ other: 'text-gray-600 bg-gray-50 dark:bg-gray-900/20',
+ };
+
+ return colors[category] || colors.other;
+}
+
+export function debounce any>(
+ func: T,
+ wait: number
+): (...args: Parameters) => void {
+ let timeout: NodeJS.Timeout;
+
+ return (...args: Parameters) => {
+ clearTimeout(timeout);
+ timeout = setTimeout(() => func(...args), wait);
+ };
+}
+
+export function copyToClipboard(text: string): Promise {
+ if (navigator.clipboard) {
+ return navigator.clipboard.writeText(text);
+ }
+
+ // Fallback for older browsers
+ const textArea = document.createElement('textarea');
+ textArea.value = text;
+ document.body.appendChild(textArea);
+ textArea.select();
+ document.execCommand('copy');
+ document.body.removeChild(textArea);
+
+ return Promise.resolve();
+}
diff --git a/src/store/promptStore.ts b/src/store/promptStore.ts
new file mode 100644
index 0000000..d2ca2f6
--- /dev/null
+++ b/src/store/promptStore.ts
@@ -0,0 +1,259 @@
+import { create } from 'zustand';
+import { devtools, persist } from 'zustand/middleware';
+import { PromptTemplate, PromptTest, PromptVariable, PromptConstraint } from '@/types/prompt';
+
+interface PromptState {
+ // Current editing template
+ currentTemplate: PromptTemplate | null;
+
+ // Template library
+ templates: PromptTemplate[];
+ filteredTemplates: PromptTemplate[];
+ selectedCategory: string | null;
+ searchQuery: string;
+
+ // Editor state
+ isEditing: boolean;
+ activeTab: 'editor' | 'preview' | 'variables' | 'test' | 'deploy';
+
+ // Test results
+ testResults: PromptTest[];
+ currentTest: PromptTest | null;
+
+ // UI state
+ sidebarCollapsed: boolean;
+ theme: 'light' | 'dark';
+
+ // Actions
+ setCurrentTemplate: (template: PromptTemplate | null) => void;
+ updateTemplate: (updates: Partial) => void;
+ addTemplate: (template: PromptTemplate) => void;
+ deleteTemplate: (id: string) => void;
+
+ // Template library actions
+ setTemplates: (templates: PromptTemplate[]) => void;
+ filterByCategory: (category: string | null) => void;
+ setSearchQuery: (query: string) => void;
+
+ // Editor actions
+ setIsEditing: (editing: boolean) => void;
+ setActiveTab: (tab: string) => void;
+
+ // Test actions
+ addTestResult: (test: PromptTest) => void;
+ setCurrentTest: (test: PromptTest | null) => void;
+
+ // UI actions
+ toggleSidebar: () => void;
+ setTheme: (theme: 'light' | 'dark') => void;
+
+ // Variable management
+ addVariable: (variable: PromptVariable) => void;
+ updateVariable: (name: string, updates: Partial) => void;
+ removeVariable: (name: string) => void;
+
+ // Constraint management
+ addConstraint: (constraint: PromptConstraint) => void;
+ updateConstraint: (id: string, updates: Partial) => void;
+ removeConstraint: (id: string) => void;
+}
+
+export const usePromptStore = create()(
+ devtools(
+ persist(
+ (set, get) => ({
+ // Initial state
+ currentTemplate: null,
+ templates: [],
+ filteredTemplates: [],
+ selectedCategory: null,
+ searchQuery: '',
+ isEditing: false,
+ activeTab: 'editor',
+ testResults: [],
+ currentTest: null,
+ sidebarCollapsed: false,
+ theme: 'dark',
+
+ // Template actions
+ setCurrentTemplate: (template) => set({ currentTemplate: template }),
+
+ updateTemplate: (updates) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ ...updates,
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+
+ addTemplate: (template) => {
+ const { templates } = get();
+ set({ templates: [...templates, template] });
+ },
+
+ deleteTemplate: (id) => {
+ const { templates } = get();
+ set({ templates: templates.filter(t => t.id !== id) });
+ },
+
+ // Library actions
+ setTemplates: (templates) => set({ templates, filteredTemplates: templates }),
+
+ filterByCategory: (category) => {
+ const { templates, searchQuery } = get();
+ let filtered = templates;
+
+ if (category) {
+ filtered = filtered.filter(t => t.category === category);
+ }
+
+ if (searchQuery) {
+ filtered = filtered.filter(t =>
+ t.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ t.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ t.tags.some(tag => tag.toLowerCase().includes(searchQuery.toLowerCase()))
+ );
+ }
+
+ set({ filteredTemplates: filtered, selectedCategory: category });
+ },
+
+ setSearchQuery: (query) => {
+ const { templates, selectedCategory } = get();
+ let filtered = templates;
+
+ if (selectedCategory) {
+ filtered = filtered.filter(t => t.category === selectedCategory);
+ }
+
+ if (query) {
+ filtered = filtered.filter(t =>
+ t.title.toLowerCase().includes(query.toLowerCase()) ||
+ t.description.toLowerCase().includes(query.toLowerCase()) ||
+ t.tags.some(tag => tag.toLowerCase().includes(query.toLowerCase()))
+ );
+ }
+
+ set({ filteredTemplates: filtered, searchQuery: query });
+ },
+
+ // Editor actions
+ setIsEditing: (editing) => set({ isEditing: editing }),
+ setActiveTab: (tab) => set({ activeTab: tab as any }),
+
+ // Test actions
+ addTestResult: (test) => {
+ const { testResults } = get();
+ set({ testResults: [test, ...testResults] });
+ },
+
+ setCurrentTest: (test) => set({ currentTest: test }),
+
+ // UI actions
+ toggleSidebar: () => {
+ const { sidebarCollapsed } = get();
+ set({ sidebarCollapsed: !sidebarCollapsed });
+ },
+
+ setTheme: (theme) => set({ theme }),
+
+ // Variable management
+ addVariable: (variable) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ variables: [...currentTemplate.variables, variable],
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+
+ updateVariable: (name, updates) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ variables: currentTemplate.variables.map(v =>
+ v.name === name ? { ...v, ...updates } : v
+ ),
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+
+ removeVariable: (name) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ variables: currentTemplate.variables.filter(v => v.name !== name),
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+
+ // Constraint management
+ addConstraint: (constraint) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ constraints: [...currentTemplate.constraints, constraint],
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+
+ updateConstraint: (id, updates) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ constraints: currentTemplate.constraints.map(c =>
+ c.id === id ? { ...c, ...updates } : c
+ ),
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+
+ removeConstraint: (id) => {
+ const { currentTemplate } = get();
+ if (currentTemplate) {
+ set({
+ currentTemplate: {
+ ...currentTemplate,
+ constraints: currentTemplate.constraints.filter(c => c.id !== id),
+ updatedAt: new Date(),
+ },
+ });
+ }
+ },
+ }),
+ {
+ name: 'promptforge-storage',
+ partialize: (state) => ({
+ templates: state.templates,
+ theme: state.theme,
+ sidebarCollapsed: state.sidebarCollapsed,
+ }),
+ }
+ )
+ )
+);
diff --git a/src/types/prompt.ts b/src/types/prompt.ts
new file mode 100644
index 0000000..e1e1a4b
--- /dev/null
+++ b/src/types/prompt.ts
@@ -0,0 +1,102 @@
+export interface PromptVariable {
+ name: string;
+ type: 'text' | 'number' | 'select' | 'boolean';
+ defaultValue?: string | number | boolean;
+ description?: string;
+ options?: string[]; // For select type
+ required: boolean;
+}
+
+export interface PromptConstraint {
+ id: string;
+ text: string;
+ category?: 'quality' | 'safety' | 'format' | 'performance';
+}
+
+export interface PromptTemplate {
+ id: string;
+ title: string;
+ description: string;
+ category: PromptCategory;
+ tags: string[];
+
+ // Core prompt structure
+ role: string;
+ task: string;
+ context?: string;
+ constraints: PromptConstraint[];
+ outputFormat: OutputFormat;
+ examples?: PromptExample[];
+
+ // Variables
+ variables: PromptVariable[];
+
+ // Metadata
+ author: string;
+ createdAt: Date;
+ updatedAt: Date;
+ usageCount: number;
+ rating: number;
+ ratingCount: number;
+
+ // Compatibility
+ compatibleModels: string[];
+
+ // Community
+ isPublic: boolean;
+ isFeatured: boolean;
+}
+
+export interface PromptExample {
+ input: Record;
+ output: string;
+ description?: string;
+}
+
+export type PromptCategory =
+ | 'programming'
+ | 'marketing'
+ | 'project-management'
+ | 'creative-writing'
+ | 'education'
+ | 'data-analysis'
+ | 'content-creation'
+ | 'customer-service';
+
+export type OutputFormat =
+ | 'markdown'
+ | 'json'
+ | 'xml'
+ | 'plain-text'
+ | 'html'
+ | 'csv'
+ | 'yaml'
+ | 'custom';
+
+export interface PromptTest {
+ id: string;
+ templateId: string;
+ variables: Record;
+ model: string;
+ temperature: number;
+ maxTokens: number;
+ result?: string;
+ status: 'pending' | 'running' | 'completed' | 'failed';
+ createdAt: Date;
+ executionTime?: number;
+}
+
+export interface PromptOptimization {
+ originalPrompt: string;
+ optimizedPrompt: string;
+ improvements: string[];
+ score: number;
+ suggestions: string[];
+}
+
+export interface CodeSnippet {
+ language: 'python' | 'javascript' | 'typescript' | 'curl' | 'php' | 'java';
+ platform: 'openai' | 'anthropic' | 'azure' | 'llama';
+ code: string;
+ description: string;
+}
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 0000000..5e4f553
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,59 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: [
+ './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
+ './src/components/**/*.{js,ts,jsx,tsx,mdx}',
+ './src/app/**/*.{js,ts,jsx,tsx,mdx}',
+ ],
+ theme: {
+ extend: {
+ colors: {
+ primary: {
+ 50: '#f0f9ff',
+ 100: '#e0f2fe',
+ 200: '#bae6fd',
+ 300: '#7dd3fc',
+ 400: '#38bdf8',
+ 500: '#0ea5e9',
+ 600: '#0284c7',
+ 700: '#0369a1',
+ 800: '#075985',
+ 900: '#0c4a6e',
+ },
+ dark: {
+ 50: '#f8fafc',
+ 100: '#f1f5f9',
+ 200: '#e2e8f0',
+ 300: '#cbd5e1',
+ 400: '#94a3b8',
+ 500: '#64748b',
+ 600: '#475569',
+ 700: '#334155',
+ 800: '#1e293b',
+ 900: '#0f172a',
+ }
+ },
+ fontFamily: {
+ mono: ['JetBrains Mono', 'Monaco', 'Consolas', 'monospace'],
+ sans: ['Inter', 'system-ui', 'sans-serif'],
+ },
+ animation: {
+ 'fade-in': 'fadeIn 0.5s ease-in-out',
+ 'slide-up': 'slideUp 0.3s ease-out',
+ 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
+ },
+ keyframes: {
+ fadeIn: {
+ '0%': { opacity: '0' },
+ '100%': { opacity: '1' },
+ },
+ slideUp: {
+ '0%': { transform: 'translateY(10px)', opacity: '0' },
+ '100%': { transform: 'translateY(0)', opacity: '1' },
+ },
+ },
+ },
+ },
+ plugins: [],
+ darkMode: 'class',
+}
diff --git a/test-db-connection.js b/test-db-connection.js
new file mode 100644
index 0000000..aec2e34
--- /dev/null
+++ b/test-db-connection.js
@@ -0,0 +1,67 @@
+const mysql = require('mysql2/promise');
+
+// 数据库连接配置
+const dbConfig = {
+ host: 'gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
+ port: 24936,
+ user: 'root',
+ password: '!Rjb12191',
+ database: 'pronode_db',
+ charset: 'utf8mb4'
+};
+
+async function testConnection() {
+ let connection;
+
+ try {
+ console.log('🔌 正在连接腾讯云数据库...');
+
+ // 创建连接
+ connection = await mysql.createConnection(dbConfig);
+
+ console.log('✅ 数据库连接成功!');
+
+ // 测试查询
+ const [rows] = await connection.execute('SELECT 1 as test');
+ console.log('✅ 查询测试成功:', rows[0]);
+
+ // 检查数据库是否存在
+ const [databases] = await connection.execute('SHOW DATABASES');
+ console.log('📊 可用数据库:');
+ databases.forEach(db => {
+ console.log(` - ${db.Database}`);
+ });
+
+ // 检查当前数据库的表
+ const [tables] = await connection.execute('SHOW TABLES');
+ console.log('📋 当前数据库表:');
+ if (tables.length === 0) {
+ console.log(' (暂无表)');
+ } else {
+ tables.forEach(table => {
+ console.log(` - ${Object.values(table)[0]}`);
+ });
+ }
+
+ return true;
+
+ } catch (error) {
+ console.error('❌ 数据库连接失败:', error.message);
+ return false;
+ } finally {
+ if (connection) {
+ await connection.end();
+ console.log('🔌 数据库连接已关闭');
+ }
+ }
+}
+
+// 运行测试
+testConnection().then(success => {
+ if (success) {
+ console.log('🎉 数据库连接测试完成!');
+ } else {
+ console.log('💥 数据库连接测试失败!');
+ }
+ process.exit(success ? 0 : 1);
+});
diff --git a/test-deepseek-api.js b/test-deepseek-api.js
new file mode 100644
index 0000000..ba17e4e
--- /dev/null
+++ b/test-deepseek-api.js
@@ -0,0 +1,53 @@
+const fetch = require('node-fetch');
+
+// DeepSeek API 配置
+const DEEPSEEK_API_URL = 'https://api.deepseek.com/v1/chat/completions';
+const DEEPSEEK_API_KEY = 'sk-fdf7cc1c73504e628ec0119b7e11b8cc';
+
+async function testDeepSeekAPI() {
+ console.log('🧪 测试 DeepSeek API 连接...\n');
+
+ try {
+ const response = await fetch(DEEPSEEK_API_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${DEEPSEEK_API_KEY}`,
+ },
+ body: JSON.stringify({
+ model: 'deepseek-chat',
+ messages: [
+ {
+ role: 'user',
+ content: '你好,请简单介绍一下你自己。'
+ }
+ ],
+ temperature: 0.7,
+ max_tokens: 200,
+ stream: false
+ })
+ });
+
+ if (!response.ok) {
+ const error = await response.text();
+ console.error('❌ API 调用失败:');
+ console.error(`状态码: ${response.status}`);
+ console.error(`错误信息: ${error}`);
+ return;
+ }
+
+ const data = await response.json();
+
+ console.log('✅ API 连接成功!');
+ console.log('📝 响应内容:');
+ console.log(data.choices[0]?.message?.content || '无响应内容');
+ console.log('\n🔧 响应详情:');
+ console.log(JSON.stringify(data, null, 2));
+
+ } catch (error) {
+ console.error('❌ 测试失败:', error.message);
+ }
+}
+
+// 运行测试
+testDeepSeekAPI();
diff --git a/test-syntax.js b/test-syntax.js
new file mode 100644
index 0000000..42682ee
--- /dev/null
+++ b/test-syntax.js
@@ -0,0 +1,68 @@
+const fs = require('fs');
+const path = require('path');
+
+function checkSyntax() {
+ try {
+ console.log('🔍 检查个人资料页面语法...');
+
+ const profilePath = path.join(__dirname, 'src', 'app', 'profile', 'page.tsx');
+
+ if (!fs.existsSync(profilePath)) {
+ console.log('❌ 个人资料页面文件不存在');
+ return false;
+ }
+
+ const content = fs.readFileSync(profilePath, 'utf8');
+
+ // 检查基本的语法结构
+ const checks = [
+ {
+ name: 'ProtectedRoute 组件导入',
+ test: content.includes("import { ProtectedRoute } from '@/components/auth/ProtectedRoute'")
+ },
+ {
+ name: 'ProtectedRoute 组件使用',
+ test: content.includes('') && content.includes('')
+ },
+ {
+ name: 'JSX 结构完整性',
+ test: (content.match(//g) || []).length
+ },
+ {
+ name: '函数组件定义',
+ test: content.includes('export default function ProfilePage()')
+ },
+ {
+ name: 'useAuth Hook 使用',
+ test: content.includes('const { user, updateProfile, logout } = useAuth()')
+ }
+ ];
+
+ let allPassed = true;
+
+ checks.forEach(check => {
+ if (check.test) {
+ console.log(`✅ ${check.name}`);
+ } else {
+ console.log(`❌ ${check.name}`);
+ allPassed = false;
+ }
+ });
+
+ if (allPassed) {
+ console.log('🎉 语法检查通过!');
+ return true;
+ } else {
+ console.log('💥 语法检查失败!');
+ return false;
+ }
+
+ } catch (error) {
+ console.error('❌ 语法检查出错:', error.message);
+ return false;
+ }
+}
+
+// 运行语法检查
+const result = checkSyntax();
+process.exit(result ? 0 : 1);
diff --git a/test-user-system.js b/test-user-system.js
new file mode 100644
index 0000000..dcada94
--- /dev/null
+++ b/test-user-system.js
@@ -0,0 +1,98 @@
+const mysql = require('mysql2/promise');
+
+// 数据库连接配置
+const dbConfig = {
+ host: 'gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
+ port: 24936,
+ user: 'root',
+ password: '!Rjb12191',
+ database: 'pronode_db',
+ charset: 'utf8mb4'
+};
+
+async function testUserSystem() {
+ let connection;
+
+ try {
+ console.log('🔌 正在连接腾讯云数据库...');
+
+ // 创建连接
+ connection = await mysql.createConnection(dbConfig);
+
+ console.log('✅ 数据库连接成功!');
+
+ // 使用数据库
+ await connection.query('USE pronode_db');
+ console.log('✅ 已切换到 pronode_db 数据库');
+
+ // 测试用户表结构
+ console.log('🔍 检查用户表结构...');
+ const [columns] = await connection.query('DESCRIBE promptforge_users');
+ console.log('📋 用户表字段:');
+ columns.forEach(col => {
+ console.log(` - ${col.Field}: ${col.Type} ${col.Null === 'YES' ? '(可空)' : '(必填)'}`);
+ });
+
+ // 检查是否有用户数据
+ console.log('🔍 检查用户数据...');
+ const [users] = await connection.query('SELECT id, email, name, avatar, createdAt FROM promptforge_users LIMIT 5');
+
+ if (users.length > 0) {
+ console.log(`✅ 找到 ${users.length} 个用户:`);
+ users.forEach((user, index) => {
+ console.log(` ${index + 1}. ${user.name} (${user.email}) - 注册时间: ${user.createdAt}`);
+ });
+ } else {
+ console.log('⚠️ 没有找到用户数据');
+ }
+
+ // 测试创建新用户
+ console.log('🧪 测试创建新用户...');
+ const testUser = {
+ id: `test_${Date.now()}`,
+ email: `test${Date.now()}@example.com`,
+ name: '测试用户',
+ avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=test',
+ password: '$2b$12$test.hash.for.testing',
+ createdAt: new Date(),
+ updatedAt: new Date()
+ };
+
+ try {
+ await connection.execute(
+ 'INSERT INTO promptforge_users (id, email, name, avatar, password, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?)',
+ [testUser.id, testUser.email, testUser.name, testUser.avatar, testUser.password, testUser.createdAt, testUser.updatedAt]
+ );
+ console.log('✅ 测试用户创建成功');
+
+ // 删除测试用户
+ await connection.execute('DELETE FROM promptforge_users WHERE id = ?', [testUser.id]);
+ console.log('✅ 测试用户清理完成');
+
+ } catch (error) {
+ console.log('❌ 测试用户创建失败:', error.message);
+ }
+
+ console.log('🎉 用户系统测试完成!');
+ return true;
+
+ } catch (error) {
+ console.error('❌ 用户系统测试失败:', error.message);
+ return false;
+ } finally {
+ if (connection) {
+ await connection.end();
+ console.log('🔌 数据库连接已关闭');
+ }
+ }
+}
+
+// 运行测试
+testUserSystem().then(success => {
+ if (success) {
+ console.log('🎉 用户系统测试通过!');
+ } else {
+ console.log('💥 用户系统测试失败!');
+ }
+ process.exit(success ? 0 : 1);
+});
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..124da8f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,32 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "es6"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"],
+ "@/components/*": ["./src/components/*"],
+ "@/lib/*": ["./src/lib/*"],
+ "@/types/*": ["./src/types/*"],
+ "@/store/*": ["./src/store/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/update-user-table.js b/update-user-table.js
new file mode 100644
index 0000000..4970238
--- /dev/null
+++ b/update-user-table.js
@@ -0,0 +1,74 @@
+const mysql = require('mysql2/promise');
+
+// 数据库连接配置
+const dbConfig = {
+ host: 'gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
+ port: 24936,
+ user: 'root',
+ password: '!Rjb12191',
+ database: 'pronode_db',
+ charset: 'utf8mb4'
+};
+
+async function updateUserTable() {
+ let connection;
+
+ try {
+ console.log('🔌 正在连接腾讯云数据库...');
+
+ // 创建连接
+ connection = await mysql.createConnection(dbConfig);
+
+ console.log('✅ 数据库连接成功!');
+
+ // 使用数据库
+ await connection.query('USE pronode_db');
+ console.log('✅ 已切换到 pronode_db 数据库');
+
+ // 检查密码字段是否存在
+ console.log('🔍 检查用户表结构...');
+ const [columns] = await connection.query('DESCRIBE promptforge_users');
+ const hasPasswordColumn = columns.some(col => col.Field === 'password');
+
+ if (!hasPasswordColumn) {
+ console.log('📝 添加密码字段...');
+ await connection.query(`
+ ALTER TABLE promptforge_users
+ ADD COLUMN password VARCHAR(255) AFTER email
+ `);
+ console.log('✅ 密码字段添加成功');
+ } else {
+ console.log('✅ 密码字段已存在');
+ }
+
+ // 验证表结构
+ console.log('🔍 验证更新后的表结构...');
+ const [updatedColumns] = await connection.query('DESCRIBE promptforge_users');
+ console.log('📋 用户表字段:');
+ updatedColumns.forEach(col => {
+ console.log(` - ${col.Field}: ${col.Type} ${col.Null === 'YES' ? '(可空)' : '(必填)'}`);
+ });
+
+ console.log('🎉 用户表更新完成!');
+ return true;
+
+ } catch (error) {
+ console.error('❌ 数据库操作失败:', error.message);
+ return false;
+ } finally {
+ if (connection) {
+ await connection.end();
+ console.log('🔌 数据库连接已关闭');
+ }
+ }
+}
+
+// 运行更新脚本
+updateUserTable().then(success => {
+ if (success) {
+ console.log('🎉 用户表结构更新完成!');
+ } else {
+ console.log('💥 用户表结构更新失败!');
+ }
+ process.exit(success ? 0 : 1);
+});
diff --git a/verify-data.js b/verify-data.js
new file mode 100644
index 0000000..6fcfacf
--- /dev/null
+++ b/verify-data.js
@@ -0,0 +1,82 @@
+const mysql = require('mysql2/promise');
+
+// 数据库连接配置
+const dbConfig = {
+ host: 'gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
+ port: 24936,
+ user: 'root',
+ password: '!Rjb12191',
+ database: 'pronode_db',
+ charset: 'utf8mb4'
+};
+
+async function verifyData() {
+ let connection;
+
+ try {
+ console.log('🔌 正在连接腾讯云数据库...');
+
+ // 创建连接
+ connection = await mysql.createConnection(dbConfig);
+
+ console.log('✅ 数据库连接成功!');
+
+ // 使用数据库
+ await connection.query('USE pronode_db');
+ console.log('✅ 已切换到 pronode_db 数据库');
+
+ // 验证用户数据
+ console.log('👥 验证用户数据...');
+ const [users] = await connection.query('SELECT id, email, name, createdAt FROM promptforge_users');
+ console.log(`✅ 找到 ${users.length} 个用户:`);
+ users.forEach(user => {
+ console.log(` - ${user.name} (${user.email}) - 创建于 ${user.createdAt}`);
+ });
+
+ // 验证模板数据
+ console.log('📝 验证模板数据...');
+ const [templates] = await connection.query('SELECT id, title, category, rating, usageCount FROM promptforge_templates');
+ console.log(`✅ 找到 ${templates.length} 个模板:`);
+ templates.forEach(template => {
+ console.log(` - ${template.title} (${template.category}) - 评分: ${template.rating} - 使用次数: ${template.usageCount}`);
+ });
+
+ // 验证系统配置
+ console.log('⚙️ 验证系统配置...');
+ const [configs] = await connection.query('SELECT config_key, value, type FROM promptforge_configs');
+ console.log(`✅ 找到 ${configs.length} 个配置项:`);
+ configs.forEach(config => {
+ console.log(` - ${config.config_key}: ${config.value} (${config.type})`);
+ });
+
+ // 显示表结构
+ console.log('📊 数据库表结构概览...');
+ const [tables] = await connection.query("SHOW TABLES LIKE 'promptforge_%'");
+ console.log('📋 PromptForge 相关表:');
+ tables.forEach(table => {
+ console.log(` - ${Object.values(table)[0]}`);
+ });
+
+ console.log('🎉 数据验证完成!');
+ return true;
+
+ } catch (error) {
+ console.error('❌ 数据验证失败:', error.message);
+ return false;
+ } finally {
+ if (connection) {
+ await connection.end();
+ console.log('🔌 数据库连接已关闭');
+ }
+ }
+}
+
+// 运行验证脚本
+verifyData().then(success => {
+ if (success) {
+ console.log('🎉 数据库表和数据验证成功!');
+ } else {
+ console.log('💥 数据库表和数据验证失败!');
+ }
+ process.exit(success ? 0 : 1);
+});