173 lines
4.5 KiB
JavaScript
173 lines
4.5 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
import { execSync } from 'child_process'
|
||
import fs from 'fs'
|
||
|
||
// 颜色输出
|
||
const colors = {
|
||
reset: '\x1b[0m',
|
||
red: '\x1b[31m',
|
||
green: '\x1b[32m',
|
||
yellow: '\x1b[33m',
|
||
cyan: '\x1b[36m'
|
||
}
|
||
const BUILD_MEMORY_MB = 6144
|
||
const DEFAULT_NODE_OPTIONS = `--max-old-space-size=${BUILD_MEMORY_MB}`
|
||
|
||
function log(message, color = 'reset') {
|
||
console.log(`${colors[color]}${message}${colors.reset}`)
|
||
}
|
||
|
||
function logStep(step, message) {
|
||
log(`${step} ${message}`, 'cyan')
|
||
}
|
||
|
||
function logSuccess(message) {
|
||
log(`✅ ${message}`, 'green')
|
||
}
|
||
|
||
function logWarning(message) {
|
||
log(`⚠️ ${message}`, 'yellow')
|
||
}
|
||
|
||
function logError(message) {
|
||
log(`❌ ${message}`, 'red')
|
||
}
|
||
|
||
// 安全执行命令
|
||
function safeExec(command, options = {}) {
|
||
try {
|
||
execSync(command, { stdio: 'inherit', ...options })
|
||
return true
|
||
} catch (error) {
|
||
logError(`命令执行失败: ${command}`)
|
||
logError(error.message)
|
||
return false
|
||
}
|
||
}
|
||
|
||
// 检查文件是否存在
|
||
function fileExists(filePath) {
|
||
try {
|
||
return fs.existsSync(filePath)
|
||
} catch {
|
||
return false
|
||
}
|
||
}
|
||
|
||
// Netlify 构建流程
|
||
async function netlifyBuild() {
|
||
log('🚀 Netlify 构建', 'cyan')
|
||
|
||
try {
|
||
// 1. 设置环境变量
|
||
process.env.NETLIFY = 'true'
|
||
process.env.NITRO_PRESET = 'netlify'
|
||
|
||
// 2. 清理构建目录
|
||
logStep('🧹', '清理构建目录...')
|
||
if (fileExists('dist')) safeExec('rm -rf dist')
|
||
if (fileExists('.netlify')) safeExec('rm -rf .netlify')
|
||
if (fileExists('.nuxt')) safeExec('rm -rf .nuxt')
|
||
logSuccess('清理完成')
|
||
|
||
// 3. 安装依赖
|
||
logStep('📦', '安装依赖...')
|
||
let installed = false
|
||
if (fileExists('node_modules')) {
|
||
safeExec('rm -rf node_modules')
|
||
}
|
||
|
||
if (fileExists('pnpm-lock.yaml')) {
|
||
if (safeExec('pnpm install --frozen-lockfile')) {
|
||
installed = true
|
||
logSuccess('依赖安装完成 (pnpm install --frozen-lockfile)')
|
||
} else {
|
||
logWarning('pnpm install --frozen-lockfile 安装失败,准备回退到 pnpm install...')
|
||
}
|
||
} else {
|
||
logWarning('未检测到 pnpm-lock.yaml,跳过冻结锁文件安装,直接使用 pnpm install...')
|
||
}
|
||
|
||
if (!installed) {
|
||
if (!safeExec('pnpm install')) {
|
||
throw new Error('依赖安装失败')
|
||
}
|
||
logSuccess('依赖安装完成 (pnpm install)')
|
||
}
|
||
|
||
// 验证 Drizzle 依赖
|
||
if (!safeExec('pnpm list drizzle-orm drizzle-kit')) {
|
||
if (!safeExec('pnpm add drizzle-orm drizzle-kit')) {
|
||
throw new Error('Drizzle 依赖安装失败')
|
||
}
|
||
}
|
||
// 4. 检查 Drizzle 配置
|
||
if (!fileExists('drizzle.config.ts') || !fileExists('app/drizzle/schema.ts')) {
|
||
throw new Error('Drizzle 配置文件不完整')
|
||
}
|
||
|
||
// 5. 确保迁移目录存在
|
||
if (!fileExists('app/drizzle/migrations')) {
|
||
fs.mkdirSync('app/drizzle/migrations', { recursive: true })
|
||
}
|
||
|
||
// 6. 数据库同步
|
||
if (process.env.DATABASE_URL) {
|
||
logStep('�️', '同步数据库...')
|
||
const env = { ...process.env, CI: 'true', DRIZZLE_KIT_FORCE: 'true', NODE_ENV: 'production' }
|
||
if (safeExec('node scripts/db-sync.js', { env })) {
|
||
logSuccess('数据库同步成功')
|
||
} else {
|
||
logWarning('数据库同步失败')
|
||
}
|
||
|
||
// 检查管理员账户
|
||
if (fileExists('scripts/create-admin.js')) {
|
||
logStep('👤', '检查管理员账户...')
|
||
safeExec('pnpm run create-admin', { env })
|
||
}
|
||
} else {
|
||
logWarning('未设置 DATABASE_URL')
|
||
}
|
||
|
||
// 7. 构建应用
|
||
logStep('🔨', '构建应用...')
|
||
const buildEnv = {
|
||
...process.env,
|
||
NODE_OPTIONS: process.env.NODE_OPTIONS || DEFAULT_NODE_OPTIONS
|
||
}
|
||
if (!safeExec('pnpm exec nuxt build', { env: buildEnv })) {
|
||
throw new Error('构建失败')
|
||
}
|
||
logSuccess('构建完成')
|
||
|
||
// 8. 验证构建输出
|
||
const hasNetlifyFunctions = fileExists('.netlify/functions-internal/server')
|
||
const hasOutputPublic = fileExists('.output/public')
|
||
|
||
if (hasNetlifyFunctions) {
|
||
logSuccess('Netlify Functions 生成成功')
|
||
}
|
||
|
||
if (hasOutputPublic) {
|
||
logSuccess('静态资源生成成功')
|
||
}
|
||
|
||
if (!hasNetlifyFunctions && !hasOutputPublic) {
|
||
throw new Error('构建输出目录不存在')
|
||
}
|
||
|
||
log('🎉 构建完成!', 'green')
|
||
} catch (error) {
|
||
logError(`构建失败: ${error.message}`)
|
||
process.exit(1)
|
||
}
|
||
}
|
||
|
||
// 运行构建
|
||
netlifyBuild().catch((error) => {
|
||
logError(`未预期的错误: ${error.message}`)
|
||
process.exit(1)
|
||
})
|