import fs from 'fs'; import path from 'path'; import archiver from 'archiver'; import { exec } from 'child_process'; import { nanoid } from 'nanoid'; const cwd = process.cwd(); const pkgPath = path.join(cwd, 'package.json'); export const checkFileExistsSync = (filePath) => { try { // 使用 F_OK 检查文件或目录是否存在 fs.accessSync(filePath, fs.constants.F_OK); return true; } catch (err) { return false; } }; const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); const releasePath = path.join(cwd, 'release'); const distPath = path.join(cwd, 'dist'); const zip = archiver('zip', { zlib: { level: 9 }, }); const zipName = `code-center-${pkg.version}.zip`; const zipCache = path.join(releasePath, `code-center-${pkg.version}.zip`); const getZip = async () => { return new Promise((resolve, reject) => { const output = fs.createWriteStream(zipCache); const startTime = (new Date().getTime() / 1000).toFixed(0); // 监听事件 output.on('close', async () => { const bytes = zip.pointer(); const size = bytes < 1024 ? `${bytes} bytes` : `${(bytes / 1024).toFixed(2)} KB`; console.log(`Zip file has been created successfully. Total size: ${size} bytes.`); let time = (new Date().getTime() / 1000).toFixed(0); console.log('time', time - startTime); resolve(); }); output.on('end', () => { console.log('Data has been drained.'); // 数据已被耗尽 throw new CustomError('Data has been drained.'); }); zip.on('warning', (err) => { if (err.code === 'ENOENT') { console.warn('File not found:', err); } else { throw err; } }); zip.on('error', (err) => { throw err; }); // 通过管道将 zip 数据流输出到指定文件 zip.pipe(output); // 添加 sh 字符串作为文件到 zip 中 const sh = `#!/bin/bash npm i -g pnpm pnpm install --prod `; zip.append(sh, { name: 'start.sh' }); // 把dist目录下的文件添加到zip中 zip.directory(distPath, 'dist'); // 把README.md添加到zip中 zip.file(path.join(cwd, 'README.md'), { name: 'README.md' }); // 把package.json添加到zip中 zip.file(pkgPath, { name: 'package.json' }); const ecosystemContent = `module.exports = { apps: [ { name: 'codecenter', // 应用名称 script: './dist/app.mjs', // 入口文件 // cwd: '.', // 设置当前工作目录 output: './logs/codecenter.log', error: './logs/codecenter.log', log_date_format: 'YYYY-MM-DD HH:mm:ss', // watch: true, // 自动监控文件变化 watch: ['dist'], // 监控的文件夹 ignore_watch: ['node_modules', 'logs'], // 忽略的文件夹 } ] } `; zip.append(ecosystemContent, { name: 'ecosystem.config.cjs' }); const json5Content = fs.readFileSync(path.join(cwd, 'app.config.json5.example'), 'utf8'); // tokenSecret 是一个随机字符串,用于生成 token const tokenSecret = 'XX' + nanoid(39); json5Content.replace('', tokenSecret); // tokenSecret // 把app.config.json5.example添加到zip中 // zip.file(path.join(cwd, 'app.config.json5.example'), { name: 'app.config.json5.example' }); zip.append(json5Content, { name: 'app.config.json5.example' }); // 结束归档(必须调用,否则 zip 文件无法完成) zip.finalize(); }); }; getZip().then(() => { console.log('zip success'); console.log(`envision switchOrg system && envision deploy ./release/${zipName} -v 1.0.0 -k code-center -y y -u`); console.log(`download zip: https://kevisual.xiongxiao.me/system/code-center/${zipName}`); });