2022-02-14 08:15:50 +00:00
|
|
|
import os from 'os'
|
2020-09-07 00:47:53 +00:00
|
|
|
import path from 'path'
|
2022-01-24 17:06:40 +00:00
|
|
|
import fs from 'fs/promises'
|
2022-02-14 08:15:50 +00:00
|
|
|
import { spawn, execSync } from 'child_process'
|
2020-09-07 18:15:11 +00:00
|
|
|
import { fileURLToPath, pathToFileURL } from 'url'
|
2020-09-07 00:47:53 +00:00
|
|
|
|
2020-09-08 08:11:42 +00:00
|
|
|
export default class Util {
|
|
|
|
constructor(root_import_meta_url) {
|
|
|
|
this._root_import_meta_url = root_import_meta_url
|
|
|
|
}
|
2020-09-07 00:47:53 +00:00
|
|
|
|
2020-09-08 08:11:42 +00:00
|
|
|
getPathFromRoot(add) {
|
|
|
|
const __dirname = path.dirname(fileURLToPath(this._root_import_meta_url));
|
|
|
|
return path.join(__dirname,'./', add)
|
|
|
|
}
|
2020-09-07 18:15:11 +00:00
|
|
|
|
2020-09-08 08:11:42 +00:00
|
|
|
getUrlFromRoot(add) {
|
|
|
|
return path.join(this._root_import_meta_url,'../', add)
|
|
|
|
}
|
|
|
|
|
2022-01-21 02:43:48 +00:00
|
|
|
getExtension(filename) {
|
|
|
|
let extension = path.extname(filename)
|
|
|
|
if (filename.indexOf('.tar.') > 0) {
|
|
|
|
return '.tar' + extension
|
|
|
|
}
|
|
|
|
return extension
|
|
|
|
}
|
|
|
|
|
|
|
|
getAppNames(config) {
|
2022-02-04 09:33:03 +00:00
|
|
|
const validLevels = [
|
|
|
|
'fatal',
|
|
|
|
'error',
|
|
|
|
'warn',
|
|
|
|
'info',
|
|
|
|
'debug',
|
|
|
|
'trace',
|
|
|
|
]
|
2022-01-21 02:43:48 +00:00
|
|
|
let out = []
|
|
|
|
let keys = Object.keys(config)
|
|
|
|
for (let key of keys) {
|
2022-02-04 09:33:03 +00:00
|
|
|
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
|
|
|
|
if (config[key].https != null && typeof(config[key].https) !== 'boolean')
|
|
|
|
continue
|
|
|
|
if (config[key].updateEvery != null && (typeof(config[key].updateEvery) !== 'number' || config[key].updateEvery < 0))
|
|
|
|
continue
|
|
|
|
if (config[key].startWaitUntilFail != null && (typeof(config[key].startWaitUntilFail) !== 'number' || config[key].startWaitUntilFail < 10))
|
|
|
|
continue
|
|
|
|
if (config[key].heartbeatTimeout != null && (typeof(config[key].heartbeatTimeout) !== 'number' || config[key].heartbeatTimeout < 10))
|
|
|
|
continue
|
|
|
|
if (config[key].heartbeatAttempts != null && (typeof(config[key].heartbeatAttempts) !== 'number' || config[key].heartbeatAttempts < 1))
|
|
|
|
continue
|
|
|
|
if (config[key].heartbeatAttemptsWait != null && (typeof(config[key].heartbeatAttemptsWait) !== 'number' || config[key].heartbeatAttemptsWait < 10))
|
|
|
|
continue
|
|
|
|
if (config[key].heartbeatPath != null && (typeof(config[key].heartbeatPath) !== 'string' || config[key].heartbeatPath[0] !== '/'))
|
|
|
|
continue
|
|
|
|
if (config[key].log != null) {
|
|
|
|
if (!Array.isArray(config[key].log))
|
|
|
|
continue
|
|
|
|
let valid = true
|
|
|
|
for (let stream of config[key].log) {
|
|
|
|
if (!stream || typeof(stream) !== 'object' || Array.isArray(stream)) {
|
|
|
|
valid = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if (typeof(stream.level) !== 'string' || !stream.level || !validLevels.includes(stream.level)) {
|
|
|
|
valid = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if ((typeof(stream.path) !== 'string' || !stream.path) && stream.stream !== 'process.stdout') {
|
|
|
|
valid = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!valid)
|
|
|
|
continue
|
|
|
|
}
|
2022-01-21 02:43:48 +00:00
|
|
|
|
|
|
|
out.push(key)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
get7zipExecutable() {
|
|
|
|
const util = new Util(import.meta.url)
|
|
|
|
if (process.platform === 'win32') {
|
2022-02-16 11:49:48 +00:00
|
|
|
return util.getPathFromRoot('../bin/7zdec.exe')
|
2022-01-21 02:43:48 +00:00
|
|
|
}
|
2022-02-16 11:49:48 +00:00
|
|
|
return util.getPathFromRoot('../bin/7zdec')
|
2022-01-21 02:43:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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')
|
|
|
|
}
|
2022-01-24 17:06:40 +00:00
|
|
|
|
|
|
|
extractFile(file, stream = function() {}) {
|
2022-02-16 11:49:48 +00:00
|
|
|
let program = this.get7zipExecutable()
|
|
|
|
let args = ['x', file]
|
|
|
|
if (file.indexOf('.tar.') > 0) {
|
|
|
|
program = 'tar'
|
|
|
|
args = ['xvf', file]
|
|
|
|
}
|
|
|
|
return this.runCommand(program, args, path.dirname(file), stream)
|
2022-01-24 17:06:40 +00:00
|
|
|
}
|
2022-01-21 02:43:48 +00:00
|
|
|
|
2020-09-08 08:11:42 +00:00
|
|
|
runCommand(command, options = [], folder = null, stream = function() {}) {
|
2022-02-16 11:49:48 +00:00
|
|
|
|
|
|
|
let baseError = new Error('')
|
|
|
|
|
2020-09-08 08:11:42 +00:00
|
|
|
return new Promise(function(res, rej) {
|
2022-01-27 18:25:33 +00:00
|
|
|
let fullcommand = path.join(folder ? folder : '', command)
|
|
|
|
if (command.indexOf('/') >= 0 || command.indexOf('\\') >= 0) {
|
|
|
|
fullcommand = command
|
|
|
|
}
|
|
|
|
stream(`[Command] ${fullcommand} ${options.join(' ')}\n`)
|
2020-09-08 08:11:42 +00:00
|
|
|
let processor = spawn(command, options, {
|
|
|
|
shell: true,
|
|
|
|
cwd: folder,
|
|
|
|
})
|
2022-01-11 16:51:15 +00:00
|
|
|
let timeOuter = setInterval(function() {
|
2022-01-27 18:25:33 +00:00
|
|
|
try {
|
|
|
|
processor.stdin.write('n\n')
|
|
|
|
} catch {}
|
2020-09-08 08:11:42 +00:00
|
|
|
}, 250)
|
|
|
|
processor.stdout.on('data', function(data) {
|
2022-01-27 18:25:33 +00:00
|
|
|
stream(data.toString().replace(/\r\n/g, '\n'))
|
2020-09-08 08:11:42 +00:00
|
|
|
})
|
|
|
|
processor.stderr.on('data', function(data) {
|
2022-01-27 18:25:33 +00:00
|
|
|
stream(data.toString().replace(/\r\n/g, '\n'))
|
2020-09-08 08:11:42 +00:00
|
|
|
})
|
2022-02-14 08:15:50 +00:00
|
|
|
processor.stdin.on('error', function() {
|
|
|
|
clearInterval(timeOuter)
|
|
|
|
})
|
2020-09-08 08:11:42 +00:00
|
|
|
processor.on('error', function(err) {
|
|
|
|
clearInterval(timeOuter)
|
2022-02-16 11:49:48 +00:00
|
|
|
baseError.message = err.message
|
|
|
|
rej(baseError)
|
2020-09-08 08:11:42 +00:00
|
|
|
})
|
|
|
|
processor.on('exit', function (code) {
|
|
|
|
clearInterval(timeOuter)
|
|
|
|
if (code !== 0) {
|
2022-02-16 11:49:48 +00:00
|
|
|
baseError.message = 'Program returned error code: ' + code
|
|
|
|
return rej(baseError)
|
2020-09-08 08:11:42 +00:00
|
|
|
}
|
|
|
|
res(code)
|
|
|
|
})
|
2020-09-07 00:47:53 +00:00
|
|
|
})
|
2020-09-08 08:11:42 +00:00
|
|
|
}
|
2022-02-14 08:15:50 +00:00
|
|
|
|
|
|
|
runCommandBackground(command, options = [], folder = null, stream = function() {}) {
|
|
|
|
let fullcommand = path.join(folder ? folder : '', command)
|
|
|
|
if (command.indexOf('/') >= 0 || command.indexOf('\\') >= 0) {
|
|
|
|
fullcommand = command
|
|
|
|
}
|
|
|
|
stream(`[Command] ${fullcommand} ${options.join(' ')}\n`)
|
|
|
|
let processor = spawn(command, options, {
|
|
|
|
shell: true,
|
|
|
|
cwd: folder,
|
|
|
|
})
|
|
|
|
let timeOuter = setInterval(function() {
|
|
|
|
try {
|
|
|
|
processor.stdin.write('n\n')
|
|
|
|
} catch {}
|
|
|
|
}, 250)
|
|
|
|
processor.stdout.on('data', function(data) {
|
|
|
|
stream(data.toString().replace(/\r\n/g, '\n'))
|
|
|
|
})
|
|
|
|
processor.stderr.on('data', function(data) {
|
|
|
|
stream(data.toString().replace(/\r\n/g, '\n'))
|
|
|
|
})
|
|
|
|
processor.stdin.on('error', function() {
|
|
|
|
clearInterval(timeOuter)
|
|
|
|
})
|
|
|
|
processor.on('error', function(err) {
|
|
|
|
clearInterval(timeOuter)
|
|
|
|
})
|
|
|
|
processor.on('exit', function (code) {
|
|
|
|
clearInterval(timeOuter)
|
|
|
|
})
|
|
|
|
|
|
|
|
processor._kill = processor.kill
|
|
|
|
processor.kill = function() {
|
|
|
|
if(os.platform() === 'win32'){
|
2022-02-15 11:28:30 +00:00
|
|
|
try {
|
|
|
|
execSync('taskkill /pid ' + processor.pid + ' /T /F')
|
|
|
|
} catch {}
|
2022-02-14 08:15:50 +00:00
|
|
|
}else{
|
|
|
|
processor.kill();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return processor
|
|
|
|
}
|
2020-09-07 00:47:53 +00:00
|
|
|
}
|