otp-wallet-cli
Version:
OTP Wallet CLI
90 lines (79 loc) • 2.24 kB
JavaScript
// Import.
import fs from 'fs';
import path from 'path';
import otplib from 'otplib';
import chalk from 'chalk';
import ora from 'ora';
// Constants.
const DATA_FILE_NAME =
process.env.NODE_ENV === 'test' ? '.otp-wallet-test-data.json' : '.otp-wallet-data.json';
export const DATA_FILE_PATH = path.join(
process.env.HOME || process.env.USERPROFILE,
DATA_FILE_NAME,
);
/**
* Load data.
* @returns {Array} Array of apps.
*/
export const loadData = () => {
if (!fs.existsSync(DATA_FILE_PATH)) return [];
return JSON.parse(fs.readFileSync(DATA_FILE_PATH));
};
/**
* Save data.
* @param {Array} data Array of apps.
*/
export const saveData = (data) => fs.writeFileSync(DATA_FILE_PATH, JSON.stringify(data, null, 2));
/**
* Show OTP codes.
*/
export const showCodes = () => {
const data = loadData();
if (data.length === 0) {
console.log(chalk.yellow('No apps added. Use `otp-cli add` to add an app.'));
return;
}
const spinner = ora('Fetching OTP codes...').start();
const updateDisplay = () => {
console.clear();
const remainingTime = 30 - (Math.floor(Date.now() / 1000) % 30);
console.log(chalk.cyan('Your OTP codes:'));
data.forEach((app) => {
const code = otplib.authenticator.generate(app.secret);
console.log(`${chalk.green(app.name)}: ${chalk.bold(code)} (Refresh in ${remainingTime}s)`);
});
setTimeout(updateDisplay, 1000);
};
spinner.stop();
updateDisplay();
};
/**
* Add an app.
* @param {string} name App name.
* @param {string} secret OTP secret.
*/
export const addApp = (name, secret) => {
if (loadData().some((app) => app.name === name)) {
console.log(chalk.red(`App ${name} already exists.`));
return;
}
const data = loadData();
data.push({ name, secret });
saveData(data);
console.log(chalk.green(`App ${name} added.`));
};
/**
* Delete an app.
* @param {string} name App name.
*/
export const deleteApp = (name) => {
let data = loadData();
const initialLength = data.length;
data = data.filter((app) => app.name !== name);
saveData(data);
if (initialLength === data.length) {
console.log(chalk.red(`App ${name} not found.`));
} else {
console.log(chalk.green(`App ${name} deleted.`));
}
};