@spoonly/otpm
Advanced tools
+44
-13
@@ -14,2 +14,3 @@ import { a as parseOTPAuthURI, i as getRemainingSeconds, n as generateOTP } from "./src-CAXJf9Vq.mjs"; | ||
| import path from "node:path"; | ||
| import { createLogUpdate } from "log-update"; | ||
| import figlet from "figlet"; | ||
@@ -19,3 +20,3 @@ | ||
| var name = "@spoonly/otpm"; | ||
| var version = "0.0.4"; | ||
| var version = "0.0.5"; | ||
| var package_default = { | ||
@@ -65,2 +66,3 @@ name, | ||
| "figlet": "catalog:", | ||
| "log-update": "catalog:", | ||
| "otpauth": "catalog:", | ||
@@ -250,2 +252,6 @@ "picocolors": "catalog:", | ||
| const outPath = path.resolve(file ?? defaultFile); | ||
| if (fs.existsSync(outPath) && fs.statSync(outPath).isDirectory()) { | ||
| consola.error(`"${outPath}" is a directory. Please specify a file path (e.g. otpm export backup.json).`); | ||
| process.exit(1); | ||
| } | ||
| const payload = JSON.stringify({ accounts }, null, 2); | ||
@@ -273,2 +279,13 @@ if (mode === "encrypted") { | ||
| //#region src/commands/generate.ts | ||
| const logUpdate$1 = createLogUpdate(process.stdout); | ||
| function buildWatchOutput$1(key, acc) { | ||
| const otp = generateOTP(acc); | ||
| const remaining = getRemainingSeconds(acc.period); | ||
| return [ | ||
| pc.dim(" Watching... Press Ctrl+C to stop."), | ||
| "", | ||
| ` ${pc.cyan(key)}`, | ||
| ` ${pc.green(pc.bold(otp))}${pc.dim(` expires in ${remaining}s`)}` | ||
| ].join("\n"); | ||
| } | ||
| async function printOTP(key, acc, copy = false) { | ||
@@ -315,9 +332,15 @@ const otp = generateOTP(acc); | ||
| if (options.watch && acc.type === "totp") { | ||
| consola.info(pc.dim("Watching... Press Ctrl+C to stop.\n")); | ||
| await printOTP(target, acc, options.copy); | ||
| const interval = setInterval(async () => { | ||
| if (getRemainingSeconds(acc.period) === acc.period) await printOTP(target, acc, options.copy); | ||
| logUpdate$1(buildWatchOutput$1(target, acc)); | ||
| const interval = setInterval(() => { | ||
| if (getRemainingSeconds(acc.period) === acc.period) { | ||
| if (options.copy) { | ||
| const otp = generateOTP(acc); | ||
| import("clipboardy").then(({ default: clipboard }) => clipboard.write(otp)); | ||
| } | ||
| } | ||
| logUpdate$1(buildWatchOutput$1(target, acc)); | ||
| }, 1e3); | ||
| process.on("SIGINT", () => { | ||
| clearInterval(interval); | ||
| logUpdate$1.done(); | ||
| outro("Stopped."); | ||
@@ -366,2 +389,6 @@ process.exit(0); | ||
| } | ||
| if (fs.statSync(resolved).isDirectory()) { | ||
| consola.error(`"${resolved}" is a directory. Please specify a file path (e.g. otpm import backup.json).`); | ||
| process.exit(1); | ||
| } | ||
| const raw = fs.readFileSync(resolved, "utf-8"); | ||
@@ -466,5 +493,9 @@ let jsonStr = raw; | ||
| //#region src/commands/list.ts | ||
| function printAll(accounts, keys) { | ||
| process.stdout.write("\x1B[2J\x1B[0f"); | ||
| consola.log(pc.bold(` ${keys.length} account(s):\n`)); | ||
| const logUpdate = createLogUpdate(process.stdout); | ||
| function buildWatchOutput(accounts, keys) { | ||
| const lines = []; | ||
| lines.push(pc.dim(" Watching... Press Ctrl+C to stop.")); | ||
| lines.push(""); | ||
| lines.push(pc.bold(` ${keys.length} account(s):`)); | ||
| lines.push(""); | ||
| for (const key of keys) { | ||
@@ -477,5 +508,5 @@ const acc = accounts[key]; | ||
| const timer = remaining !== null ? pc.dim(` (${remaining}s)`) : pc.dim(` [counter: ${acc.counter}]`); | ||
| consola.log(` ${label} ${code}${timer}`); | ||
| lines.push(` ${label} ${code}${timer}`); | ||
| } | ||
| consola.log(""); | ||
| return lines.join("\n"); | ||
| } | ||
@@ -490,9 +521,9 @@ function listHandler(config$1, options = {}) { | ||
| if (options.watch) { | ||
| consola.info(pc.dim("Watching... Press Ctrl+C to stop.")); | ||
| printAll(accounts, keys); | ||
| logUpdate(buildWatchOutput(accounts, keys)); | ||
| const interval = setInterval(() => { | ||
| printAll(accounts, keys); | ||
| logUpdate(buildWatchOutput(accounts, keys)); | ||
| }, 1e3); | ||
| process.on("SIGINT", () => { | ||
| clearInterval(interval); | ||
| logUpdate.done(); | ||
| outro("Stopped."); | ||
@@ -499,0 +530,0 @@ process.exit(0); |
+2
-1
| { | ||
| "name": "@spoonly/otpm", | ||
| "type": "module", | ||
| "version": "0.0.4", | ||
| "version": "0.0.5", | ||
| "description": "OTPm is a lightweight and efficient command-line two-factor authentication passcode generator, focusing on the generation and management of TOTP one-time passcodes.", | ||
@@ -37,2 +37,3 @@ "author": "OSpoon <zxin088@gmail.com>", | ||
| "figlet": "^1.11.0", | ||
| "log-update": "^8.0.0", | ||
| "otpauth": "^9.5.0", | ||
@@ -39,0 +40,0 @@ "picocolors": "^1.1.1", |
31207
3.57%706
4.59%10
11.11%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added