import path from 'path' import fs from 'fs/promises' import { spawn } from 'child_process' import { fileURLToPath, pathToFileURL } from 'url' export default class Util { constructor(root_import_meta_url) { this._root_import_meta_url = root_import_meta_url } getPathFromRoot(add) { const __dirname = path.dirname(fileURLToPath(this._root_import_meta_url)); return path.join(__dirname,'./', add) } getUrlFromRoot(add) { return path.join(this._root_import_meta_url,'../', add) } getExtension(filename) { let extension = path.extname(filename) if (filename.indexOf('.tar.') > 0) { return '.tar' + extension } return extension } getAppNames(config) { let out = [] let keys = Object.keys(config) for (let key of keys) { if (typeof(config[key]) !== 'object' || config[key] == null) continue if (typeof(config[key].port) !== 'number' || !config[key].port) continue if (typeof(config[key].provider) !== 'string' || !config[key].provider) continue out.push(key) } return out } get7zipExecutable() { const util = new Util(import.meta.url) if (process.platform === 'win32') { return util.getPathFromRoot('../bin/7za.exe') } return util.getPathFromRoot('../bin/7zas') } verifyConfig(config) { if (!config.name) throw new Error('name is missing in config.json') if (this.getAppNames(config).length === 0) throw new Error('no application was found in config') if (config.debugPort != null && (typeof(config.debugPort) !== 'number' || !config.debugPort)) throw new Error('debugPort in config not a valid number') } extractFile(file, stream = function() {}) { return this.runCommand(this.get7zipExecutable(), ['x', file], path.dirname(file), stream) .then(() => { if (!file.indexOf('.tar.')) return let tarFile = file.slice(0, file.lastIndexOf('.')) return fs.stat(tarFile) .catch(function() { return null }) .then((stat) => { if (!stat) return return this.extractFile(tarFile) .then(function() { return fs.rm(tarFile, { force: true }) }) }) }) } runCommand(command, options = [], folder = null, stream = function() {}) { return new Promise(function(res, rej) { stream(`[Command] ${folder ? folder : ''}${command} ${options.join(' ')}\n`) let processor = spawn(command, options, { shell: true, cwd: folder, }) let timeOuter = setInterval(function() { processor.stdin.write('n\n') }, 250) processor.stdout.on('data', function(data) { stream(data.toString()) }) processor.stderr.on('data', function(data) { stream(data.toString()) }) processor.on('error', function(err) { clearInterval(timeOuter) rej(err) }) processor.on('exit', function (code) { clearInterval(timeOuter) if (code !== 0) { return rej(new Error('Program returned error code: ' + code)) } res(code) }) }) } }