#!/usr/bin/env node /** * 生成部署用 zip,排除 node_modules、构建产物、.git、本地 .env 等。 * 用法: node pack.mjs * 输出: release/thebet365-deploy-YYYYMMDD-HHmmss.zip */ import { execSync } from 'node:child_process'; import { existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs'; import { basename, join } from 'node:path'; const root = process.cwd(); const projectName = basename(root); const parent = join(root, '..'); const stamp = new Date() .toISOString() .replace(/[-:]/g, '') .slice(0, 15) .replace('T', '-'); const outDir = join(root, 'release'); const outFile = join(outDir, `thebet365-deploy-${stamp}.zip`); /** 相对项目根目录的路径(tar 归档时加 projectName/ 前缀) */ const excludePaths = [ 'node_modules', 'apps/api/node_modules', 'apps/player/node_modules', 'apps/admin/node_modules', 'packages/shared/node_modules', '.claude', '.git', '.env', '.env.local', '.env.docker', 'apps/api/.env', 'apps/api/dist', 'apps/player/dist', 'apps/admin/dist', 'release', ]; mkdirSync(outDir, { recursive: true }); const sharedPublic = join(root, 'packages/shared/public'); const playersDir = join(sharedPublic, 'players'); if (!existsSync(playersDir)) { console.error('Missing packages/shared/public/players — player avatars not migrated.'); process.exit(1); } for (const name of readdirSync(sharedPublic, { withFileTypes: true })) { if (!name.isDirectory()) continue; if (name.name === 'flags' || name.name === 'players') continue; const legacy = join(sharedPublic, name.name); rmSync(legacy, { recursive: true, force: true }); console.log(`Removed legacy public dir: ${name.name}`); } const excludeArgs = excludePaths .map((p) => `--exclude=${projectName}/${p}`) .join(' '); const cmd = `tar -a -c -f "${outFile}" ${excludeArgs} -C "${parent}" "${projectName}"`; console.log('Packing deployment archive...'); console.log('Excluding:'); for (const p of excludePaths) console.log(` - ${p}/`); console.log(''); try { execSync(cmd, { stdio: 'inherit' }); } catch { console.error('\nPack failed. Ensure tar is available (Windows 10+ / Linux / macOS).'); process.exit(1); } const sizeMb = (statSync(outFile).size / (1024 * 1024)).toFixed(2); console.log(`\nDone: ${outFile}`); console.log(`Size: ${sizeMb} MB`); console.log('\nUpload to server, extract under /www/wwwroot/thebet365, then:'); console.log(' cp .env.docker.example .env.docker'); console.log(' docker compose -f docker-compose.prod.yml --env-file .env.docker up -d --build');