mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-10 16:51:11 +08:00
90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
import Client from "ssh2-sftp-client";
|
|
import { Plugin } from "vite";
|
|
|
|
export interface FtpSyncTarget {
|
|
host: string;
|
|
port: number;
|
|
username: string;
|
|
password: string;
|
|
remotePath: string;
|
|
localPath?: string;
|
|
clearRemote?: boolean;
|
|
}
|
|
|
|
// 创建日志工具
|
|
const logger = {
|
|
pluginName: "vite-plugin-ftp-sync",
|
|
info: (message: string) => {
|
|
console.log(`\x1b[36m[${logger.pluginName}]\x1b[0m \x1b[32m${message}\x1b[0m`);
|
|
},
|
|
warn: (message: string) => {
|
|
console.warn(`\x1b[36m[${logger.pluginName}]\x1b[0m \x1b[33m${message}\x1b[0m`);
|
|
},
|
|
error: (message: string, err?: any) => {
|
|
console.error(`\x1b[36m[${logger.pluginName}]\x1b[0m \x1b[31m${message}\x1b[0m`, err || "");
|
|
},
|
|
success: (message: string) => {
|
|
console.log(`\x1b[36m[${logger.pluginName}]\x1b[0m \x1b[32m${message} ✓\x1b[0m`);
|
|
}
|
|
};
|
|
|
|
export function ftpSync(options: FtpSyncTarget[] | FtpSyncTarget): Plugin {
|
|
return {
|
|
name: "vite-plugin-ftp-sync",
|
|
apply: "build",
|
|
closeBundle: async () => {
|
|
if (!Array.isArray(options)) options = [options];
|
|
const results = await Promise.allSettled(
|
|
options.map(async (target) => {
|
|
const sftp = new Client();
|
|
try {
|
|
await sftp.connect({
|
|
host: target.host,
|
|
port: target.port,
|
|
username: target.username,
|
|
password: target.password,
|
|
});
|
|
|
|
const localPath = target.localPath || "dist";
|
|
logger.info(
|
|
`开始同步文件到 SFTP 服务器 ${target.host}:${target.port} -> ${target.remotePath}`,
|
|
);
|
|
|
|
if (target.clearRemote) {
|
|
logger.info(`正在清除远程目录 ${target.remotePath}...`);
|
|
try {
|
|
await sftp.rmdir(target.remotePath, true);
|
|
logger.success(`远程目录 ${target.remotePath} 已清除`);
|
|
} catch (err) {
|
|
logger.warn(`清除远程目录失败,可能目录不存在: ${err}`);
|
|
}
|
|
}
|
|
|
|
await sftp.uploadDir(localPath, target.remotePath);
|
|
logger.success(`文件同步到 ${target.host} 完成!`);
|
|
|
|
sftp.end();
|
|
return { target, success: true };
|
|
} catch (err) {
|
|
logger.error(`SFTP 同步到 ${target.host} 失败:`, err);
|
|
sftp.end();
|
|
return { target, success: false, error: err };
|
|
}
|
|
}),
|
|
);
|
|
|
|
const failures = results.filter(
|
|
(result): result is PromiseRejectedResult =>
|
|
result.status === "rejected",
|
|
);
|
|
|
|
if (failures.length > 0) {
|
|
logger.error(`部分 SFTP 同步失败: ${failures.length} 个目标`);
|
|
throw new Error(`部分 SFTP 同步失败: ${failures.length} 个目标`);
|
|
} else {
|
|
logger.success("所有同步任务已成功完成");
|
|
}
|
|
},
|
|
};
|
|
}
|