Files
hair-keeper/quickstart.sh

452 lines
13 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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-opus-4-6",
"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-6",
"background": "pku-anthropic,claude-haiku-4-5-20251001",
"think": "pku-anthropic,claude-opus-4-6",
"longContext": "pku-anthropic,claude-opus-4-6",
"longContextThreshold": 80000,
"webSearch": "",
"image": "pku-anthropic,claude-opus-4-6"
},
"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