Files
ts-scripts/single-scripts/kpxcenv.ts
2025-01-19 19:23:50 +08:00

125 lines
3.5 KiB
TypeScript
Executable File

#!/usr/bin/env -S deno run --allow-env --allow-run --allow-import
// Reference:
// - https://github.com/nwwdles/kpxcpc
// - https://stackoverflow.com/questions/62142699/how-do-i-run-an-arbitrary-shell-command-from-deno
// - https://docs.deno.com/api/deno/~/Deno.CommandOptions
// - https://github.com/aliyun/aliyun-cli
import {
compareVersion,
isEnvOn,
log,
} from "https://hatter.ink/script/get/@1/deno-commons-mod.ts";
const args = Deno.args;
if (args.length == 0) {
console.log(
`kpxcenv.js - KeepassXC environment tool (currently only support Alibaba Cloud)
kpxcenv.js aliyunak://ak-name
Environments:
KPXC_SHELL - Shell, default bash
KPXC_REGION - Region, default cn-hangzhou, effects env: ALIBABA_CLOUD_REGION_ID
KPXC_DEBUG - Debug, default false
`,
);
Deno.exit(0);
}
const KEEPASSXC_PROXY_COMMAND = "kpxcpc";
const isDebug = isEnvOn("KPXC_DEBUG");
const xdrRuntimeDir = Deno.env.get("XDG_RUNTIME_DIR");
if (xdrRuntimeDir == null) {
const tmpdir = Deno.env.get("TMPDIR");
if (tmpdir == null) {
log.error("Environment XDG_RUNTIME_DIR is not set.");
Deno.exit(1);
}
if (isDebug) {
log.debug("Set env XDG_RUNTIME_DIR=" + tmpdir);
}
Deno.env.set("XDG_RUNTIME_DIR", tmpdir);
}
const shellCommand = Deno.env.get("KPXC_SHELL") || "bash";
const region = Deno.env.get("KPXC_REGION") || "cn-hangzhou";
if (compareVersion(Deno.version.deno, "1.18.0") < 0) {
log.error("Require deno version >= 1.18.0 .");
Deno.exit(1);
}
async function commandExists(cmd: string): Promise<boolean> {
const whichCmd = new Deno.Command("which", {
args: [cmd],
});
const {
code: whichCmdCode,
stdout: _whichCmdStdout,
stderr: _whichCmdStderr,
} = await whichCmd.output();
return whichCmdCode === 0;
}
if (!await commandExists(KEEPASSXC_PROXY_COMMAND)) {
log.error(
"Command kpxcpc is not installed, please install from: https://github.com/nwwdles/kpxcpc",
);
Deno.exit(1);
}
const akName = args[0];
const kpxcpcCmd = new Deno.Command(KEEPASSXC_PROXY_COMMAND, {
args: ["--json", akName],
});
const {
code: kpxcpcCmdCode,
stdout: kpxcpcCmdStdout,
stderr: kpxcpcCmdStderr,
} = await kpxcpcCmd.output();
if (kpxcpcCmdCode != 0) {
console.error(new TextDecoder().decode(kpxcpcCmdStderr));
console.log(new TextDecoder().decode(kpxcpcCmdStdout));
Deno.exit(kpxcpcCmdCode);
}
const kpxcpcCmdStdoutString = new TextDecoder().decode(kpxcpcCmdStdout);
const kpxcpcCmdJsonObjects = JSON.parse(kpxcpcCmdStdoutString);
if (kpxcpcCmdJsonObjects.length == 0) {
log.error(
"Should not happen, since KeepassXC return JSON array is empty.",
);
Deno.exit(1);
}
if (kpxcpcCmdJsonObjects.length > 1) {
log.warn(
"Get more than one vaule from KeepassXC, default use the first.",
);
}
const kpxcpcCmdJsonObject = kpxcpcCmdJsonObjects[0];
const accessKeyName = kpxcpcCmdJsonObject.name;
const accessKeyId = kpxcpcCmdJsonObject.login;
const accessKeySecret = kpxcpcCmdJsonObject.password;
if (isDebug) {
log.debug("Found object: ", kpxcpcCmdJsonObject);
}
const command = new Deno.Command(shellCommand, {
args: [],
env: {
"PS1": accessKeyName + " (" + akName + ")" + "> ", // FIXME support fish
"ALIBABA_CLOUD_REGION_ID": region,
"ALIBABA_CLOUD_ACCESS_KEY_ID": accessKeyId,
"ALIBABA_CLOUD_ACCESS_KEY_SECRET": accessKeySecret,
},
stdin: "inherit",
stdout: "inherit",
});
const _child = command.spawn();