UNPKG

ql-publish

Version:

159 lines (141 loc) 5.24 kB
const config = require('../config/config.js')[process.env.NODE_ENV]; const logger = require('../utils/logger'); const { Client } = require('ssh2'); const readline = require("readline"); const path = require("path"); const readStreamByFile = async (sftp, remoteFilePath) => { return new Promise((resolve) => { console.log(`准备读取文件: ${remoteFilePath}`); // 创建读取流 const readStream = sftp.createReadStream(remoteFilePath, { encoding: 'utf8' // 以UTF-8编码读取 }); let fileContent = ''; // 收集文件内容 readStream.on('data', (chunk) => { fileContent += chunk; }); // 读取完成处理 readStream.on('end', () => { try { // 解析JSON数据 const jsonData = JSON.parse(fileContent); console.log('文件内容解析成功:'); resolve(jsonData) } catch (parseErr) { logger.error('JSON解析失败:', parseErr); console.log('原始文件内容:', fileContent); process.exit(1); } }); // 处理读取错误 readStream.on('error', (err) => { logger.error('读取文件时发生错误:', err); process.exit(1); }); }) } const isHasDir = (sftp, dirPath) => { return new Promise(resolve => { sftp.stat(dirPath, (err) => { resolve(!err); }) }) } const authProjectName = () => { return new Promise((resolve) => { // 创建readline接口 const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); // 向用户提问 rl.question(`${process.env.NODE_ENV}环境:是否确认删除map映射文件 ${config.path} 项目? (输入 y 继续) `, (answer) => { // 检查用户输入是否为'y'(不区分大小写) if (answer.trim().toLowerCase() === 'y') { resolve(true); } else { logger.error('❌ 发布程序终止'); resolve(false); } // 关闭接口 rl.close(); }); }) } const deleteFileByMapJson = async (sftp, currentSourceDir, mtime) => { // 获取源目录中的所有项目 const items = await new Promise((resolve, reject) => { sftp.readdir(currentSourceDir, (err, list) => { if (err) { reject(new Error(`读取目录失败 ${currentSourceDir}: ${err.message}`)); } else { resolve(list); } }); }); // 处理每个项目 for (const item of items) { const sourcePath = path.posix.join(currentSourceDir, item.filename); if (item.attrs.isDirectory()) { // 如果是目录,递归处理 await deleteFileByMapJson(sftp, sourcePath, mtime); } else { // 删除文件 if (mtime >= item.attrs.mtime) { // console.log(`删除文件: ${sourcePath}`,); await sftp.unlink(sourcePath); } } } } async function run() { if (!await authProjectName()) { process.exit(1); } let conn, sftp; try { logger.warn('连接到服务器...'); // 连接到服务器 conn = new Client(); await new Promise((resolve, reject) => { conn.on('ready', resolve); conn.on('error', (err) => reject(new Error(`❌ 服务器连接失败: ${err.message}`))); conn.connect(config); }); logger.info('✅ 已成功连接到服务器'); // 初始化SFTP sftp = await new Promise((resolve, reject) => { conn.sftp((err, sftpClient) => { if (err) { reject(new Error(`SFTP初始化失败: ${err.message}`)); } else { resolve(sftpClient); } }); }); // 没有项目目录,直接返回 if (!await isHasDir(sftp, config.path)) { logger.warn('✅ 新项目,无需清理旧文件') return } // 没有map文件,直接返回 if (!await isHasDir(sftp, `${config.path}/fileMap.json`)) { logger.warn('✅ 没有map映射文件,无需清理旧文件') return } const { mtime } = await readStreamByFile(sftp, `${config.path}/fileMap.json`); logger.warn('正在删除文件...') await deleteFileByMapJson(sftp, config.path, mtime); await deleteFileByMapJson(sftp, config.path, mtime); logger.success(`✅ ${process.env.NODE_ENV}环境,根据map删除映射文件成功!`) } catch (err) { logger.error('❌ 过程出错:', err.message); } finally { // 关闭连接 if (sftp) sftp.end(); if (conn) conn.end(); // console.log('连接已关闭'); } } run();