Compare commits
3 Commits
4207d6e467
...
d93316be15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d93316be15 | ||
|
|
97614a9079 | ||
|
|
37fa4cf020 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
build.json
|
build.json
|
||||||
kit/.kit/modules/*
|
kit/.kit/modules/*
|
||||||
|
kit/publish/*
|
||||||
|
|||||||
78
kit/package-lock.json
generated
78
kit/package-lock.json
generated
@ -18,6 +18,7 @@
|
|||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
"physical-cpu-count": "^2.0.0",
|
"physical-cpu-count": "^2.0.0",
|
||||||
"sm-crypto": "^0.3.13",
|
"sm-crypto": "^0.3.13",
|
||||||
|
"ssh2": "^1.16.0",
|
||||||
"systeminformation": "^5.30.6",
|
"systeminformation": "^5.30.6",
|
||||||
"webdav": "^5.3.1"
|
"webdav": "^5.3.1"
|
||||||
},
|
},
|
||||||
@ -56,6 +57,15 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/applescript/-/applescript-1.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/applescript/-/applescript-1.0.0.tgz",
|
||||||
"integrity": "sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ=="
|
"integrity": "sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/asn1": {
|
||||||
|
"version": "0.2.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/asn1/-/asn1-0.2.6.tgz",
|
||||||
|
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": "~2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/auto-launch": {
|
"node_modules/auto-launch": {
|
||||||
"version": "5.0.6",
|
"version": "5.0.6",
|
||||||
"resolved": "https://registry.npmmirror.com/auto-launch/-/auto-launch-5.0.6.tgz",
|
"resolved": "https://registry.npmmirror.com/auto-launch/-/auto-launch-5.0.6.tgz",
|
||||||
@ -81,6 +91,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
|
||||||
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
|
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/bcrypt-pbkdf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"tweetnacl": "^0.14.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
@ -97,6 +116,15 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buildcheck": {
|
||||||
|
"version": "0.0.7",
|
||||||
|
"resolved": "https://registry.npmmirror.com/buildcheck/-/buildcheck-0.0.7.tgz",
|
||||||
|
"integrity": "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/byte-length": {
|
"node_modules/byte-length": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz",
|
||||||
@ -110,6 +138,20 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cpu-features": {
|
||||||
|
"version": "0.0.10",
|
||||||
|
"resolved": "https://registry.npmmirror.com/cpu-features/-/cpu-features-0.0.10.tgz",
|
||||||
|
"integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"buildcheck": "~0.0.6",
|
||||||
|
"nan": "^2.19.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cross-port-killer": {
|
"node_modules/cross-port-killer": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/cross-port-killer/-/cross-port-killer-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/cross-port-killer/-/cross-port-killer-1.4.0.tgz",
|
||||||
@ -417,6 +459,13 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/nan": {
|
||||||
|
"version": "2.27.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/nan/-/nan-2.27.0.tgz",
|
||||||
|
"integrity": "sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/nested-property": {
|
"node_modules/nested-property": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz",
|
||||||
@ -523,6 +572,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
|
||||||
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
|
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/sm-crypto": {
|
"node_modules/sm-crypto": {
|
||||||
"version": "0.3.13",
|
"version": "0.3.13",
|
||||||
"resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz",
|
"resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz",
|
||||||
@ -531,6 +586,23 @@
|
|||||||
"jsbn": "^1.1.0"
|
"jsbn": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ssh2": {
|
||||||
|
"version": "1.17.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/ssh2/-/ssh2-1.17.0.tgz",
|
||||||
|
"integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"asn1": "^0.2.6",
|
||||||
|
"bcrypt-pbkdf": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.16.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"cpu-features": "~0.0.10",
|
||||||
|
"nan": "^2.23.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/streamroller": {
|
"node_modules/streamroller": {
|
||||||
"version": "3.1.5",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz",
|
||||||
@ -575,6 +647,12 @@
|
|||||||
"url": "https://www.buymeacoffee.com/systeminfo"
|
"url": "https://www.buymeacoffee.com/systeminfo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tweetnacl": {
|
||||||
|
"version": "0.14.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||||
|
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||||
|
"license": "Unlicense"
|
||||||
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
"bin": "src/index.js",
|
"bin": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "bun src/index.js",
|
"test": "bun src/index.js",
|
||||||
|
"publish": "node publish.js",
|
||||||
"linux": "bun build.js && bun build ./src/index.js --compile --bytecode --minify --target=bun-linux-x64-baseline --outfile=./dist/linux/kit",
|
"linux": "bun build.js && bun build ./src/index.js --compile --bytecode --minify --target=bun-linux-x64-baseline --outfile=./dist/linux/kit",
|
||||||
"windows": "bun build.js && bun build ./src/index.js --compile --bytecode --minify --target=bun-windows-x64-baseline --outfile=./dist/windows/kit.exe",
|
"windows": "bun build.js && bun build ./src/index.js --compile --bytecode --minify --target=bun-windows-x64-baseline --outfile=./dist/windows/kit.exe",
|
||||||
"pkg-alpine": "bun build.js && pkg --compress GZip . -t node14-alpine-arm64 -o ./dist/alpine/kit",
|
"pkg-alpine": "bun build.js && pkg --compress GZip . -t node14-alpine-arm64 -o ./dist/alpine/kit",
|
||||||
@ -22,7 +23,9 @@
|
|||||||
"node-forge": "^1.3.1",
|
"node-forge": "^1.3.1",
|
||||||
"physical-cpu-count": "^2.0.0",
|
"physical-cpu-count": "^2.0.0",
|
||||||
"sm-crypto": "^0.3.13",
|
"sm-crypto": "^0.3.13",
|
||||||
|
"ssh2": "^1.16.0",
|
||||||
"systeminformation": "^5.30.6",
|
"systeminformation": "^5.30.6",
|
||||||
"webdav": "^5.3.1"
|
"webdav": "^5.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
116
kit/publish.js
Normal file
116
kit/publish.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { spawnSync } = require('child_process');
|
||||||
|
const JSON5 = require('json5');
|
||||||
|
|
||||||
|
const root = __dirname;
|
||||||
|
const publishDir = path.resolve(root, 'publish');
|
||||||
|
const artifacts = [
|
||||||
|
{
|
||||||
|
script: 'pkg-windows',
|
||||||
|
source: path.resolve(root, 'dist/windows/kit.exe'),
|
||||||
|
target: path.resolve(publishDir, 'windows/x86_64/kit.exe'),
|
||||||
|
localPath: 'publish/windows/x86_64/kit.exe',
|
||||||
|
os: 'windows',
|
||||||
|
arch: 'x86_64',
|
||||||
|
filename: 'kit.exe'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
script: 'pkg-linux',
|
||||||
|
source: path.resolve(root, 'dist/linux/kit'),
|
||||||
|
target: path.resolve(publishDir, 'linux/x86_64/kit'),
|
||||||
|
localPath: 'publish/linux/x86_64/kit',
|
||||||
|
os: 'linux',
|
||||||
|
arch: 'x86_64',
|
||||||
|
filename: 'kit'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function run(command, args) {
|
||||||
|
console.log(`> ${command} ${args.join(' ')}`);
|
||||||
|
const result = spawnSync(command, args, {
|
||||||
|
cwd: root,
|
||||||
|
stdio: 'inherit',
|
||||||
|
shell: process.platform === 'win32'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
throw result.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.status !== 0) {
|
||||||
|
process.exit(result.status || 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readJson(file) {
|
||||||
|
return JSON5.parse(fs.readFileSync(file, 'utf-8'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function readPackage() {
|
||||||
|
return readJson(path.resolve(root, 'package.json'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function readSourceMeta() {
|
||||||
|
const candidates = [
|
||||||
|
path.resolve(root, 'meta.json'),
|
||||||
|
path.resolve(root, '..', 'meta.json')
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const file of candidates) {
|
||||||
|
if (fs.existsSync(file)) {
|
||||||
|
return readJson(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyFile(source, target) {
|
||||||
|
if (!fs.existsSync(source)) {
|
||||||
|
throw new Error(`Build artifact not found: ${source}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
||||||
|
fs.copyFileSync(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeMeta() {
|
||||||
|
const pkg = readPackage();
|
||||||
|
const sourceMeta = readSourceMeta();
|
||||||
|
const meta = {
|
||||||
|
id: sourceMeta.id || pkg.name || 'kit',
|
||||||
|
name: sourceMeta.name || pkg.name || 'kit',
|
||||||
|
desc: sourceMeta.desc || sourceMeta.description || '',
|
||||||
|
group: sourceMeta.group || '/modules',
|
||||||
|
dist: artifacts.map((artifact) => ({
|
||||||
|
path: artifact.localPath,
|
||||||
|
os: artifact.os,
|
||||||
|
arch: artifact.arch,
|
||||||
|
filename: artifact.filename,
|
||||||
|
type: 'executable'
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.mkdirSync(publishDir, { recursive: true });
|
||||||
|
fs.writeFileSync(path.resolve(publishDir, 'meta.json'), JSON.stringify(meta, null, 4), 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
function preparePublishDir() {
|
||||||
|
fs.rmSync(publishDir, { recursive: true, force: true });
|
||||||
|
|
||||||
|
for (const artifact of artifacts) {
|
||||||
|
copyFile(artifact.source, artifact.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeMeta();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const artifact of artifacts) {
|
||||||
|
run('npm', ['run', artifact.script]);
|
||||||
|
}
|
||||||
|
|
||||||
|
preparePublishDir();
|
||||||
|
run('kit3', ['publish', './publish']);
|
||||||
|
|
||||||
|
console.log('Publish completed.');
|
||||||
@ -172,7 +172,7 @@ parser.addCmdLine("freem [level]", "释放内存", function (cli) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
parser.addCmdLine("docker runsh <container> [--file]", "反向获取 docker 容器启动脚本", function (cli) {
|
parser.addCmdLine("dockersh <container> [--file]", "反向获取 docker 容器启动脚本", function (cli) {
|
||||||
let container = cli.getParamValue("container")
|
let container = cli.getParamValue("container")
|
||||||
let file = cli.getParamValue("file")
|
let file = cli.getParamValue("file")
|
||||||
import("./docker/index.js").then(psl => psl.main(container, file))
|
import("./docker/index.js").then(psl => psl.main(container, file))
|
||||||
|
|||||||
@ -96,10 +96,24 @@ async function main(){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.addCmdLine("check", "验证远程仓库可达;", async function () {
|
parser.addCmdLine("check [module]", "验证远程仓库可达;指定 module 时查看远程 meta 信息;", async function (cli) {
|
||||||
const remote = await getAvailableRemote();
|
const remote = await getAvailableRemote();
|
||||||
if (remote) {
|
if (!remote) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const module = cli.getParamValue("module");
|
||||||
|
if (!module) {
|
||||||
$logger.info("远程仓库可用");
|
$logger.info("远程仓库可用");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = remote.parseProjectVersion(module);
|
||||||
|
const meta = await remote.getProjectMetadata(parsed.projectId, parsed.group);
|
||||||
|
$logger.info(JSON.stringify(meta, null, 4));
|
||||||
|
} catch (e) {
|
||||||
|
$logger.info(`远程 module 不存在: ${module}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -130,6 +144,7 @@ async function main(){
|
|||||||
}
|
}
|
||||||
await remote.publish(localFile, remotePath);
|
await remote.publish(localFile, remotePath);
|
||||||
$logger.info("发布成功");
|
$logger.info("发布成功");
|
||||||
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.addCmdLine("install [module]", "安装/更新模块; 支持 myapp、myapp@1.0、/docker/net/myapp", async function (cli) {
|
parser.addCmdLine("install [module]", "安装/更新模块; 支持 myapp、myapp@1.0、/docker/net/myapp", async function (cli) {
|
||||||
@ -168,3 +183,4 @@ async function main(){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -335,12 +335,155 @@ function scp(from, to, params = {}) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadSsh2Client() {
|
||||||
|
try {
|
||||||
|
return require("ssh2").Client;
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error("remoteShell requires pure JS dependency ssh2. Please run npm install ssh2 in kit project.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRemoteShellConfig(config = {}) {
|
||||||
|
const host = config.host || config.hostname;
|
||||||
|
if (!host) {
|
||||||
|
throw new Error("remoteShell host is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const username = config.username || config.user;
|
||||||
|
if (!username) {
|
||||||
|
throw new Error("remoteShell username is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const password = resolveScpPassword(config);
|
||||||
|
const privateKey = config.privateKey || config.keyText || (config.keyFile ? fs.readFileSync(path.resolve(config.keyFile), "utf-8") : undefined);
|
||||||
|
const connectConfig = Object.assign({}, config, {
|
||||||
|
host,
|
||||||
|
username,
|
||||||
|
port: config.port || 22,
|
||||||
|
password,
|
||||||
|
privateKey,
|
||||||
|
passphrase: resolveValue(config.passphrase)
|
||||||
|
});
|
||||||
|
|
||||||
|
delete connectConfig.user;
|
||||||
|
delete connectConfig.hostname;
|
||||||
|
delete connectConfig.pwd;
|
||||||
|
delete connectConfig.plainPwd;
|
||||||
|
delete connectConfig.plainPassword;
|
||||||
|
delete connectConfig.plaintextPwd;
|
||||||
|
delete connectConfig.plaintextPassword;
|
||||||
|
delete connectConfig.keyText;
|
||||||
|
delete connectConfig.keyFile;
|
||||||
|
|
||||||
|
return connectConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteShell(config = {}) {
|
||||||
|
const Client = loadSsh2Client();
|
||||||
|
const connectConfig = normalizeRemoteShellConfig(config);
|
||||||
|
let client = null;
|
||||||
|
let connectPromise = null;
|
||||||
|
|
||||||
|
function connect() {
|
||||||
|
if (client) {
|
||||||
|
return Promise.resolve(client);
|
||||||
|
}
|
||||||
|
if (connectPromise) {
|
||||||
|
return connectPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
connectPromise = new Promise((resolve, reject) => {
|
||||||
|
const conn = new Client();
|
||||||
|
conn.once("ready", () => {
|
||||||
|
client = conn;
|
||||||
|
resolve(conn);
|
||||||
|
});
|
||||||
|
conn.once("error", (e) => {
|
||||||
|
connectPromise = null;
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
conn.once("close", () => {
|
||||||
|
client = null;
|
||||||
|
connectPromise = null;
|
||||||
|
});
|
||||||
|
conn.connect(connectConfig);
|
||||||
|
});
|
||||||
|
return connectPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function exec(cmd, options = {}) {
|
||||||
|
if (!cmd) {
|
||||||
|
throw new Error("remoteShell exec cmd is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const conn = await connect();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const execOptions = Object.assign({}, options);
|
||||||
|
delete execOptions.stdio;
|
||||||
|
delete execOptions.rejectOnError;
|
||||||
|
conn.exec(cmd, execOptions, (err, stream) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stdout = "";
|
||||||
|
let stderr = "";
|
||||||
|
stream.on("error", reject);
|
||||||
|
stream.on("close", (code, signal) => {
|
||||||
|
const result = { code, signal, stdout, stderr };
|
||||||
|
if (options.rejectOnError === false || code === 0) {
|
||||||
|
resolve(result);
|
||||||
|
} else {
|
||||||
|
const error = new Error(`Remote command failed with code ${code}: ${cmd}`);
|
||||||
|
error.result = result;
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stream.on("data", (data) => {
|
||||||
|
const text = data.toString();
|
||||||
|
stdout += text;
|
||||||
|
if (options.stdio === "inherit") {
|
||||||
|
process.stdout.write(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stream.stderr.on("data", (data) => {
|
||||||
|
const text = data.toString();
|
||||||
|
stderr += text;
|
||||||
|
if (options.stdio === "inherit") {
|
||||||
|
process.stderr.write(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function execText(cmd, options = {}) {
|
||||||
|
const result = await exec(cmd, options);
|
||||||
|
return result.stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function call(cmd, options = {}) {
|
||||||
|
return exec(cmd, Object.assign({ stdio: "inherit" }, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
if (client) {
|
||||||
|
client.end();
|
||||||
|
}
|
||||||
|
client = null;
|
||||||
|
connectPromise = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { connect, exec, execText, call, close };
|
||||||
|
}
|
||||||
|
|
||||||
function exit(code = 0) {
|
function exit(code = 0) {
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSecretLogKey(key) {
|
function isSecretLogKey(key) {
|
||||||
return /^(pwd|password|plainPwd|plainPassword|plaintextPwd|plaintextPassword)$/i.test(key);
|
return /^(pwd|password|plainPwd|plainPassword|plaintextPwd|plaintextPassword|privateKey|passphrase|keyText)$/i.test(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function redactLogValue(value) {
|
function redactLogValue(value) {
|
||||||
@ -403,6 +546,7 @@ module.exports = {
|
|||||||
readJson: withCallLog("readJson", readJson),
|
readJson: withCallLog("readJson", readJson),
|
||||||
writeJson: withCallLog("writeJson", writeJson),
|
writeJson: withCallLog("writeJson", writeJson),
|
||||||
scp: withCallLog("scp", scp),
|
scp: withCallLog("scp", scp),
|
||||||
|
remoteShell: withCallLog("remoteShell", remoteShell),
|
||||||
exit: withCallLog("exit", exit),
|
exit: withCallLog("exit", exit),
|
||||||
setVar: withCallLog("setVar", setVar),
|
setVar: withCallLog("setVar", setVar),
|
||||||
getVar: withCallLog("getVar", getVar),
|
getVar: withCallLog("getVar", getVar),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user