Compare commits

..

No commits in common. "d93316be1588a7f19d2cba654cf084c7fce4a05a" and "4207d6e46779bc006c0b0ba40d0052f678df211a" have entirely different histories.

7 changed files with 4 additions and 362 deletions

1
.gitignore vendored
View File

@ -2,4 +2,3 @@ node_modules
dist
build.json
kit/.kit/modules/*
kit/publish/*

78
kit/package-lock.json generated
View File

@ -18,7 +18,6 @@
"node-forge": "^1.3.1",
"physical-cpu-count": "^2.0.0",
"sm-crypto": "^0.3.13",
"ssh2": "^1.16.0",
"systeminformation": "^5.30.6",
"webdav": "^5.3.1"
},
@ -57,15 +56,6 @@
"resolved": "https://registry.npmmirror.com/applescript/-/applescript-1.0.0.tgz",
"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": {
"version": "5.0.6",
"resolved": "https://registry.npmmirror.com/auto-launch/-/auto-launch-5.0.6.tgz",
@ -91,15 +81,6 @@
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
"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": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@ -116,15 +97,6 @@
"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": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz",
@ -138,20 +110,6 @@
"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": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/cross-port-killer/-/cross-port-killer-1.4.0.tgz",
@ -459,13 +417,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"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": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz",
@ -572,12 +523,6 @@
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
"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": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz",
@ -586,23 +531,6 @@
"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": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz",
@ -647,12 +575,6 @@
"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": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",

View File

@ -4,7 +4,6 @@
"bin": "src/index.js",
"scripts": {
"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",
"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",
@ -23,9 +22,7 @@
"node-forge": "^1.3.1",
"physical-cpu-count": "^2.0.0",
"sm-crypto": "^0.3.13",
"ssh2": "^1.16.0",
"systeminformation": "^5.30.6",
"webdav": "^5.3.1"
}
}

View File

@ -1,116 +0,0 @@
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.');

View File

@ -172,7 +172,7 @@ parser.addCmdLine("freem [level]", "释放内存", function (cli) {
});
parser.addCmdLine("dockersh <container> [--file]", "反向获取 docker 容器启动脚本", function (cli) {
parser.addCmdLine("docker runsh <container> [--file]", "反向获取 docker 容器启动脚本", function (cli) {
let container = cli.getParamValue("container")
let file = cli.getParamValue("file")
import("./docker/index.js").then(psl => psl.main(container, file))

View File

@ -96,24 +96,10 @@ async function main(){
}
});
parser.addCmdLine("check [module]", "验证远程仓库可达;指定 module 时查看远程 meta 信息;", async function (cli) {
parser.addCmdLine("check", "验证远程仓库可达;", async function () {
const remote = await getAvailableRemote();
if (!remote) {
return;
}
const module = cli.getParamValue("module");
if (!module) {
if (remote) {
$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}`);
}
});
@ -144,7 +130,6 @@ async function main(){
}
await remote.publish(localFile, remotePath);
$logger.info("发布成功");
process.exit(0);
});
parser.addCmdLine("install [module]", "安装/更新模块; 支持 myapp、myapp@1.0、/docker/net/myapp", async function (cli) {
@ -183,4 +168,3 @@ async function main(){
});
}
}

View File

@ -335,155 +335,12 @@ 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) {
process.exit(code);
}
function isSecretLogKey(key) {
return /^(pwd|password|plainPwd|plainPassword|plaintextPwd|plaintextPassword|privateKey|passphrase|keyText)$/i.test(key);
return /^(pwd|password|plainPwd|plainPassword|plaintextPwd|plaintextPassword)$/i.test(key);
}
function redactLogValue(value) {
@ -546,7 +403,6 @@ module.exports = {
readJson: withCallLog("readJson", readJson),
writeJson: withCallLog("writeJson", writeJson),
scp: withCallLog("scp", scp),
remoteShell: withCallLog("remoteShell", remoteShell),
exit: withCallLog("exit", exit),
setVar: withCallLog("setVar", setVar),
getVar: withCallLog("getVar", getVar),