albertgao.common-electron
Version:
个人常用的nodejs/electron模块
158 lines (157 loc) • 6.39 kB
JavaScript
module.exports = {
/**
* 运行Python或Js文件
*
* @param {object}param0 选项
* @param {string}param0.filePath 主Python文件的所在路径
* @param {object}param0.togetherWith 选项
* @param {string[]}param0.togetherWith.files 主Python文件依赖的其他文件
* @param {boolean}[param0.togetherWith.relative=true] files是否相对于filePath所在目录,默认为true
* @param {boolean}param0.isPython 是否为Python,默认根据后缀自动判断
* @param {*}[param0.msgTo=[]] Python中 "json.loads(sys.stdin.read())"接收; NodeJs中 process.on('message',(msgTo)=>{ ...to do}) 接收msgTo
* @param {string}[param0.atDir=filePath所在目录] 要在哪个目录下运行Python文件,默认为原目录
* @param {string[]}[param0.copyFiles=[]] 需要拷贝到atDir运行的文件(夹),运行后会删除临时拷过来的文件
* @param {Function}[param0.onMsg=(result)=>0] 对进程发送的信息进行处理的函数, 参数为发回来的信息, (先callBack后resolve)
* @param {boolean}[param0.killOnMsg=false] 是否在收到1条信息后就kill这个process
* @param {boolean}[param0.returnRaw=false] Python返回原始数据,不将字符串转为Json, 不对js生效
* @returns {Promise}返回Pyhton中 print(json.dumps(result))中的result,或者如果没有结果的话,在python文件exit时返回Undefined
* @description 在Python中使用"json.loads(sys.stdin.read())"接收msgTo (需要import sys;import json; )
* @description 在NodeJs中 process.on('message',(msgTo)=>{ ...to do}) 接收msgTo
* @description 在Python中使用"print(json.dumps(result))" 返回结果 (需要import json; )
* @description 在NodeJs中 process.send(result) 来返回结果
*/
runScript: function ({
filePath: originPath,
togetherWith: { files: env = [], relative = true } = {},
atDir = require('path').dirname(originPath),
msgTo = [],
isPython = /py$/i.test(require('path').extname(originPath)),
copyFiles = [],
onMsg = () => 0,
killOnMsg = false,
returnRaw = false
}) {
return new Promise((resolve, reject) => {
const [Path, Fs, { PythonShell }, childProcess] = [
require('path'),
require('fs-extra'),
require('python-shell'),
require('child_process')
]
const [runOrigin, newPyPath, newEnvPath, newCopyFilesPath] = [
atDir === Path.dirname(originPath), // 是否在Python文件的原位置运行
Path.join(atDir, Path.basename(originPath)), // 新的Python文件位置
[...env].map((origin) => {
// 新的Env文件位置
if (relative) {
return Path.join(atDir, origin)
} else {
return Path.join(
atDir,
Path.relative(Path.dirname(originPath), origin)
)
}
}),
[...copyFiles].map((e) => Path.join(atDir, Path.basename(e)))
]
if (!runOrigin) {
// 如果不是在原位置运行
Fs.copySync(originPath, newPyPath, { overwrite: true }) // 把Python原文件拷贝过去
newEnvPath.forEach((dest, i) => {
// 把环境文件拷贝过去
if (relative) {
Fs.copySync(Path.join(Path.dirname(originPath), env[i]), dest, {
overwrite: true
})
} else {
Fs.copySync(env[i], dest, { overwrite: true })
}
})
}
copyFiles.forEach((e, i) =>
Fs.copySync(e, newCopyFilesPath[i], { overwrite: true })
)
const removeFiles = () => {
// 最后删除文件
if (!runOrigin) {
Fs.removeSync(newPyPath)
newEnvPath.forEach((e) => Fs.removeSync(e))
}
newCopyFilesPath.forEach((e) => Fs.removeSync(e))
}
if (isPython) {
const pyshell = new PythonShell(newPyPath, { mode: 'text' })
pyshell.send(JSON.stringify(msgTo)) // 在Python文件中sys.stdin.read()
pyshell.on('message', (msg) => {
// 在Python文件中 print(json.dumps(result))
try {
const result = returnRaw ? msg : JSON.parse(msg)
onMsg(result)
resolve(result) // 有两个resolve
killOnMsg && pyshell.kill()
} catch (error) {
// 如果不能parse,那么可能不是主动print
}
})
pyshell.on('error', (msg) => reject(msg))
pyshell.end((err, exitCode) => {
console.log('Python run ended:', { err, exitCode })
resolve()
removeFiles()
})
} else {
const jsShell = childProcess.fork(newPyPath)
jsShell.on('message', (msg) => {
onMsg(msg)
resolve(msg)
if (killOnMsg) {
jsShell.kill()
console.log('Javascript run ended', { by: 'kill' })
removeFiles()
}
})
jsShell.send(msgTo)
jsShell.on('error', (err) => reject(err))
jsShell.on('exit', (code, signal) => {
console.log('Javascript run ended:', { code, signal })
resolve()
removeFiles()
})
}
})
},
/**
* 运行Docker MongoDb
*
* @param {string} [cwd=cwd()/Mongodb] 在哪个目录运行
* @param {string} [options={'--name': 'my-mongo-db','-v': `${dbPath}:/data/db`,'-p': `${port}:27017`}] 参数
* @returns {string} 由于执行失败,所以仅返回该指令
*/
async runDockerMongo(
cwd = require('path').join(process.cwd(), 'MongoDb'),
options
) {
const { getUnOccupiedPort } = require('./express-wss')
const path = require('path')
const port = await getUnOccupiedPort(27017)
const dbPath = path.join(process.cwd(), 'MongoDb/database')
options = options || {
'--name': 'my-mongo-db',
'-v': `${dbPath}:/data/db`,
'-p': `${port}:27017`
}
let args = 'docker run'
for (const key in options) {
args += ` ${key} ${options[key]}`
}
args += ` -d mongo:latest`
console.log(args)
return args
// return await new Promise((resolve, reject) => {
// require('child_process').exec(args, { cwd }, (error, stdout, stderr) => {
// console.log({ 'mongo-server running at ': { port, dbPath } })
// resolve({ error, stdout, stderr, port, dbPath })
// })
// })
}
}