Files
asciidisco.com/build/tasks/deploy.js
2023-08-01 13:49:46 +02:00

84 lines
4.2 KiB
JavaScript

const path = require('path')
const Client = require('ftp')
const filewalker = require('filewalker')
const chalk = require('chalk')
const log = console.log;
/* FTP functions */
// create client instance
const client = new Client()
// connect to server
const connect = (options) => new Promise((resolve, reject) => client.on('ready', () => resolve()) && client.connect(options))
// get list of files/dirs in root directory
const list = () => new Promise((resolve, reject) => client.list((err, list) => err ? reject(err) : resolve(list)))
// recursively create a directory structure on the server
const mkdir = name => new Promise((resolve, reject) => client.mkdir(name, true, err => err ? reject(err) : resolve(name)))
// recursively remove a directory structure from the server
const rmdir = name => new Promise((resolve, reject) => client.rmdir(name, true, err => err ? reject(err) : resolve(name)))
// remove a file from the server
const remove_file = name => new Promise((resolve, reject) => client.delete(name, err => err ? reject(err) : resolve(name)))
// transfer a file to the server (binary mode by default)
const transfer_file = (local, remote) => new Promise((resolve, reject) => client.put(local, remote, err => err ? reject(err) : resolve([local, remote])))
// close the connection
const close = () => client.end()
/* Path matching functions */
// find local folders & files that should be transferred
const find_paths = (basepath, dist_path) => {
return new Promise((resolve, reject) => {
let paths = []
filewalker(path.join(basepath, dist_path))
.on('file', file => file.search('.htaccess') !== -1 ? false : paths.push([path.join(basepath, dist_path, file), file]))
.on('done', () => resolve(paths))
.walk()
})
}
// get a list of directories that need to be created on the server
const get_dirs_to_create = files => files.map(file => path.dirname(file[1])).filter((item, i, ar) => ar.indexOf(item) === i).filter(item => item !== '.' && item !== '..')
// get a list of directories that should be deleted on the server
const get_dirs_to_delete = paths => paths.filter(path => path.type === 'd' && path.name !== '.' && path.name !== '..').sort((a, b) => parseInt(a.name) < parseInt(b.name)).filter((_, idx, arr) => arr.length < 3 ? false : idx >= 2).map(path => path.name)
/* Runner */
module.exports = config => {
// get config vars
const root_dir = config.root_dir
const basepath = config.basepath
const dist_path = config.dist_path
const options = config.ftp_options
// run async deployment
return new Promise(async (resolve, reject) => {
try {
// make a list of files to be transferred to the server
const files_to_transfer = await find_paths(basepath, dist_path)
// make a list of subfolders to be created
const dirs_to_create = get_dirs_to_create(files_to_transfer)
// connect to the server
log(' ', chalk.green('>>'), 'Connecting to server')
await connect(options)
// fetch the list of existing folders & delete the oldest one and his .htaccess backup
log(' ', chalk.green('>>'), 'Deleting oldest deployments')
const existing_folders = await list()
const folders_to_delete = get_dirs_to_delete(existing_folders)
let delete_promises = []
folders_to_delete.forEach(dir => delete_promises.push(rmdir(dir)))
folders_to_delete.forEach(dir => delete_promises.push(remove_file(dir + '.htaccess')))
await Promise.all(delete_promises)
// create the new directories & transfer the files
log(' ', chalk.green('>>'), 'Uploading assets')
let create_promises = []
dirs_to_create.forEach(dir => create_promises.push(mkdir(path.join(root_dir, dir))))
files_to_transfer.forEach(file => create_promises.push(transfer_file(file[0], path.join(root_dir, file[1]))))
await Promise.all(create_promises)
// transfer .htaccess file
log(' ', chalk.green('>>'), 'Uploading .htaccess changes')
await transfer_file(path.join(basepath, dist_path, '.htaccess'), '.htaccess')
await transfer_file(path.join(basepath, dist_path, '.htaccess'), root_dir + '.htaccess')
// close the connection
log(' ', chalk.green('>>'), 'Closing connection')
close()
resolve(root_dir)
} catch(err) {
reject(err)
}
})
}