khodkar-cli
Version:
A TypeScript CLI application that extracts business rules and logic from codebases for customer support knowledge bases
226 lines • 8.3 kB
JavaScript
;
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutputFormatter = void 0;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const types_1 = require("../types");
class OutputFormatter {
options;
constructor(options = {}) {
this.options = options;
this.options = {
includeMetadata: true,
includeSourceReferences: true,
groupByCategory: true,
sortByPriority: true,
...options,
};
}
async formatAndSave(result, outputPath, format) {
const output = format === 'json' ? this.formatAsJSON(result) : this.formatAsMarkdown(result);
try {
// Ensure output directory exists
const outputDir = path.dirname(outputPath);
await fs.mkdir(outputDir, { recursive: true });
// Write the formatted output
await fs.writeFile(outputPath, output.content, 'utf-8');
}
catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
throw new types_1.FileSystemError(`Failed to save output: ${message}`, {
outputPath,
format,
error: message,
});
}
}
formatAsJSON(result) {
return {
format: 'json',
content: JSON.stringify(result, null, 2),
};
}
formatAsMarkdown(result) {
const lines = [];
// Header
lines.push(`# Business Rules`);
lines.push('');
// Metadata section
if (this.options.includeMetadata) {
lines.push('## Analysis Summary');
lines.push('');
lines.push(`- **Analysis Date:** ${new Date(result.analysisDate).toLocaleDateString()}`);
lines.push(`- **Total Business Rules:** ${result.summary.totalRules}`);
lines.push(`- **High Priority Rules:** ${result.summary.highPriorityRules}`);
lines.push(`- **User-Facing Rules:** ${result.summary.userFacingRules}`);
lines.push('');
}
// All rules in one section
lines.push('## Business Rules');
lines.push('');
const sortedRules = this.options.sortByPriority
? this.sortRulesByPriority(result.businessRules)
: result.businessRules;
for (const rule of sortedRules) {
lines.push(...this.formatRule(rule));
}
// Footer with generation info
lines.push('---');
lines.push('');
lines.push('*This document was automatically generated by Khodkar CLI.*');
lines.push(`*Generated on: ${new Date().toLocaleString()}*`);
return {
format: 'markdown',
content: lines.join('\n'),
};
}
formatRule(rule) {
const lines = [];
// Rule title with priority indicator
const priorityEmoji = this.getPriorityEmoji(rule.priority);
lines.push(`### ${priorityEmoji} ${rule.title}`);
lines.push('');
// Rule description
lines.push(rule.description);
lines.push('');
// Tags if present
if (rule.tags.length > 0) {
lines.push(`**Tags:** ${rule.tags.map(tag => `\`${tag}\``).join(', ')}`);
lines.push('');
}
// Source reference
if (this.options.includeSourceReferences && rule.source) {
const sourceRef = rule.source.startLine && rule.source.endLine
? `${rule.source.file}:${rule.source.startLine}-${rule.source.endLine}`
: rule.source.file;
lines.push(`*Source: ${sourceRef}*`);
lines.push('');
}
return lines;
}
sortRulesByPriority(rules) {
const priorityOrder = { high: 3, medium: 2, low: 1 };
return [...rules].sort((a, b) => {
// First sort by priority
const priorityDiff = priorityOrder[b.priority] - priorityOrder[a.priority];
if (priorityDiff !== 0)
return priorityDiff;
// Then by user-facing (user-facing first)
if (a.userFacing !== b.userFacing) {
return b.userFacing ? 1 : -1;
}
// Finally by title alphabetically
return a.title.localeCompare(b.title);
});
}
getPriorityEmoji(priority) {
const emojiMap = {
high: '🔴',
medium: '🟡',
low: '🟢',
};
return emojiMap[priority];
}
// Static utility methods
static async validateOutputPath(outputPath) {
try {
const outputDir = path.dirname(outputPath);
await fs.access(outputDir);
}
catch {
// Directory doesn't exist, try to create it
try {
await fs.mkdir(path.dirname(outputPath), { recursive: true });
}
catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
throw new types_1.FileSystemError(`Cannot create output directory: ${message}`, {
outputPath,
error: message,
});
}
}
}
static getOutputExtension(format) {
return format === 'json' ? '.json' : '.md';
}
static generateDefaultOutputPath(directory, format) {
const timestamp = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
const projectName = path.basename(directory);
const extension = OutputFormatter.getOutputExtension(format);
return path.join(directory, `business-rules-${projectName}-${timestamp}${extension}`);
}
static async fileExists(filePath) {
try {
await fs.access(filePath);
return true;
}
catch {
return false;
}
}
static async getFileStats(filePath) {
try {
const stats = await fs.stat(filePath);
return {
size: stats.size,
created: stats.birthtime,
modified: stats.mtime,
};
}
catch (error) {
const message = error instanceof Error ? error.message : 'Unknown error';
throw new types_1.FileSystemError(`Cannot get file stats: ${message}`, {
filePath,
error: message,
});
}
}
// Template methods for custom formatting
formatHeader(result) {
return [`# Business Rules`, ''];
}
formatFooter() {
return [
'---',
'',
'*This document was automatically generated by Khodkar CLI.*',
`*Generated on: ${new Date().toLocaleString()}*`,
];
}
}
exports.OutputFormatter = OutputFormatter;
//# sourceMappingURL=output-formatter.js.map