UNPKG

todofordevs

Version:

CLI for TodoForDevs - A simple task management tool for developers

372 lines (371 loc) 13.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.listTasks = listTasks; exports.addTask = addTask; exports.viewTask = viewTask; exports.updateTask = updateTask; exports.deleteTask = deleteTask; const inquirer_1 = __importDefault(require("inquirer")); const api_1 = require("./api"); const output = __importStar(require("./output")); const auth_1 = require("./auth"); const project_1 = require("./project"); /** * List tasks for a project */ async function listTasks(options = {}) { if (!(0, auth_1.requireAuth)()) return []; try { // Get the project ID (from options or active project) const projectId = await (0, project_1.getActiveProjectId)(options.project); if (!projectId) { output.error('No project specified. Use --project or select an active project.'); return []; } output.info(`Fetching tasks for project ID: ${projectId}...`); // Build query parameters const params = {}; if (options.status) params.status = options.status; if (options.priority) params.priority = options.priority; if (options.assignee) params.assignee = options.assignee; if (options.sortBy) params.sortBy = options.sortBy; if (options.sortOrder) params.sortOrder = options.sortOrder; // Fetch tasks const response = await (0, api_1.get)(api_1.endpoints.tasks.list(projectId, params)); const tasks = response.tasks || []; if (tasks.length === 0) { output.info('No tasks found.'); return []; } // Display tasks in a table const table = output.createTable([ 'ID', 'Title', 'Status', 'Priority', 'Assignee', 'Due Date', ]); tasks.forEach((task) => { table.push([ output.truncate(task.id, 10), output.truncate(task.title, 30), task.status, task.priority, output.truncate(task.assigneeEmail || task.assigneeName || 'Unassigned', 20), output.formatDate(task.dueDate), ]); }); console.log(table.toString()); return tasks; } catch (error) { output.error('Failed to fetch tasks.'); console.error(error); return []; } } /** * Add a new task */ async function addTask(options = {}) { if (!(0, auth_1.requireAuth)()) return; try { // Get the project ID (from options or active project) const projectId = await (0, project_1.getActiveProjectId)(options.project); if (!projectId) { output.error('No project specified. Use --project or select an active project.'); return; } // Prompt for task details const taskInput = await promptForTaskDetails(); if (!taskInput) { output.info('Task creation cancelled.'); return; } output.info('Creating task...'); // Create the task const response = await (0, api_1.post)(api_1.endpoints.tasks.create(projectId), taskInput); output.success(`Task '${response.task.title}' created successfully with ID: ${response.task.id}.`); } catch (error) { output.error('Failed to create task.'); console.error(error); } } /** * View a task's details */ async function viewTask(taskId) { if (!(0, auth_1.requireAuth)()) return; try { output.info(`Fetching task details for ID: ${taskId}...`); // Fetch the task const response = await (0, api_1.get)(api_1.endpoints.tasks.get(taskId)); const task = response.task; // Display task details output.heading('Task Details'); output.formatKeyValue('ID', task.id); output.formatKeyValue('Title', task.title); output.formatKeyValue('Description', task.description || ''); output.formatKeyValue('Status', task.status); output.formatKeyValue('Priority', task.priority); output.formatKeyValue('Due Date', output.formatDate(task.dueDate)); output.formatKeyValue('Assignee', task.assigneeEmail || task.assigneeName || 'Unassigned'); output.formatKeyValue('Project ID', task.projectId); output.formatKeyValue('Project Name', task.project?.name || ''); output.formatKeyValue('Created At', new Date(task.createdAt).toLocaleString()); output.formatKeyValue('Updated At', new Date(task.updatedAt).toLocaleString()); } catch (error) { output.error(`Failed to fetch task with ID: ${taskId}.`); console.error(error); } } /** * Update a task */ async function updateTask(taskId) { if (!(0, auth_1.requireAuth)()) return; try { output.info(`Fetching task details for ID: ${taskId}...`); // Fetch the current task const response = await (0, api_1.get)(api_1.endpoints.tasks.get(taskId)); const task = response.task; // Prompt for updates const updates = await promptForTaskUpdates(task); if (!updates) { output.info('Task update cancelled.'); return; } output.info('Updating task...'); // Update the task await (0, api_1.put)(api_1.endpoints.tasks.update(taskId), updates); output.success(`Task '${updates.title || task.title}' (ID: ${taskId}) updated successfully.`); } catch (error) { output.error(`Failed to update task with ID: ${taskId}.`); console.error(error); } } /** * Delete a task */ async function deleteTask(taskId) { if (!(0, auth_1.requireAuth)()) return; try { // Fetch the task to get its title let taskTitle = 'Unknown'; try { const response = await (0, api_1.get)(api_1.endpoints.tasks.get(taskId)); const task = response.task; taskTitle = task.title || 'Unknown'; } catch (fetchError) { output.warning(`Could not fetch task details: ${fetchError}`); } // Confirm deletion const { confirm } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirm', message: `Are you sure you want to delete task ${taskId} '${taskTitle}'?`, default: false, }, ]); if (!confirm) { output.info('Task deletion cancelled.'); return; } output.info('Deleting task...'); // Delete the task await (0, api_1.del)(api_1.endpoints.tasks.delete(taskId)); output.success(`Task '${taskTitle}' (ID: ${taskId}) deleted successfully.`); } catch (error) { output.error(`Failed to delete task with ID: ${taskId}.`); console.error(error); } } /** * Prompt for task details */ async function promptForTaskDetails() { try { const answers = await inquirer_1.default.prompt([ { type: 'input', name: 'title', message: 'Title:', validate: (input) => input.trim() !== '' || 'Title is required', }, { type: 'input', name: 'description', message: 'Description (optional):', }, { type: 'list', name: 'status', message: 'Status:', choices: ['To Do', 'In Progress', 'Blocked', 'Done'], default: 'To Do', }, { type: 'list', name: 'priority', message: 'Priority:', choices: ['Low', 'Medium', 'High', 'Urgent'], default: 'Medium', }, { type: 'input', name: 'dueDate', message: 'Due Date (YYYY-MM-DD, optional):', validate: (input) => { if (!input) return true; const dateRegex = /^\d{4}-\d{2}-\d{2}$/; if (!dateRegex.test(input)) { return 'Please use YYYY-MM-DD format'; } const date = new Date(input); return !isNaN(date.getTime()) || 'Invalid date'; }, }, { type: 'input', name: 'assigneeId', message: 'Assignee ID/Email (optional):', }, ]); return { title: answers.title, description: answers.description || undefined, status: answers.status, priority: answers.priority, dueDate: answers.dueDate || undefined, assigneeId: answers.assigneeId || undefined, }; } catch (error) { console.error('Error during task creation prompt:', error); return null; } } /** * Prompt for task updates */ async function promptForTaskUpdates(currentTask) { try { const answers = await inquirer_1.default.prompt([ { type: 'input', name: 'title', message: 'Title:', default: currentTask.title, validate: (input) => input.trim() !== '' || 'Title is required', }, { type: 'input', name: 'description', message: 'Description (optional):', default: currentTask.description || '', }, { type: 'list', name: 'status', message: 'Status:', choices: ['To Do', 'In Progress', 'Blocked', 'Done'], default: currentTask.status, }, { type: 'list', name: 'priority', message: 'Priority:', choices: ['Low', 'Medium', 'High', 'Urgent'], default: currentTask.priority, }, { type: 'input', name: 'dueDate', message: 'Due Date (YYYY-MM-DD, optional):', default: currentTask.dueDate || '', validate: (input) => { if (!input) return true; const dateRegex = /^\d{4}-\d{2}-\d{2}$/; if (!dateRegex.test(input)) { return 'Please use YYYY-MM-DD format'; } const date = new Date(input); return !isNaN(date.getTime()) || 'Invalid date'; }, }, { type: 'input', name: 'assigneeId', message: 'Assignee ID/Email (optional):', default: currentTask.assigneeId || currentTask.assigneeEmail || '', }, ]); return { title: answers.title, description: answers.description || undefined, status: answers.status, priority: answers.priority, dueDate: answers.dueDate || undefined, assigneeId: answers.assigneeId || undefined, }; } catch (error) { console.error('Error during task update prompt:', error); return null; } }