UNPKG

@fromsvenwithlove/devops-issues-cli

Version:

AI-powered CLI tool and library for Azure DevOps work item management with Claude agents

205 lines (177 loc) 4.97 kB
/** * Templates Index * * Provides access to pre-built Azure DevOps work item templates * and utilities for template management. */ import { readFileSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); /** * Load template from JSON file */ function loadTemplate(filename) { try { const content = readFileSync(join(__dirname, filename), 'utf-8'); return JSON.parse(content); } catch (error) { throw new Error(`Failed to load template ${filename}: ${error.message}`); } } /** * Available templates */ export const templates = { userStory: { name: 'User Story Template', description: 'Basic user story with tasks and acceptance criteria', file: 'user-story-template.json', category: 'story', get content() { return loadTemplate('user-story-template.json'); } }, feature: { name: 'Feature Template', description: 'Feature with multiple user stories and tasks', file: 'feature-template.json', category: 'feature', get content() { return loadTemplate('feature-template.json'); } }, bug: { name: 'Bug Report Template', description: 'Detailed bug report with reproduction steps', file: 'bug-template.json', category: 'bug', get content() { return loadTemplate('bug-template.json'); } }, epic: { name: 'Epic Template', description: 'Large epic with features and stories', file: 'epic-template.json', category: 'epic', get content() { return loadTemplate('epic-template.json'); } }, // Project-specific templates webApp: { name: 'Web Application Project', description: 'Complete web app project structure', file: 'web-app-project.json', category: 'project', get content() { return loadTemplate('web-app-project.json'); } }, api: { name: 'API Project', description: 'REST API development project structure', file: 'api-project.json', category: 'project', get content() { return loadTemplate('api-project.json'); } }, mobileApp: { name: 'Mobile Application', description: 'Mobile app development project structure', file: 'mobile-app-project.json', category: 'project', get content() { return loadTemplate('mobile-app-project.json'); } } }; /** * Get list of all available templates */ export function getTemplateList() { return Object.keys(templates).map(key => ({ key, ...templates[key] })); } /** * Get template by key */ export function getTemplate(key) { return templates[key] || null; } /** * Get templates by category */ export function getTemplatesByCategory(category) { return Object.keys(templates) .filter(key => templates[key].category === category) .map(key => ({ key, ...templates[key] })); } /** * Template categories */ export const categories = { story: 'User Stories', feature: 'Features', epic: 'Epics', bug: 'Bug Reports', project: 'Project Templates' }; /** * Create a new work item from template */ export function createFromTemplate(templateKey, overrides = {}) { const template = getTemplate(templateKey); if (!template) { throw new Error(`Template '${templateKey}' not found`); } const baseTemplate = template.content; // Deep merge overrides return mergeTemplate(baseTemplate, overrides); } /** * Deep merge template with overrides */ function mergeTemplate(template, overrides) { const result = JSON.parse(JSON.stringify(template)); // Deep clone if (overrides.metadata) { result.metadata = { ...result.metadata, ...overrides.metadata }; } if (overrides.workItems) { // Replace work items entirely if provided result.workItems = overrides.workItems; } return result; } /** * Validate template structure */ export function validateTemplate(template) { const required = ['workItems']; const missing = required.filter(field => !(field in template)); if (missing.length > 0) { throw new Error(`Template missing required fields: ${missing.join(', ')}`); } if (!Array.isArray(template.workItems) || template.workItems.length === 0) { throw new Error('Template must have at least one work item'); } // Validate each work item has required fields for (const [index, item] of template.workItems.entries()) { if (!item.type || !item.title) { throw new Error(`Work item ${index} missing required fields (type, title)`); } } return true; } /** * Load all templates for export */ export function loadAllTemplates() { const result = {}; for (const [key, template] of Object.entries(templates)) { try { result[key] = { ...template, content: template.content }; } catch (error) { console.warn(`Warning: Could not load template ${key}: ${error.message}`); } } return result; } export default templates;