mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-08 15:51:11 +08:00
【新增】插件git同步模块,用于同步项目内容,加速项目开发
【调整】前端暗色问题
This commit is contained in:
46
frontend/plugin/vite-plugin-ftp-sync/README.md
Normal file
46
frontend/plugin/vite-plugin-ftp-sync/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Vite FTP/SFTP Sync Plugin
|
||||
|
||||
这是一个用于 Vite 构建后自动同步文件到 SFTP 服务器的插件。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
pnpm add @tools/ftp-sync -D
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
在 `vite.config.ts` 中配置:
|
||||
|
||||
```typescript
|
||||
import { defineConfig } from 'vite';
|
||||
import ftpSync from '@tools/ftp-sync';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
ftpSync({
|
||||
host: 'your-sftp-host',
|
||||
port: 22,
|
||||
username: 'your-username',
|
||||
password: 'your-password',
|
||||
remotePath: '/path/on/remote/server',
|
||||
localPath: 'dist' // 可选,默认为 'dist'
|
||||
})
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
## 配置选项
|
||||
|
||||
- `host`: SFTP 服务器地址
|
||||
- `port`: SFTP 端口号(默认 22)
|
||||
- `username`: SFTP 用户名
|
||||
- `password`: SFTP 密码
|
||||
- `remotePath`: 远程服务器上的目标路径
|
||||
- `localPath`: 本地要上传的目录路径(可选,默认为 'dist')
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 该插件仅在构建模式下运行
|
||||
2. 确保有正确的 SFTP 服务器访问权限
|
||||
3. 建议将敏感信息(如密码)存储在环境变量中
|
||||
26
frontend/plugin/vite-plugin-ftp-sync/package.json
Normal file
26
frontend/plugin/vite-plugin-ftp-sync/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@baota/vite-plugin-ftp-sync",
|
||||
"version": "1.0.0",
|
||||
"description": "FTP/SFTP sync plugin for build process",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc -w"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"ssh2-sftp-client": "^12.0.0",
|
||||
"@types/ssh2-sftp-client": "^9.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0",
|
||||
"@types/node": "^20.0.0",
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
89
frontend/plugin/vite-plugin-ftp-sync/src/index.ts
Normal file
89
frontend/plugin/vite-plugin-ftp-sync/src/index.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
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("所有同步任务已成功完成");
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
15
frontend/plugin/vite-plugin-ftp-sync/tsconfig.json
Normal file
15
frontend/plugin/vite-plugin-ftp-sync/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "CommonJS",
|
||||
"lib": ["ES2020"],
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user