fitr
Version:
Financial Investment Tracker
138 lines (117 loc) • 4.25 kB
text/typescript
import {Command} from 'commander';
import {displayPortfolio} from './commands/displayPortfolio';
import {updateData} from './commands/updateData';
import {interactiveAddTransaction} from './commands/interactiveTransaction';
import {listTransactions} from './commands/listTransactions';
import {initializeStorage} from './utils/storageUtils';
import {Config} from './config';
import {Logger} from './utils/logger';
const program = new Command();
// Configure the main program
program
.name('fi-tracker')
.description('A CLI tool for tracking investment portfolio performance')
.version('0.1.0')
.helpOption('--help, -h', 'Display help information');
// Add global options
program
.option('-v, --verbose', 'Enable verbose logging mode')
.option('-D, --dev-data', 'Use development data directory');
/**
* Common options interface for commands
*/
interface CommandOptions {
verbose?: boolean;
devData?: boolean;
sync?: boolean;
growthRate?: string;
skipPrediction?: boolean;
symbol?: string;
type?: string;
date?: string;
quantity?: number;
price?: number;
fees?: number;
notes?: string;
interactive?: boolean;
}
/**
* Setup common configuration and initialization for commands
* @param options Command options
* @returns Promise that resolves when setup is complete
*/
async function setupCommand(options: CommandOptions): Promise<void> {
Config.getInstance().setDevMode(!!options.devData);
Config.getInstance().setDebugMode(!!options.verbose);
await initializeStorage();
await Config.getInstance().loadConfigFromFile();
if (options.verbose) {
Logger.debug(`Options: ${JSON.stringify(options)}`);
Logger.debug(`Config: ${JSON.stringify(Config.getInstance())}`);
}
if (Config.getInstance().isDevMode()) {
Logger.info(`Running in dev data mode`);
}
}
// Main command
program
.option('-s, --sync', 'Fetches and updates historical price data for all assets and calculates portfolio performance')
.option('-g, --growth-rate <growthRate>', 'Set the expected annual growth rate for the portfolio', '0.07')
.option('-p, --skip-prediction', 'Hide the prediction table')
.action(async (options) => {
try {
await setupCommand(options);
if (options.sync) {
await updateData();
}
await displayPortfolio(options.growthRate, !!options.skipPrediction);
} catch (error) {
Logger.error('', error);
}
});
// Create transaction command with subcommands
const transactionCommand = program
.command('transaction')
.description('Manage asset transactions')
.alias('tx')
.helpOption('--help, -h', 'Display help information');
// Add transaction subcommand (always interactive)
transactionCommand
.command('add')
.description('Add a new transaction for an asset (interactive mode)')
.helpOption('--help, -h', 'Display help information')
.action(async (options) => {
try {
// Merge command options with global options
const mergedOptions = {
...program.opts(),
...options
};
await setupCommand(mergedOptions);
// Always use interactive mode
await interactiveAddTransaction();
} catch (error) {
Logger.error('Error adding transaction', error);
}
});
// List transactions subcommand
transactionCommand
.command('list')
.description('List transactions for an asset')
.option('-s, --symbol <symbol>', 'Asset symbol')
.helpOption('--help, -h', 'Display help information')
.action(async (options) => {
try {
// Merge command options with global options
const mergedOptions = {
...program.opts(),
...options
};
await setupCommand(mergedOptions);
await listTransactions(options.symbol);
} catch (error) {
Logger.error('Error listing transactions', error);
}
});
program.parse(process.argv);