@aiready/consistency 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs ADDED
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ analyzeConsistency
4
+ } from "./chunk-CF4LU7KE.mjs";
5
+
6
+ // src/cli.ts
7
+ import { Command } from "commander";
8
+ import chalk from "chalk";
9
+ import { writeFileSync } from "fs";
10
+ import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
11
+ var program = new Command();
12
+ program.name("aiready-consistency").description("Detect consistency issues in naming, patterns, and architecture").version("0.1.0").addHelpText("after", `
13
+ CONFIGURATION:
14
+ Supports config files: aiready.json, aiready.config.json, .aiready.json, .aireadyrc.json
15
+ CLI options override config file settings
16
+
17
+ ANALYSIS CATEGORIES:
18
+ --naming Check naming conventions and quality (default: enabled)
19
+ --patterns Check code pattern consistency (default: enabled)
20
+ --architecture Check architectural consistency (coming soon)
21
+
22
+ EXAMPLES:
23
+ aiready-consistency . # Full analysis
24
+ aiready-consistency . --no-naming # Skip naming checks
25
+ aiready-consistency . --min-severity major # Only show major+ issues
26
+ aiready-consistency . --output json > report.json # JSON export
27
+ `).argument("<directory>", "Directory to analyze").option("--naming", "Check naming conventions and quality (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code pattern consistency (default: true)").option("--no-patterns", "Skip pattern analysis").option("--architecture", "Check architectural consistency (not yet implemented)").option("--min-severity <level>", "Minimum severity: info|minor|major|critical. Default: info").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console|json|markdown", "console").option("--output-file <path>", "Output file path (for json/markdown)").action(async (directory, options) => {
28
+ console.log(chalk.blue("\u{1F50D} Analyzing consistency...\n"));
29
+ const startTime = Date.now();
30
+ const config = loadConfig(directory);
31
+ const defaults = {
32
+ checkNaming: true,
33
+ checkPatterns: true,
34
+ checkArchitecture: false,
35
+ minSeverity: "info",
36
+ include: void 0,
37
+ exclude: void 0
38
+ };
39
+ const mergedConfig = mergeConfigWithDefaults(config, defaults);
40
+ const finalOptions = {
41
+ rootDir: directory,
42
+ checkNaming: options.naming !== false && mergedConfig.checkNaming,
43
+ checkPatterns: options.patterns !== false && mergedConfig.checkPatterns,
44
+ checkArchitecture: options.architecture || mergedConfig.checkArchitecture,
45
+ minSeverity: options.minSeverity || mergedConfig.minSeverity,
46
+ include: options.include?.split(",") || mergedConfig.include,
47
+ exclude: options.exclude?.split(",") || mergedConfig.exclude
48
+ };
49
+ const report = await analyzeConsistency(finalOptions);
50
+ const elapsedTime = ((Date.now() - startTime) / 1e3).toFixed(2);
51
+ if (options.output === "json") {
52
+ const output = JSON.stringify(report, null, 2);
53
+ if (options.outputFile) {
54
+ writeFileSync(options.outputFile, output);
55
+ console.log(chalk.green(`\u2713 Report saved to ${options.outputFile}`));
56
+ } else {
57
+ console.log(output);
58
+ }
59
+ } else if (options.output === "markdown") {
60
+ const markdown = generateMarkdownReport(report, elapsedTime);
61
+ if (options.outputFile) {
62
+ writeFileSync(options.outputFile, markdown);
63
+ console.log(chalk.green(`\u2713 Report saved to ${options.outputFile}`));
64
+ } else {
65
+ console.log(markdown);
66
+ }
67
+ } else {
68
+ displayConsoleReport(report, elapsedTime);
69
+ }
70
+ });
71
+ program.parse();
72
+ function displayConsoleReport(report, elapsedTime) {
73
+ const { summary, results, recommendations } = report;
74
+ console.log(chalk.bold("\n\u{1F4CA} Summary\n"));
75
+ console.log(`Files Analyzed: ${chalk.cyan(summary.filesAnalyzed)}`);
76
+ console.log(`Total Issues: ${chalk.yellow(summary.totalIssues)}`);
77
+ console.log(` Naming: ${chalk.yellow(summary.namingIssues)}`);
78
+ console.log(` Patterns: ${chalk.yellow(summary.patternIssues)}`);
79
+ console.log(` Architecture: ${chalk.yellow(summary.architectureIssues)}`);
80
+ console.log(`Analysis Time: ${chalk.gray(elapsedTime + "s")}
81
+ `);
82
+ if (summary.totalIssues === 0) {
83
+ console.log(chalk.green("\u2728 No consistency issues found! Your codebase is well-maintained.\n"));
84
+ return;
85
+ }
86
+ const namingResults = results.filter(
87
+ (r) => r.issues.some((i) => i.category === "naming")
88
+ );
89
+ const patternResults = results.filter(
90
+ (r) => r.issues.some((i) => i.category === "patterns")
91
+ );
92
+ if (namingResults.length > 0) {
93
+ console.log(chalk.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
94
+ displayCategoryIssues(namingResults, 5);
95
+ }
96
+ if (patternResults.length > 0) {
97
+ console.log(chalk.bold("\n\u{1F504} Pattern Issues\n"));
98
+ displayCategoryIssues(patternResults, 5);
99
+ }
100
+ console.log(chalk.bold("\n\u{1F4A1} Recommendations\n"));
101
+ recommendations.forEach((rec, i) => {
102
+ console.log(`${i + 1}. ${rec}`);
103
+ });
104
+ console.log();
105
+ }
106
+ function displayCategoryIssues(results, maxToShow) {
107
+ let shown = 0;
108
+ for (const result of results) {
109
+ if (shown >= maxToShow) break;
110
+ for (const issue of result.issues) {
111
+ if (shown >= maxToShow) break;
112
+ const severityColor = issue.severity === "critical" ? chalk.red : issue.severity === "major" ? chalk.yellow : issue.severity === "minor" ? chalk.blue : chalk.gray;
113
+ console.log(
114
+ `${severityColor(issue.severity.toUpperCase())} ${chalk.dim(
115
+ `${issue.location.file}:${issue.location.line}`
116
+ )}`
117
+ );
118
+ console.log(` ${issue.message}`);
119
+ if (issue.suggestion) {
120
+ console.log(` ${chalk.dim("\u2192")} ${chalk.italic(issue.suggestion)}`);
121
+ }
122
+ console.log();
123
+ shown++;
124
+ }
125
+ }
126
+ const remaining = results.reduce((sum, r) => sum + r.issues.length, 0) - shown;
127
+ if (remaining > 0) {
128
+ console.log(chalk.dim(` ... and ${remaining} more issues
129
+ `));
130
+ }
131
+ }
132
+ function generateMarkdownReport(report, elapsedTime) {
133
+ const { summary, results, recommendations } = report;
134
+ let markdown = `# Consistency Analysis Report
135
+
136
+ `;
137
+ markdown += `**Generated:** ${(/* @__PURE__ */ new Date()).toISOString()}
138
+ `;
139
+ markdown += `**Analysis Time:** ${elapsedTime}s
140
+
141
+ `;
142
+ markdown += `## Summary
143
+
144
+ `;
145
+ markdown += `- **Files Analyzed:** ${summary.filesAnalyzed}
146
+ `;
147
+ markdown += `- **Total Issues:** ${summary.totalIssues}
148
+ `;
149
+ markdown += ` - Naming: ${summary.namingIssues}
150
+ `;
151
+ markdown += ` - Patterns: ${summary.patternIssues}
152
+ `;
153
+ markdown += ` - Architecture: ${summary.architectureIssues}
154
+
155
+ `;
156
+ if (summary.totalIssues === 0) {
157
+ markdown += `\u2728 No consistency issues found!
158
+ `;
159
+ return markdown;
160
+ }
161
+ markdown += `## Issues by Category
162
+
163
+ `;
164
+ const namingResults = results.filter(
165
+ (r) => r.issues.some((i) => i.category === "naming")
166
+ );
167
+ if (namingResults.length > 0) {
168
+ markdown += `### \u{1F3F7}\uFE0F Naming Issues
169
+
170
+ `;
171
+ for (const result of namingResults) {
172
+ for (const issue of result.issues) {
173
+ if (issue.category !== "naming") continue;
174
+ markdown += `- **${issue.severity.toUpperCase()}** \`${issue.location.file}:${issue.location.line}\`
175
+ `;
176
+ markdown += ` - ${issue.message}
177
+ `;
178
+ if (issue.suggestion) {
179
+ markdown += ` - \u{1F4A1} ${issue.suggestion}
180
+ `;
181
+ }
182
+ }
183
+ }
184
+ markdown += `
185
+ `;
186
+ }
187
+ const patternResults = results.filter(
188
+ (r) => r.issues.some((i) => i.category === "patterns")
189
+ );
190
+ if (patternResults.length > 0) {
191
+ markdown += `### \u{1F504} Pattern Issues
192
+
193
+ `;
194
+ for (const result of patternResults) {
195
+ for (const issue of result.issues) {
196
+ if (issue.category !== "patterns") continue;
197
+ markdown += `- **${issue.severity.toUpperCase()}** ${issue.message}
198
+ `;
199
+ if (issue.examples && issue.examples.length > 0) {
200
+ markdown += ` - Examples:
201
+ `;
202
+ issue.examples.forEach((ex) => {
203
+ markdown += ` - ${ex}
204
+ `;
205
+ });
206
+ }
207
+ if (issue.suggestion) {
208
+ markdown += ` - \u{1F4A1} ${issue.suggestion}
209
+ `;
210
+ }
211
+ }
212
+ }
213
+ markdown += `
214
+ `;
215
+ }
216
+ markdown += `## Recommendations
217
+
218
+ `;
219
+ recommendations.forEach((rec, i) => {
220
+ markdown += `${i + 1}. ${rec}
221
+ `;
222
+ });
223
+ return markdown;
224
+ }
@@ -0,0 +1,77 @@
1
+ import { ScanOptions, AnalysisResult, Issue } from '@aiready/core';
2
+
3
+ interface ConsistencyOptions extends ScanOptions {
4
+ /** Check naming conventions and quality */
5
+ checkNaming?: boolean;
6
+ /** Check code pattern consistency */
7
+ checkPatterns?: boolean;
8
+ /** Check architectural consistency */
9
+ checkArchitecture?: boolean;
10
+ /** Minimum severity to report */
11
+ minSeverity?: 'info' | 'minor' | 'major' | 'critical';
12
+ }
13
+ interface ConsistencyIssue extends Issue {
14
+ type: 'naming-inconsistency' | 'naming-quality' | 'pattern-inconsistency' | 'architecture-inconsistency';
15
+ category: 'naming' | 'patterns' | 'architecture';
16
+ /** Examples of the inconsistency found */
17
+ examples?: string[];
18
+ /** Suggested fix or convention to follow */
19
+ suggestion?: string;
20
+ }
21
+ interface NamingIssue {
22
+ file: string;
23
+ line: number;
24
+ column?: number;
25
+ type: 'poor-naming' | 'convention-mix' | 'abbreviation' | 'unclear';
26
+ identifier: string;
27
+ suggestion?: string;
28
+ severity: 'critical' | 'major' | 'minor' | 'info';
29
+ }
30
+ interface PatternIssue {
31
+ files: string[];
32
+ type: 'error-handling' | 'async-style' | 'import-style' | 'api-design';
33
+ description: string;
34
+ examples: string[];
35
+ severity: 'critical' | 'major' | 'minor' | 'info';
36
+ }
37
+ interface ArchitectureIssue {
38
+ type: 'file-organization' | 'module-structure' | 'export-style';
39
+ description: string;
40
+ affectedPaths: string[];
41
+ severity: 'critical' | 'major' | 'minor' | 'info';
42
+ }
43
+ interface ConsistencyReport {
44
+ summary: {
45
+ totalIssues: number;
46
+ namingIssues: number;
47
+ patternIssues: number;
48
+ architectureIssues: number;
49
+ filesAnalyzed: number;
50
+ };
51
+ results: AnalysisResult[];
52
+ recommendations: string[];
53
+ }
54
+
55
+ /**
56
+ * Main consistency analyzer that orchestrates all analysis types
57
+ */
58
+ declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
59
+
60
+ /**
61
+ * Analyzes naming conventions and quality
62
+ */
63
+ declare function analyzeNaming(files: string[]): Promise<NamingIssue[]>;
64
+ /**
65
+ * Detects naming convention patterns across the codebase
66
+ */
67
+ declare function detectNamingConventions(files: string[], allIssues: NamingIssue[]): {
68
+ dominantConvention: 'camelCase' | 'snake_case' | 'PascalCase' | 'mixed';
69
+ conventionScore: number;
70
+ };
71
+
72
+ /**
73
+ * Analyzes code pattern consistency
74
+ */
75
+ declare function analyzePatterns(files: string[]): Promise<PatternIssue[]>;
76
+
77
+ export { type ArchitectureIssue, type ConsistencyIssue, type ConsistencyOptions, type ConsistencyReport, type NamingIssue, type PatternIssue, analyzeConsistency, analyzeNaming, analyzePatterns, detectNamingConventions };
@@ -0,0 +1,77 @@
1
+ import { ScanOptions, AnalysisResult, Issue } from '@aiready/core';
2
+
3
+ interface ConsistencyOptions extends ScanOptions {
4
+ /** Check naming conventions and quality */
5
+ checkNaming?: boolean;
6
+ /** Check code pattern consistency */
7
+ checkPatterns?: boolean;
8
+ /** Check architectural consistency */
9
+ checkArchitecture?: boolean;
10
+ /** Minimum severity to report */
11
+ minSeverity?: 'info' | 'minor' | 'major' | 'critical';
12
+ }
13
+ interface ConsistencyIssue extends Issue {
14
+ type: 'naming-inconsistency' | 'naming-quality' | 'pattern-inconsistency' | 'architecture-inconsistency';
15
+ category: 'naming' | 'patterns' | 'architecture';
16
+ /** Examples of the inconsistency found */
17
+ examples?: string[];
18
+ /** Suggested fix or convention to follow */
19
+ suggestion?: string;
20
+ }
21
+ interface NamingIssue {
22
+ file: string;
23
+ line: number;
24
+ column?: number;
25
+ type: 'poor-naming' | 'convention-mix' | 'abbreviation' | 'unclear';
26
+ identifier: string;
27
+ suggestion?: string;
28
+ severity: 'critical' | 'major' | 'minor' | 'info';
29
+ }
30
+ interface PatternIssue {
31
+ files: string[];
32
+ type: 'error-handling' | 'async-style' | 'import-style' | 'api-design';
33
+ description: string;
34
+ examples: string[];
35
+ severity: 'critical' | 'major' | 'minor' | 'info';
36
+ }
37
+ interface ArchitectureIssue {
38
+ type: 'file-organization' | 'module-structure' | 'export-style';
39
+ description: string;
40
+ affectedPaths: string[];
41
+ severity: 'critical' | 'major' | 'minor' | 'info';
42
+ }
43
+ interface ConsistencyReport {
44
+ summary: {
45
+ totalIssues: number;
46
+ namingIssues: number;
47
+ patternIssues: number;
48
+ architectureIssues: number;
49
+ filesAnalyzed: number;
50
+ };
51
+ results: AnalysisResult[];
52
+ recommendations: string[];
53
+ }
54
+
55
+ /**
56
+ * Main consistency analyzer that orchestrates all analysis types
57
+ */
58
+ declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
59
+
60
+ /**
61
+ * Analyzes naming conventions and quality
62
+ */
63
+ declare function analyzeNaming(files: string[]): Promise<NamingIssue[]>;
64
+ /**
65
+ * Detects naming convention patterns across the codebase
66
+ */
67
+ declare function detectNamingConventions(files: string[], allIssues: NamingIssue[]): {
68
+ dominantConvention: 'camelCase' | 'snake_case' | 'PascalCase' | 'mixed';
69
+ conventionScore: number;
70
+ };
71
+
72
+ /**
73
+ * Analyzes code pattern consistency
74
+ */
75
+ declare function analyzePatterns(files: string[]): Promise<PatternIssue[]>;
76
+
77
+ export { type ArchitectureIssue, type ConsistencyIssue, type ConsistencyOptions, type ConsistencyReport, type NamingIssue, type PatternIssue, analyzeConsistency, analyzeNaming, analyzePatterns, detectNamingConventions };