// ============================================================ // 发布版本信息到后端 API // // 用法: // node scripts/publish-release.mjs [version] [--url ] // // 环境变量: // UPDATE_API_URL — API 基地址(默认 https://www.heixiu.com) // UPDATE_API_KEY — API 鉴权 Key(通过 Authorization: Bearer 头传递) // ============================================================ import { readFileSync, readdirSync } from 'node:fs'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import axios from 'axios'; const __dirname = dirname(fileURLToPath(import.meta.url)); const ROOT = join(__dirname, '..'); // ---------- 参数 ---------- const args = process.argv.slice(2); const positional = []; let urlOverride = ''; let jsonOverride = ''; for (let i = 0; i < args.length; i++) { if (args[i] === '--url' && args[i + 1]) { urlOverride = args[++i]; } else if (args[i] === '--json' && args[i + 1]) { jsonOverride = args[++i]; } else if (!args[i].startsWith('--')) { positional.push(args[i]); } } const platform = positional[0]; if (!platform) { console.error('用法: node scripts/publish-release.mjs [version] [--url ]'); console.error('示例: node scripts/publish-release.mjs win32 0.1.0'); process.exit(1); } const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8')); const version = positional[1] || pkg.version; // ---------- 读取 update-info.json ---------- let updateInfo; if (jsonOverride) { try { updateInfo = JSON.parse(jsonOverride); } catch { console.error('错误: --json 参数不是有效的 JSON'); process.exit(1); } } else { const releaseDir = join(ROOT, 'release', version); let infoFile; try { const all = readdirSync(releaseDir); infoFile = all.find((f) => f.includes(platform) && f.endsWith('-update-info.json'), ); if (!infoFile) console.error(`未找到 ${platform} 的 update-info.json`); } catch (err) { console.error(`错误: ${releaseDir} — ${err.message}`); process.exit(1); } updateInfo = JSON.parse(readFileSync(join(releaseDir, infoFile), 'utf-8')); if (urlOverride) updateInfo.downloadUrl = urlOverride; } // ---------- 发送到 API ---------- const apiBase = (process.env.UPDATE_API_URL || 'https://www.heixiu.com').replace(/\/+$/, ''); const apiKey = process.env.UPDATE_API_KEY || ''; const payload = { platform, latestVersion: updateInfo.latestVersion || version, downloadUrl: updateInfo.downloadUrl, fileSize: updateInfo.fileSize, sha512: updateInfo.sha512, changelog: updateInfo.changelog, releaseDate: updateInfo.releaseDate, forceUpdate: updateInfo.forceUpdate || false, minimumVersion: updateInfo.minimumVersion || '0.0.0', }; const endpoint = `${apiBase}/api/v1/releases`; console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log('📡 发布版本到 API'); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); console.log(`POST ${endpoint}`); console.log(`版本: ${version} (${platform})`); console.log(`URL: ${payload.downloadUrl}\n`); try { const response = await axios.post(endpoint, payload, { headers: { 'Content-Type': 'application/json', ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}), }, timeout: 30000, }); console.log('✅ 发布成功'); console.log(`响应: ${JSON.stringify(response.data, null, 2)}`); } catch (err) { const status = err.response?.status; const data = err.response?.data; if (status) { console.error(`❌ 发布失败 HTTP ${status}: ${JSON.stringify(data)}`); } else { console.error(`❌ 请求失败: ${err.message}`); } console.log('\n💡 手动备选 — 把以下 JSON 发给后端:'); console.log(JSON.stringify(payload, null, 2)); process.exit(1); } console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');