/** * rules.js * Direct function implementation for adding or removing rules */ import { enableSilentMode, disableSilentMode } from '../../../../scripts/modules/utils.js'; import { convertAllRulesToProfileRules, removeProfileRules, getRulesProfile, isValidProfile } from '../../../../src/utils/rule-transformer.js'; import { RULES_PROFILES } from '../../../../src/constants/profiles.js'; import { RULES_ACTIONS } from '../../../../src/constants/rules-actions.js'; import path from 'path'; import fs from 'fs'; /** * Direct function wrapper for adding or removing rules. * @param {Object} args - Command arguments * @param {"add"|"remove"} args.action - Action to perform: add or remove rules * @param {string[]} args.profiles - List of profiles to add or remove * @param {string} args.projectRoot - Absolute path to the project root * @param {boolean} [args.yes=true] - Run non-interactively * @param {Object} log - Logger object * @param {Object} context - Additional context (session) * @returns {Promise} - Result object { success: boolean, data?: any, error?: { code: string, message: string } } */ export async function rulesDirect(args, log, context = {}) { enableSilentMode(); try { const { action, profiles, projectRoot, yes } = args; if ( !action || !Array.isArray(profiles) || profiles.length === 0 || !projectRoot ) { return { success: false, error: { code: 'MISSING_ARGUMENT', message: 'action, profiles, and projectRoot are required.' } }; } const removalResults = []; const addResults = []; if (action === RULES_ACTIONS.REMOVE) { for (const profile of profiles) { if (!isValidProfile(profile)) { removalResults.push({ profileName: profile, success: false, error: `The requested rules profile for '${profile}' is unavailable. Supported profiles are: ${RULES_PROFILES.join(', ')}.` }); continue; } const profileConfig = getRulesProfile(profile); const result = removeProfileRules(projectRoot, profileConfig); removalResults.push(result); } const successes = removalResults .filter((r) => r.success) .map((r) => r.profileName); const skipped = removalResults .filter((r) => r.skipped) .map((r) => r.profileName); const errors = removalResults.filter( (r) => r.error && !r.success && !r.skipped ); let summary = ''; if (successes.length > 0) { summary += `Successfully removed rules: ${successes.join(', ')}.`; } if (skipped.length > 0) { summary += `Skipped (default or protected): ${skipped.join(', ')}.`; } if (errors.length > 0) { summary += errors .map((r) => `Error removing ${r.profileName}: ${r.error}`) .join(' '); } disableSilentMode(); return { success: errors.length === 0, data: { summary, results: removalResults } }; } else if (action === RULES_ACTIONS.ADD) { for (const profile of profiles) { if (!isValidProfile(profile)) { addResults.push({ profileName: profile, success: false, error: `Profile not found: static import missing for '${profile}'. Valid profiles: ${RULES_PROFILES.join(', ')}` }); continue; } const profileConfig = getRulesProfile(profile); const { success, failed } = convertAllRulesToProfileRules( projectRoot, profileConfig ); // Determine paths const rulesDir = profileConfig.rulesDir; const profileRulesDir = path.join(projectRoot, rulesDir); const profileDir = profileConfig.profileDir; const mcpConfig = profileConfig.mcpConfig !== false; const mcpPath = path.join(projectRoot, profileConfig.mcpConfigPath); // Check what was created const mcpConfigCreated = mcpConfig ? fs.existsSync(mcpPath) : undefined; const rulesDirCreated = fs.existsSync(profileRulesDir); const profileFolderCreated = fs.existsSync( path.join(projectRoot, profileDir) ); const error = failed > 0 ? `${failed} rule files failed to convert.` : null; const resultObj = { profileName: profile, mcpConfigCreated, rulesDirCreated, profileFolderCreated, skipped: false, error, success: (mcpConfig ? mcpConfigCreated : true) && rulesDirCreated && success > 0 && !error }; addResults.push(resultObj); } const successes = addResults .filter((r) => r.success) .map((r) => r.profileName); const errors = addResults.filter((r) => r.error && !r.success); let summary = ''; if (successes.length > 0) { summary += `Successfully added rules: ${successes.join(', ')}.`; } if (errors.length > 0) { summary += errors .map((r) => ` Error adding ${r.profileName}: ${r.error}`) .join(' '); } disableSilentMode(); return { success: errors.length === 0, data: { summary, results: addResults } }; } else { disableSilentMode(); return { success: false, error: { code: 'INVALID_ACTION', message: `Unknown action. Use "${RULES_ACTIONS.ADD}" or "${RULES_ACTIONS.REMOVE}".` } }; } } catch (error) { disableSilentMode(); log.error(`[rulesDirect] Error: ${error.message}`); return { success: false, error: { code: error.code || 'RULES_ERROR', message: error.message } }; } }