diff --git a/script-meta-v2.json b/script-meta-v2.json index 5d7a4e8..d02ea35 100644 --- a/script-meta-v2.json +++ b/script-meta-v2.json @@ -11,6 +11,13 @@ "script_sha256": "b301944e64def6c3a1ada4e327a7b2c2e37c576a65da5f797998355c51686f76", "script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/helloworld-ts/main.ts" }, + "kpxcenv.ts": { + "script_name": "kpxcenv.ts", + "script_length": 3622, + "script_sha256": "e2e35aa9a535837a7f663c0b35857d78c178b96451d24be3137dcc0e783cce9c", + "script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/single-scripts/kpxcenv.ts", + "single_script_file": true + }, "print-env.ts": { "script_name": "print-env.ts", "script_length": 156, diff --git a/single-scripts/kpxcenv.ts b/single-scripts/kpxcenv.ts new file mode 100755 index 0000000..eba1794 --- /dev/null +++ b/single-scripts/kpxcenv.ts @@ -0,0 +1,120 @@ +#!/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,} from "https://hatter.ink/script/fetch/library/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) { + console.error("[ERROR] Environment XDG_RUNTIME_DIR is not set."); + Deno.exit(1); + } + if (isDebug) { + console.debug("[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) { + console.error("[ERROR] Require deno version >= 1.18.0 ."); + Deno.exit(1); +} + +async function commandExists(cmd: string): Promise { + 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)) { + console.error( + "[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) { + console.error( + "[ERROR] Should not happen, since KeepassXC return JSON array is empty.", + ); + Deno.exit(1); +} +if (kpxcpcCmdJsonObjects.length > 1) { + console.warn( + "[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) { + console.debug("[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();