forked from admin/hair-keeper
451 lines
13 KiB
Bash
Executable File
451 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# Hair Keeper 模板项目快速配置脚本
|
||
# 用于帮助用户快速配置环境变量和开发工具
|
||
|
||
set -e
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 打印带颜色的信息
|
||
print_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
print_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
print_warning() {
|
||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||
}
|
||
|
||
print_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
print_header() {
|
||
echo ""
|
||
echo -e "${CYAN}========================================${NC}"
|
||
echo -e "${CYAN} $1${NC}"
|
||
echo -e "${CYAN}========================================${NC}"
|
||
echo ""
|
||
}
|
||
|
||
# 读取用户输入,支持默认值
|
||
read_input() {
|
||
local prompt="$1"
|
||
local default="$2"
|
||
local allow_empty="$3"
|
||
local result
|
||
|
||
if [ -n "$default" ]; then
|
||
echo -n "$prompt [默认: $default]: " >&2
|
||
read result
|
||
result="${result:-$default}"
|
||
else
|
||
if [ "$allow_empty" = "true" ]; then
|
||
echo -n "$prompt (可为空): " >&2
|
||
read result
|
||
else
|
||
while [ -z "$result" ]; do
|
||
echo -n "$prompt: " >&2
|
||
read result
|
||
if [ -z "$result" ]; then
|
||
print_warning "此项不能为空,请重新输入"
|
||
fi
|
||
done
|
||
fi
|
||
fi
|
||
echo "$result"
|
||
}
|
||
|
||
# 读取密码输入(隐藏输入)
|
||
read_password() {
|
||
local prompt="$1"
|
||
local allow_empty="$2"
|
||
local result
|
||
|
||
if [ "$allow_empty" = "true" ]; then
|
||
echo -n "$prompt (可为空): " >&2
|
||
read -s result
|
||
echo "" >&2
|
||
else
|
||
while [ -z "$result" ]; do
|
||
echo -n "$prompt: " >&2
|
||
read -s result
|
||
echo "" >&2
|
||
if [ -z "$result" ]; then
|
||
print_warning "此项不能为空,请重新输入"
|
||
fi
|
||
done
|
||
fi
|
||
echo "$result"
|
||
}
|
||
|
||
# 生成随机密码
|
||
generate_password() {
|
||
local length="$1"
|
||
if command -v pwgen &> /dev/null; then
|
||
pwgen -s "$length" 1
|
||
else
|
||
# 如果没有 pwgen,使用 openssl 或 /dev/urandom
|
||
if command -v openssl &> /dev/null; then
|
||
openssl rand -base64 "$length" | tr -dc 'a-zA-Z0-9' | head -c "$length"
|
||
else
|
||
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c "$length"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
# 选择菜单
|
||
select_option() {
|
||
local prompt="$1"
|
||
shift
|
||
local options=("$@")
|
||
local choice
|
||
|
||
echo "$prompt" >&2
|
||
for i in "${!options[@]}"; do
|
||
echo " $((i+1)). ${options[$i]}" >&2
|
||
done
|
||
|
||
while true; do
|
||
echo -n "请输入选项编号: " >&2
|
||
read choice
|
||
if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#options[@]}" ]; then
|
||
echo "$choice"
|
||
return
|
||
fi
|
||
print_warning "无效选项,请重新输入"
|
||
done
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
print_header "Hair Keeper 模板项目快速配置"
|
||
|
||
echo "本脚本将帮助您快速配置项目环境变量和开发工具"
|
||
echo ""
|
||
|
||
# ==================== 环境变量配置 ====================
|
||
print_header "环境变量配置"
|
||
|
||
# --- PostgreSQL 配置 ---
|
||
print_info "配置 PostgreSQL 数据库..."
|
||
echo ""
|
||
|
||
POSTGRESQL_USERNAME=$(read_input "PostgreSQL 用户名" "postgres")
|
||
POSTGRESQL_PASSWORD=$(read_password "PostgreSQL 密码" "true")
|
||
POSTGRESQL_PORT=$(read_input "PostgreSQL 端口" "5432")
|
||
|
||
echo ""
|
||
db_url_choice=$(select_option "DATABASE_URL 配置方式:" "自动构造 PostgreSQL URL" "手动输入完整 URL")
|
||
|
||
if [ "$db_url_choice" = "1" ]; then
|
||
POSTGRESQL_HOSTNAME=$(read_input "PostgreSQL 主机名" "postgresql")
|
||
POSTGRESQL_DBNAME=$(read_input "PostgreSQL 数据库名" "postgres")
|
||
POSTGRESQL_SCHEMA=$(read_input "PostgreSQL 模式名" "public")
|
||
|
||
if [ -n "$POSTGRESQL_PASSWORD" ]; then
|
||
DATABASE_URL="postgresql://${POSTGRESQL_USERNAME}:${POSTGRESQL_PASSWORD}@${POSTGRESQL_HOSTNAME}:${POSTGRESQL_PORT}/${POSTGRESQL_DBNAME}?schema=${POSTGRESQL_SCHEMA}"
|
||
else
|
||
DATABASE_URL="postgresql://${POSTGRESQL_USERNAME}@${POSTGRESQL_HOSTNAME}:${POSTGRESQL_PORT}/${POSTGRESQL_DBNAME}?schema=${POSTGRESQL_SCHEMA}"
|
||
fi
|
||
else
|
||
DATABASE_URL=$(read_input "DATABASE_URL" "")
|
||
fi
|
||
|
||
echo ""
|
||
print_success "PostgreSQL 配置完成"
|
||
echo ""
|
||
|
||
# --- Redis 配置 ---
|
||
print_info "配置 Redis..."
|
||
echo ""
|
||
|
||
REDIS_HOST=$(read_input "Redis 主机名" "redis")
|
||
REDIS_PORT=$(read_input "Redis 端口" "6379")
|
||
REDIS_PASSWORD=$(read_password "Redis 密码" "true")
|
||
|
||
echo ""
|
||
print_success "Redis 配置完成"
|
||
echo ""
|
||
|
||
# --- MinIO 配置 ---
|
||
print_info "配置 MinIO 对象存储..."
|
||
echo ""
|
||
|
||
MINIO_ENDPOINT=$(read_input "MinIO 端点地址" "minio")
|
||
MINIO_API_PORT=$(read_input "MinIO API 端口" "9000")
|
||
MINIO_CONSOLE_PORT=$(read_input "MinIO 控制台端口" "9001")
|
||
MINIO_USE_SSL=$(read_input "MinIO 是否使用 SSL (true/false)" "false")
|
||
MINIO_ROOT_USER=$(read_input "MinIO 用户名" "admin")
|
||
MINIO_ROOT_PASSWORD=$(read_password "MinIO 密码" "true")
|
||
MINIO_SERVER_URL=$(read_input "MinIO 服务器 URL (用于生成公开访问链接)" "" "true")
|
||
MINIO_BUCKET=$(read_input "MinIO 存储桶名称" "app-files")
|
||
|
||
echo ""
|
||
print_success "MinIO 配置完成"
|
||
echo ""
|
||
|
||
# --- 应用配置 ---
|
||
print_info "配置应用参数..."
|
||
echo ""
|
||
|
||
SUPER_ADMIN_PASSWORD=$(generate_password 16)
|
||
USER_DEFAULT_PASSWORD=$(generate_password 16)
|
||
NEXTAUTH_SECRET=$(generate_password 32)
|
||
|
||
print_info "已自动生成以下密码:"
|
||
echo " SUPER_ADMIN_PASSWORD: $SUPER_ADMIN_PASSWORD"
|
||
echo " USER_DEFAULT_PASSWORD: $USER_DEFAULT_PASSWORD"
|
||
echo " NEXTAUTH_SECRET: $NEXTAUTH_SECRET"
|
||
echo ""
|
||
|
||
DB_PARALLEL_LIMIT=$(read_input "数据库批次操作默认并发数" "32")
|
||
|
||
echo ""
|
||
print_success "应用参数配置完成"
|
||
echo ""
|
||
|
||
# --- AI API 配置 ---
|
||
print_info "配置 AI API..."
|
||
echo ""
|
||
|
||
PKUAI_API_KEY=$(read_password "PKU AI API Key" "true")
|
||
PKUAI_API_BASE=$(read_input "PKU AI API Base URL" "https://chat.noc.pku.edu.cn/")
|
||
|
||
echo ""
|
||
print_success "AI API 配置完成"
|
||
echo ""
|
||
|
||
# --- 开发环境配置 ---
|
||
print_info "配置开发环境参数..."
|
||
echo ""
|
||
|
||
DEV_PORT=$(read_input "开发服务器端口" "3000")
|
||
DEV_TERMINAL_PORT=$(read_input "开发终端默认端口" "7681")
|
||
DEV_TERMINAL_URL=$(read_input "开发终端 URL" "" "true")
|
||
DEV_TERMINAL=$(read_input "开发终端 tmux session 名称" "nextdev")
|
||
|
||
echo ""
|
||
print_success "开发环境配置完成"
|
||
echo ""
|
||
|
||
# ==================== 写入配置文件 ====================
|
||
print_header "写入配置文件"
|
||
|
||
# 写入 .env 文件
|
||
print_info "写入 .env 文件..."
|
||
cat > .env << EOF
|
||
# ==================== 容器相关 ====================
|
||
POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME}
|
||
POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD}
|
||
POSTGRESQL_PORT=${POSTGRESQL_PORT}
|
||
DATABASE_URL="${DATABASE_URL}"
|
||
|
||
REDIS_HOST=${REDIS_HOST}
|
||
REDIS_PORT=${REDIS_PORT}
|
||
REDIS_PASSWORD=${REDIS_PASSWORD}
|
||
|
||
MINIO_ENDPOINT=${MINIO_ENDPOINT}
|
||
MINIO_API_PORT=${MINIO_API_PORT}
|
||
MINIO_CONSOLE_PORT=${MINIO_CONSOLE_PORT}
|
||
MINIO_USE_SSL=${MINIO_USE_SSL}
|
||
MINIO_ROOT_USER=${MINIO_ROOT_USER}
|
||
MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
|
||
MINIO_SERVER_URL=${MINIO_SERVER_URL}
|
||
MINIO_BUCKET=${MINIO_BUCKET}
|
||
|
||
# ==================== 应用相关 ====================
|
||
SUPER_ADMIN_PASSWORD=${SUPER_ADMIN_PASSWORD}
|
||
USER_DEFAULT_PASSWORD=${USER_DEFAULT_PASSWORD}
|
||
## 数据库批次操作默认并发数
|
||
DB_PARALLEL_LIMIT=${DB_PARALLEL_LIMIT}
|
||
|
||
# ==================== NextAuth.js Configuration ====================
|
||
NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||
|
||
# ==================== AI API ====================
|
||
PKUAI_API_KEY=${PKUAI_API_KEY}
|
||
PKUAI_API_BASE=${PKUAI_API_BASE}
|
||
EOF
|
||
print_success ".env 文件已创建"
|
||
|
||
# 写入 .env.development 文件
|
||
print_info "写入 .env.development 文件..."
|
||
cat > .env.development << EOF
|
||
# 仅在开发环境加载
|
||
PORT=${DEV_PORT}
|
||
NEXT_PUBLIC_DEV_TERMINAL_DEFAULT_PORT=${DEV_TERMINAL_PORT}
|
||
NEXT_PUBLIC_DEV_TERMINAL_URL=${DEV_TERMINAL_URL}
|
||
DEV_TERMINAL=${DEV_TERMINAL}
|
||
EOF
|
||
print_success ".env.development 文件已创建"
|
||
|
||
# 写入 .env.production 文件
|
||
print_info "写入 .env.production 文件..."
|
||
cat > .env.production << EOF
|
||
# 仅在生产环境加载
|
||
EOF
|
||
print_success ".env.production 文件已创建"
|
||
|
||
# ==================== Claude Code 编程代理配置 ====================
|
||
print_header "Claude Code 编程代理配置"
|
||
|
||
# 重命名 CLAUDE.md
|
||
if [ -f "CLAUDE.md" ]; then
|
||
print_info "重命名 CLAUDE.md 为 TEMPLATE_README.md..."
|
||
mv CLAUDE.md TEMPLATE_README.md
|
||
print_success "CLAUDE.md 已重命名为 TEMPLATE_README.md"
|
||
fi
|
||
|
||
# 创建新的 CLAUDE.md
|
||
print_info "创建新的 CLAUDE.md..."
|
||
cat > CLAUDE.md << 'EOF'
|
||
# CLAUDE.md
|
||
|
||
本文件为 AI 代理(如 Claude)提供在本代码库中工作的指导说明。
|
||
|
||
## 项目说明
|
||
|
||
本项目基于 Hair Keeper 模板构建(详见 @TEMPLATE_README.md),目前尚未实现业务功能
|
||
EOF
|
||
print_success "新的 CLAUDE.md 已创建"
|
||
|
||
# 清空 README.md
|
||
print_info "清空 README.md..."
|
||
> README.md
|
||
print_success "README.md 已清空"
|
||
|
||
# 创建 Claude Code Router 配置
|
||
print_info "配置 Claude Code Router..."
|
||
mkdir -p ~/.claude-code-router
|
||
|
||
cat > ~/.claude-code-router/config.json << EOF
|
||
{
|
||
"LOG": false,
|
||
"LOG_LEVEL": "debug",
|
||
"CLAUDE_PATH": "",
|
||
"HOST": "127.0.0.1",
|
||
"PORT": 3456,
|
||
"APIKEY": "",
|
||
"API_TIMEOUT_MS": "600000",
|
||
"PROXY_URL": "",
|
||
"transformers": [],
|
||
"Providers": [
|
||
{
|
||
"name": "pku-anthropic",
|
||
"api_base_url": "${PKUAI_API_BASE}api/anthropic/v1/messages",
|
||
"api_key": "${PKUAI_API_KEY}",
|
||
"models": [
|
||
"claude-sonnet-4-5-20250929",
|
||
"claude-opus-4-5-20251101",
|
||
"claude-haiku-4-5-20251001"
|
||
],
|
||
"transformer": {
|
||
"use": [
|
||
"Anthropic"
|
||
]
|
||
}
|
||
}
|
||
],
|
||
"StatusLine": {
|
||
"enabled": false,
|
||
"currentStyle": "default",
|
||
"default": {
|
||
"modules": []
|
||
},
|
||
"powerline": {
|
||
"modules": []
|
||
}
|
||
},
|
||
"Router": {
|
||
"default": "pku-anthropic,claude-opus-4-5-20251101",
|
||
"background": "pku-anthropic,claude-haiku-4-5-20251001",
|
||
"think": "pku-anthropic,claude-opus-4-5-20251101",
|
||
"longContext": "pku-anthropic,claude-opus-4-5-20251101",
|
||
"longContextThreshold": 80000,
|
||
"webSearch": "",
|
||
"image": "pku-anthropic,claude-opus-4-5-20251101"
|
||
},
|
||
"CUSTOM_ROUTER_PATH": ""
|
||
}
|
||
EOF
|
||
print_success "Claude Code Router 配置已写入 ~/.claude-code-router/config.json"
|
||
|
||
# ==================== Git 版本控制初始化 ====================
|
||
print_header "Git 版本控制初始化"
|
||
|
||
# 删除模板项目的 git 仓库
|
||
if [ -d ".git" ]; then
|
||
print_info "删除模板项目的 git 仓库..."
|
||
rm -rf .git
|
||
print_success "已删除 .git 目录"
|
||
fi
|
||
|
||
# 获取用户的 git 配置信息
|
||
print_info "配置 Git 用户信息..."
|
||
echo ""
|
||
|
||
GIT_USER_EMAIL=$(read_input "Git 用户邮箱" "")
|
||
GIT_USER_NAME=$(read_input "Git 用户名" "")
|
||
|
||
echo ""
|
||
git init
|
||
git config init.defaultBranch main
|
||
print_info "设置 Git 用户配置..."
|
||
git config user.email "$GIT_USER_EMAIL"
|
||
git config user.name "$GIT_USER_NAME"
|
||
print_success "Git 用户配置已设置"
|
||
|
||
# 初始化新的 git 仓库
|
||
print_info "初始化 Git 仓库..."
|
||
git add .
|
||
git commit -m "init"
|
||
git branch -M main
|
||
print_success "Git 仓库已初始化并完成首次提交 (主分支: main)"
|
||
|
||
# 配置远程仓库
|
||
echo ""
|
||
print_info "配置远程仓库 (格式: https://用户名:密码@gitea.example.com/用户名/仓库名.git)"
|
||
GIT_REMOTE_URL=$(read_input "远程仓库链接" "" "true")
|
||
|
||
if [ -n "$GIT_REMOTE_URL" ]; then
|
||
git remote add origin "$GIT_REMOTE_URL"
|
||
print_success "远程仓库已配置: $GIT_REMOTE_URL"
|
||
else
|
||
print_info "跳过远程仓库配置"
|
||
fi
|
||
|
||
# ==================== 完成提示 ====================
|
||
print_header "配置完成!"
|
||
|
||
echo -e "${GREEN}所有配置已完成!${NC}"
|
||
echo ""
|
||
echo "Claude Code 编程代理使用说明:"
|
||
echo -e " ${CYAN}ccr code${NC} - 打开 Claude Code 编程代理,可通过对话完成编程任务"
|
||
echo -e " ${CYAN}ccr ui${NC} - 配置 Claude Code 编程代理对接的大模型"
|
||
echo -e " ${CYAN}ccr code --resume${NC} - 查看历史对话"
|
||
echo ""
|
||
echo "接下来您可以进行以下操作:"
|
||
echo -e " ${CYAN}1. pnpm install${NC} - 安装依赖包"
|
||
echo -e " ${CYAN}2. pnpm prisma migrate dev${NC} - 迁移数据库并初始化 Prisma 客户端"
|
||
echo -e " ${CYAN}3. pnpm run db:seed${NC} - 初始化数据库数据"
|
||
echo -e " ${CYAN}4. pnpm run dev${NC} - 运行开发服务器"
|
||
echo -e " ${CYAN}5. ccr code${NC} - 打开编程代理后,先输入 ${YELLOW}/init <我的项目的主要功能是...>${NC} 初始化"
|
||
echo " 然后再开始使用 AI 完成编程任务"
|
||
echo ""
|
||
print_success "祝您开发愉快!"
|
||
}
|
||
|
||
# 运行主函数
|
||
main
|