@tangelo/tangelo-configuration-toolkit
Version:
Tangelo Configuration Toolkit is a command-line toolkit which offers support for developing a Tangelo configuration.
64 lines (53 loc) • 2.5 kB
JavaScript
const path = require('path');
const pLimit = require('p-limit');
const sftpClient = require('ssh2-sftp-client');
const through2 = require('through2');
module.exports = function(ftpConfig, remotedir) {
const sftp = new sftpClient();
const serial = pLimit(1);
const parallel = pLimit(ftpConfig.parallel);
const files = [];
return through2.obj(
function transform (file, _, cb) {
if (file.isStream()) return cb(new Error('Streaming not supported.'));
if (file.stat?.isDirectory()) return cb();
file.destination = path.join(remotedir, file.relative).toFws;
files.push(file); // collect all files in array
return cb();
},
async function flush(cb) {
if (!files[0]) cb();
const paths = [...new Set(files.map(({destination}) => path.dirname(destination)))] // collect unique paths
.filter((p1, i, a) => !a.find(p2 => p1 != p2 && p2.includes(p1+'/'))) // remove paths being part of others
;
await ftpConfig.eventBeforeAll(files);
sftp.connect(ftpConfig)
.then(() => Promise.all(paths.map(p => parallel( // check if all directories exist
() => sftp.exists(p).then(r => {
if (r) paths.splice(paths.indexOf(p), 1); // if exists, remove from paths
})
))))
.then(() => Promise.all(paths.map(p => serial( // create directories that do not exist, which cannot be done parallel
() => {
_write(p.replace(remotedir, '').lblack);
return sftp.mkdir(p, true).catch(err => _warn(err));
}
))))
.then(() => Promise.all(files.map(file => parallel( // upload files
() => {
ftpConfig.eventPut(file);
return ( // use fastPut for files larger than 3mb; since it requires a local path we assume these files are not changed in the gulp pipeline
file.contents.length > 3000000 ? sftp.fastPut(file.originalRelativePath, file.destination) : sftp.put(file.contents, file.destination)
).catch(err => _warn(`File transfer failed${err ? ': '+err : ''}`));
}
))))
.then(async () => {
await ftpConfig.eventAfterAll(files);
cb();
return sftp.end();
})
.catch(err => _error(`Could not connect to server${err ? ': '+err.message : ''}`));
}
)
.resume(); // required for triggering 'end' event
};