UNPKG

folder-upload-webpack-plugin

Version:

Upload your folder to ssh sftp server after build, add support to 'webpack --watch'

142 lines (121 loc) 4.23 kB
import * as console from "console"; import {Client as Ssh2Client, ConnectConfig, Client} from "ssh2"; import SftpClient from "ssh2-sftp-client"; import chalk, {Chalk} from "chalk"; import path from "path"; import ProgressBar from "./ProgressBar"; import {clearTimeout} from "timers"; const fs = require('fs') const promiseRepeat = function(promise: () => Promise<any>, ms = 3000, attempt = 0) { return new Promise((resolve, reject) => { promiseTimeout(promise, ms).then(result => { resolve(result); }).catch(async (err) => { attempt++; if(attempt < 3) return await promiseRepeat(promise, ms, attempt); reject(err); }); }) } const promiseTimeout = function(promise: () => Promise<any>, ms = 3000){ let timeout = new Promise((resolve, reject) => { let id = setTimeout(() => { clearTimeout(id); reject('Timed out in '+ ms + 'ms.') }, ms) }) return Promise.race([ promise, timeout ]) } export default class SshClient { private readonly logging: boolean|undefined; private progress: boolean; private options: ConnectConfig; private sftp: SftpClient; private streams: number = 10; constructor(log:boolean|undefined = false, progress = true, streams = 10) { this.logging = log; this.progress = progress; this.streams = streams } async connect(options: ConnectConfig = {}) { this.options = options; this.sftp = new SftpClient(); await this.sftp.connect({...this.options}); } async ssh2connect(config: ConnectConfig): Promise<Client> { return await new Promise((resolve, reject) => { let conn = new Ssh2Client(); conn.on('ready', () => resolve(conn)).on('error', reject).connect(config) return conn; }) } async exists(remotePath:string) { let exits = await this.sftp.exists(remotePath); return !!exits; } async mkdir(remotePath:string, recursive?: boolean) { return await this.sftp.mkdir(remotePath, recursive); } async rmdir(remotePath:string) { return await this.sftp.rmdir(remotePath); } async sendFile(files: Array<{ remotePath:string,name:string,fillPath:string }>) { let self = this; let uploaded = 0; const pb = new ProgressBar('Sending...', 20); if (files.length > 0) { let sliced_array: Array<Array<{ remotePath:string,name:string,fillPath:string }>> = []; let i = 0; files.map((item) => { if(!sliced_array[i]) sliced_array[i] = [] sliced_array[i].push(item); if(sliced_array[i].length > this.streams) i++; }); for (let i in sliced_array) { await Promise.all(sliced_array[i].map(file => { if (!fs.existsSync(file.fillPath)) { throw new Error(`File: ${file.fillPath} not exist!`) } let remoteFile = path.resolve(file.remotePath + file.name); this.log('Put: ' + file.fillPath + ' to server ' + remoteFile, chalk.yellow); return this.sftp.fastPut(file.fillPath, remoteFile, {mode: 0o777}).then(result => { uploaded++; self.progress && pb.render({ percent: parseFloat((uploaded / files.length).toFixed(4)), completed: uploaded, total: files.length, }) }).catch(err => { this.log(err, chalk.red.bold) return async function retry() { return await self.sftp.fastPut(file.fillPath, remoteFile, {mode: 0o777}); }(); }); })).catch(err => { this.log(err, chalk.red.bold) }); } } } async symlink(remotePath: string) { return await this.sftp.mkdir(remotePath, true); } async delete(path: string) { return await this.sftp.delete(path); } async chmod(path: string, chmod: number|string) { return await this.sftp.chmod(path, chmod); } async end() { await this.sftp.end(); } log(text: string, formatter:Chalk = chalk) { if(!this.logging) { return; } console.log(formatter(text)); } }