UNPKG

@latentsearch/timemachine-cli

Version:

CLI tool for TimeMachine API. Generates time entries, lists users/projects, and features an enhanced dry-run output for generation.

149 lines (148 loc) 6.69 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.listEntries = listEntries; const chalk_1 = __importDefault(require("chalk")); const console_table_printer_1 = require("console-table-printer"); const luxon_1 = require("luxon"); const api_client_1 = require("../utils/api-client"); const resolvers_1 = require("../utils/resolvers"); /** * Lists time entries with filtering options */ async function listEntries(options) { try { const api = (0, api_client_1.createApiClient)(options); // Parse date inputs const startDate = luxon_1.DateTime.fromISO(options.startDate || ""); const endDate = luxon_1.DateTime.fromISO(options.endDate || ""); const limit = parseInt(options.limit || "50", 10); if (!startDate.isValid) { throw new Error(`Invalid start date "${options.startDate}". Use YYYY-MM-DD format.`); } if (!endDate.isValid) { throw new Error(`Invalid end date "${options.endDate}". Use YYYY-MM-DD format.`); } console.log(chalk_1.default.blue(`Fetching time entries from ${startDate.toISODate()} to ${endDate.toISODate()}...`)); // Build query parameters const params = new URLSearchParams({ start_date: startDate.toISODate() || "", end_date: endDate.toISODate() || "", limit: limit.toString() }); // Resolve user and project if provided if (options.user) { try { const userId = await (0, resolvers_1.resolveUser)(api, options.user); params.append("user_id", userId.toString()); console.log(chalk_1.default.blue(`Filtering by user ID: ${userId}`)); } catch (error) { console.warn(chalk_1.default.yellow(`Warning: ${error.message}`)); } } if (options.project) { try { const projectId = await (0, resolvers_1.resolveProject)(api, options.project); params.append("project_id", projectId.toString()); console.log(chalk_1.default.blue(`Filtering by project ID: ${projectId}`)); } catch (error) { console.warn(chalk_1.default.yellow(`Warning: ${error.message}`)); } } // Fetch time entries const response = await api.get(`/api/time_entries?${params.toString()}`); if (response.data && response.data.length > 0) { // Calculate total hours const totalHours = response.data.reduce((sum, entry) => sum + entry.hours_worked, 0); // Group entries by date for better visualization const entriesByDate = {}; response.data.forEach(entry => { if (!entriesByDate[entry.date]) { entriesByDate[entry.date] = []; } entriesByDate[entry.date].push(entry); }); // Sort dates in descending order (newest first) const sortedDates = Object.keys(entriesByDate).sort((a, b) => luxon_1.DateTime.fromISO(b).toMillis() - luxon_1.DateTime.fromISO(a).toMillis()); // Display entries in a table const table = new console_table_printer_1.Table({ title: `Time Entries (${response.data.length})`, columns: [ { name: "id", title: "ID", alignment: "right" }, { name: "date", title: "Date" }, { name: "user", title: "User" }, { name: "project", title: "Project" }, { name: "hours", title: "Hours", alignment: "right" } ] }); // Add entries to table, grouped by date sortedDates.forEach((date, index) => { // Add date separator if not the first date if (index > 0) { table.addRow({ id: "", date: "", user: "", project: "", hours: "" }); } // Calculate date total const dateTotal = entriesByDate[date].reduce((sum, entry) => sum + entry.hours_worked, 0); // Add date header table.addRow({ id: "", date: chalk_1.default.bold(formatDate(date)), user: "", project: "", hours: chalk_1.default.bold(dateTotal.toFixed(2)) }); // Add date's entries entriesByDate[date].forEach(entry => { table.addRow({ id: entry.id, date: "", // Date already shown in group header user: entry.user_name || "N/A", project: entry.project_name || "N/A", hours: entry.hours_worked.toFixed(2) }); }); }); table.printTable(); // Print summary console.log(chalk_1.default.green(`\nTotal Hours: ${totalHours.toFixed(2)}`)); console.log(`Average per entry: ${(totalHours / response.data.length).toFixed(2)}`); console.log(`Date range: ${formatDate(startDate.toISODate() || "")} to ${formatDate(endDate.toISODate() || "")}`); console.log(`Unique dates: ${sortedDates.length}`); // If there are potentially more entries than the limit, inform the user if (response.data.length >= limit) { console.log(chalk_1.default.yellow(`\nNote: Results limited to ${limit} entries. Use --limit to show more.`)); } } else { console.log(chalk_1.default.yellow("No time entries found matching your criteria")); } } catch (error) { console.error(chalk_1.default.red("Error fetching time entries:"), error.response?.data?.error || error.message); if (options.verbose && error.response?.data) { console.error(chalk_1.default.gray(JSON.stringify(error.response.data, null, 2))); } process.exit(1); } } /** * Formats a date string as a readable format */ function formatDate(dateStr) { try { return luxon_1.DateTime.fromISO(dateStr).toLocaleString(luxon_1.DateTime.DATE_MED_WITH_WEEKDAY); } catch (error) { return dateStr; } }