@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/.turbo/turbo-build.log +24 -0
- package/CONTRIBUTING.md +153 -0
- package/LICENSE +21 -0
- package/README.md +170 -0
- package/dist/chunk-BDDMOIU2.mjs +385 -0
- package/dist/chunk-CF4LU7KE.mjs +384 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +626 -0
- package/dist/cli.mjs +224 -0
- package/dist/index.d.mts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +415 -0
- package/dist/index.mjs +12 -0
- package/package.json +63 -0
- package/src/__tests__/analyzer.test.ts +127 -0
- package/src/analyzer.ts +182 -0
- package/src/analyzers/naming.ts +134 -0
- package/src/analyzers/patterns.ts +192 -0
- package/src/cli.ts +254 -0
- package/src/index.ts +11 -0
- package/src/types.ts +62 -0
- package/tsconfig.json +9 -0
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
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -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 };
|
package/dist/index.d.ts
ADDED
|
@@ -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 };
|