@aiready/consistency 0.20.2 → 0.20.4
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 +9 -9
- package/.turbo/turbo-lint.log +24 -17
- package/.turbo/turbo-test.log +12 -12
- package/dist/chunk-3ZB6FFRL.mjs +661 -0
- package/dist/chunk-6BM5MV3S.mjs +719 -0
- package/dist/chunk-BYY6MD5T.mjs +729 -0
- package/dist/chunk-DSI3TEO2.mjs +662 -0
- package/dist/chunk-H6S7WKSQ.mjs +729 -0
- package/dist/chunk-LMOXGPCM.mjs +722 -0
- package/dist/chunk-MAPVFXBP.mjs +708 -0
- package/dist/chunk-NPWCJZUG.mjs +708 -0
- package/dist/chunk-S6BZVTWN.mjs +731 -0
- package/dist/chunk-ZB6UK276.mjs +662 -0
- package/dist/cli.js +102 -158
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +102 -158
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/analyzer.ts +131 -183
- package/src/analyzers/naming-ast.ts +8 -3
- package/src/analyzers/naming-generalized.ts +3 -4
- package/src/analyzers/naming.ts +2 -0
- package/src/analyzers/patterns.ts +2 -5
- package/src/types.ts +6 -1
package/dist/cli.js
CHANGED
|
@@ -353,7 +353,7 @@ function checkNamingConvention(name, convention, node, file, issues, context) {
|
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
355
|
function checkVariableNaming(varInfo, file, issues, context) {
|
|
356
|
-
const { name,
|
|
356
|
+
const { name, line, options } = varInfo;
|
|
357
357
|
if (isAcceptableInContext(name, context, options)) {
|
|
358
358
|
return;
|
|
359
359
|
}
|
|
@@ -475,7 +475,6 @@ async function analyzeNamingGeneralized(files) {
|
|
|
475
475
|
const conventions = parser.getNamingConventions();
|
|
476
476
|
for (const exp of result.exports) {
|
|
477
477
|
let pattern;
|
|
478
|
-
const typeName = exp.type;
|
|
479
478
|
if (exp.type === "class") {
|
|
480
479
|
pattern = conventions.classPattern;
|
|
481
480
|
} else if (exp.type === "interface" && conventions.interfacePattern) {
|
|
@@ -491,7 +490,7 @@ async function analyzeNamingGeneralized(files) {
|
|
|
491
490
|
}
|
|
492
491
|
if (pattern && !pattern.test(exp.name)) {
|
|
493
492
|
issues.push({
|
|
494
|
-
type: "
|
|
493
|
+
type: "naming-inconsistency",
|
|
495
494
|
identifier: exp.name,
|
|
496
495
|
file,
|
|
497
496
|
line: exp.loc?.start.line || 1,
|
|
@@ -507,7 +506,7 @@ async function analyzeNamingGeneralized(files) {
|
|
|
507
506
|
if (spec === "*" || spec === "default") continue;
|
|
508
507
|
if (!conventions.variablePattern.test(spec) && !conventions.classPattern.test(spec)) {
|
|
509
508
|
issues.push({
|
|
510
|
-
type: "
|
|
509
|
+
type: "naming-inconsistency",
|
|
511
510
|
identifier: spec,
|
|
512
511
|
file,
|
|
513
512
|
line: imp.loc?.start.line || 1,
|
|
@@ -533,7 +532,6 @@ async function analyzePatterns(filePaths) {
|
|
|
533
532
|
const issues = [];
|
|
534
533
|
const contents = /* @__PURE__ */ new Map();
|
|
535
534
|
const tryCatchPattern = /try\s*\{/g;
|
|
536
|
-
const catchPattern = /catch\s*\(\s*(\w+)\s*\)/g;
|
|
537
535
|
const styleStats = {
|
|
538
536
|
tryCatch: 0,
|
|
539
537
|
thenCatch: 0,
|
|
@@ -554,7 +552,6 @@ async function analyzePatterns(filePaths) {
|
|
|
554
552
|
void err;
|
|
555
553
|
}
|
|
556
554
|
}
|
|
557
|
-
const totalFiles = filePaths.length;
|
|
558
555
|
if (styleStats.tryCatch > 0 && styleStats.thenCatch > 0) {
|
|
559
556
|
const dominant = styleStats.tryCatch >= styleStats.thenCatch ? "try-catch" : ".catch()";
|
|
560
557
|
const minority = dominant === "try-catch" ? ".catch()" : "try-catch";
|
|
@@ -563,7 +560,7 @@ async function analyzePatterns(filePaths) {
|
|
|
563
560
|
const c = contents.get(f) || "";
|
|
564
561
|
return minority === "try-catch" ? c.match(tryCatchPattern) : c.match(/\.catch\s*\(/);
|
|
565
562
|
}),
|
|
566
|
-
type: "
|
|
563
|
+
type: "pattern-inconsistency",
|
|
567
564
|
description: `Mixed error handling styles: codebase primarily uses ${dominant}, but found ${minority} in some files.`,
|
|
568
565
|
examples: [dominant, minority],
|
|
569
566
|
severity: import_core4.Severity.Minor
|
|
@@ -576,7 +573,7 @@ async function analyzePatterns(filePaths) {
|
|
|
576
573
|
const c = contents.get(f) || "";
|
|
577
574
|
return minority === "CommonJS (require)" ? c.match(/\brequire\s*\(/) : c.match(/\bimport\b/);
|
|
578
575
|
}),
|
|
579
|
-
type: "
|
|
576
|
+
type: "pattern-inconsistency",
|
|
580
577
|
description: `Mixed module systems: found both ESM and CommonJS.`,
|
|
581
578
|
examples: ['import X from "y"', 'const X = require("y")'],
|
|
582
579
|
severity: import_core4.Severity.Major
|
|
@@ -610,130 +607,126 @@ async function analyzeConsistency(options) {
|
|
|
610
607
|
const results = [];
|
|
611
608
|
const fileIssuesMap = /* @__PURE__ */ new Map();
|
|
612
609
|
for (const issue of namingIssues) {
|
|
613
|
-
if (!shouldIncludeSeverity(issue.severity, minSeverity))
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
type: issue.type === "convention-mix" ? import_core5.IssueType.NamingInconsistency : import_core5.IssueType.NamingQuality,
|
|
618
|
-
category: "naming",
|
|
619
|
-
severity: getSeverityEnum(issue.severity),
|
|
620
|
-
message: `${issue.type}: ${issue.identifier}`,
|
|
621
|
-
location: {
|
|
622
|
-
file: issue.file,
|
|
623
|
-
line: issue.line,
|
|
624
|
-
column: issue.column
|
|
625
|
-
},
|
|
626
|
-
suggestion: issue.suggestion
|
|
627
|
-
};
|
|
628
|
-
if (!fileIssuesMap.has(issue.file)) {
|
|
629
|
-
fileIssuesMap.set(issue.file, []);
|
|
630
|
-
}
|
|
631
|
-
fileIssuesMap.get(issue.file).push(consistencyIssue);
|
|
610
|
+
if (!shouldIncludeSeverity(issue.severity, minSeverity)) continue;
|
|
611
|
+
const fileName = issue.fileName || issue.file || issue.filePath || "unknown";
|
|
612
|
+
if (!fileIssuesMap.has(fileName)) fileIssuesMap.set(fileName, []);
|
|
613
|
+
fileIssuesMap.get(fileName).push(issue);
|
|
632
614
|
}
|
|
633
615
|
for (const issue of patternIssues) {
|
|
634
|
-
if (!shouldIncludeSeverity(issue.severity, minSeverity))
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
type: import_core5.IssueType.PatternInconsistency,
|
|
639
|
-
category: "patterns",
|
|
640
|
-
severity: getSeverityEnum(issue.severity),
|
|
641
|
-
message: issue.description,
|
|
642
|
-
location: {
|
|
643
|
-
file: issue.files[0] || "multiple files",
|
|
644
|
-
line: 1
|
|
645
|
-
},
|
|
646
|
-
examples: issue.examples,
|
|
647
|
-
suggestion: `Standardize ${issue.type} patterns across ${issue.files.length} files`
|
|
648
|
-
};
|
|
649
|
-
const firstFile = issue.files[0];
|
|
650
|
-
if (firstFile && !fileIssuesMap.has(firstFile)) {
|
|
651
|
-
fileIssuesMap.set(firstFile, []);
|
|
652
|
-
}
|
|
653
|
-
if (firstFile) {
|
|
654
|
-
fileIssuesMap.get(firstFile).push(consistencyIssue);
|
|
655
|
-
}
|
|
616
|
+
if (!shouldIncludeSeverity(issue.severity, minSeverity)) continue;
|
|
617
|
+
const fileName = issue.fileName || issue.file || issue.filePath || (Array.isArray(issue.files) ? issue.files[0] : "unknown");
|
|
618
|
+
if (!fileIssuesMap.has(fileName)) fileIssuesMap.set(fileName, []);
|
|
619
|
+
fileIssuesMap.get(fileName).push(issue);
|
|
656
620
|
}
|
|
657
|
-
for (const [fileName, issues] of fileIssuesMap) {
|
|
621
|
+
for (const [fileName, issues] of fileIssuesMap.entries()) {
|
|
658
622
|
results.push({
|
|
659
623
|
fileName,
|
|
660
|
-
issues,
|
|
624
|
+
issues: issues.map((i) => transformToIssue(i)),
|
|
661
625
|
metrics: {
|
|
662
626
|
consistencyScore: calculateConsistencyScore(issues)
|
|
663
627
|
}
|
|
664
628
|
});
|
|
665
629
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
return val === 4 ? 0 : val === 3 ? 1 : val === 2 ? 2 : 3;
|
|
677
|
-
})
|
|
630
|
+
const recommendations = [];
|
|
631
|
+
if (namingIssues.length > 0) {
|
|
632
|
+
recommendations.push("Standardize naming conventions across the codebase");
|
|
633
|
+
}
|
|
634
|
+
if (patternIssues.length > 0) {
|
|
635
|
+
recommendations.push("Consolidate repetitive implementation patterns");
|
|
636
|
+
}
|
|
637
|
+
if (results.some((r) => (r.metrics?.consistencyScore ?? 1) < 0.8)) {
|
|
638
|
+
recommendations.push(
|
|
639
|
+
"Improve cross-module consistency to reduce AI confusion"
|
|
678
640
|
);
|
|
679
|
-
|
|
680
|
-
return maxSeverityA - maxSeverityB;
|
|
681
|
-
}
|
|
682
|
-
return fileResultB.issues.length - fileResultA.issues.length;
|
|
683
|
-
});
|
|
684
|
-
const recommendations = generateRecommendations(namingIssues, patternIssues);
|
|
685
|
-
const namingCountFiltered = namingIssues.filter(
|
|
686
|
-
(i) => shouldIncludeSeverity(i.severity, minSeverity)
|
|
687
|
-
).length;
|
|
688
|
-
const patternCountFiltered = patternIssues.filter(
|
|
689
|
-
(i) => shouldIncludeSeverity(i.severity, minSeverity)
|
|
690
|
-
).length;
|
|
641
|
+
}
|
|
691
642
|
return {
|
|
643
|
+
results,
|
|
692
644
|
summary: {
|
|
693
|
-
totalIssues: namingCountFiltered + patternCountFiltered,
|
|
694
|
-
namingIssues: namingCountFiltered,
|
|
695
|
-
patternIssues: patternCountFiltered,
|
|
696
|
-
architectureIssues: 0,
|
|
697
645
|
filesAnalyzed: filePaths.length,
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
)
|
|
646
|
+
totalIssues: results.reduce((acc, r) => acc + r.issues.length, 0),
|
|
647
|
+
namingIssues: namingIssues.length,
|
|
648
|
+
patternIssues: patternIssues.length,
|
|
649
|
+
architectureIssues: 0
|
|
703
650
|
},
|
|
704
|
-
|
|
705
|
-
|
|
651
|
+
recommendations,
|
|
652
|
+
metadata: {
|
|
653
|
+
toolName: "naming-consistency",
|
|
654
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
655
|
+
}
|
|
706
656
|
};
|
|
707
657
|
}
|
|
708
|
-
function
|
|
709
|
-
|
|
710
|
-
if (s === import_core5.Severity.Major || s === "major") return 3;
|
|
711
|
-
if (s === import_core5.Severity.Minor || s === "minor") return 2;
|
|
712
|
-
if (s === import_core5.Severity.Info || s === "info") return 1;
|
|
713
|
-
return 0;
|
|
658
|
+
function shouldIncludeSeverity(severity, minSeverity) {
|
|
659
|
+
return (0, import_core5.getSeverityLevel)(severity) >= (0, import_core5.getSeverityLevel)(minSeverity);
|
|
714
660
|
}
|
|
715
|
-
function
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
661
|
+
function getIssueType(type) {
|
|
662
|
+
if (!type) return import_core5.IssueType.NamingInconsistency;
|
|
663
|
+
const typeMap = {
|
|
664
|
+
"naming-inconsistency": import_core5.IssueType.NamingInconsistency,
|
|
665
|
+
"naming-quality": import_core5.IssueType.NamingQuality,
|
|
666
|
+
"pattern-inconsistency": import_core5.IssueType.PatternInconsistency,
|
|
667
|
+
"architecture-inconsistency": import_core5.IssueType.ArchitectureInconsistency,
|
|
668
|
+
"error-handling": import_core5.IssueType.PatternInconsistency,
|
|
669
|
+
"async-style": import_core5.IssueType.PatternInconsistency,
|
|
670
|
+
"import-style": import_core5.IssueType.PatternInconsistency,
|
|
671
|
+
"api-design": import_core5.IssueType.PatternInconsistency
|
|
672
|
+
};
|
|
673
|
+
return typeMap[type] || import_core5.IssueType.NamingInconsistency;
|
|
729
674
|
}
|
|
730
|
-
function
|
|
731
|
-
|
|
675
|
+
function transformToIssue(i) {
|
|
676
|
+
if (i.message && i.location) {
|
|
677
|
+
return {
|
|
678
|
+
type: getIssueType(i.type),
|
|
679
|
+
severity: i.severity,
|
|
680
|
+
message: i.message,
|
|
681
|
+
location: i.location,
|
|
682
|
+
suggestion: i.suggestion
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
if (i.identifier || i.type) {
|
|
686
|
+
const line = i.line || 1;
|
|
687
|
+
const column = i.column || 1;
|
|
688
|
+
return {
|
|
689
|
+
type: getIssueType(i.type),
|
|
690
|
+
severity: i.severity,
|
|
691
|
+
message: i.suggestion ? `Naming issue: ${i.suggestion}` : `Naming issue for '${i.identifier || "unknown"}'`,
|
|
692
|
+
location: {
|
|
693
|
+
file: i.file || i.fileName || "",
|
|
694
|
+
line,
|
|
695
|
+
column,
|
|
696
|
+
endLine: line,
|
|
697
|
+
endColumn: column + (i.identifier?.length || 10)
|
|
698
|
+
},
|
|
699
|
+
suggestion: i.suggestion
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
if (i.description || i.files) {
|
|
703
|
+
const fileName = Array.isArray(i.files) ? i.files[0] : i.file || "";
|
|
704
|
+
return {
|
|
705
|
+
type: getIssueType(i.type),
|
|
706
|
+
severity: i.severity,
|
|
707
|
+
message: i.description || "Pattern inconsistency found",
|
|
708
|
+
location: {
|
|
709
|
+
file: fileName,
|
|
710
|
+
line: 1,
|
|
711
|
+
column: 1,
|
|
712
|
+
endLine: 1,
|
|
713
|
+
endColumn: 10
|
|
714
|
+
},
|
|
715
|
+
suggestion: i.examples?.[0]
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
return {
|
|
719
|
+
type: getIssueType(i.type),
|
|
720
|
+
severity: i.severity,
|
|
721
|
+
message: i.message || "Unknown issue",
|
|
722
|
+
location: i.location || { file: "", line: 1, column: 1 },
|
|
723
|
+
suggestion: i.suggestion
|
|
724
|
+
};
|
|
732
725
|
}
|
|
733
726
|
function calculateConsistencyScore(issues) {
|
|
734
727
|
let totalWeight = 0;
|
|
735
728
|
for (const issue of issues) {
|
|
736
|
-
const val = getSeverityLevel(issue.severity);
|
|
729
|
+
const val = (0, import_core5.getSeverityLevel)(issue.severity);
|
|
737
730
|
switch (val) {
|
|
738
731
|
case 4:
|
|
739
732
|
totalWeight += 10;
|
|
@@ -753,55 +746,6 @@ function calculateConsistencyScore(issues) {
|
|
|
753
746
|
}
|
|
754
747
|
return Math.max(0, 1 - totalWeight / 100);
|
|
755
748
|
}
|
|
756
|
-
function generateRecommendations(namingIssues, patternIssues) {
|
|
757
|
-
const recommendations = [];
|
|
758
|
-
if (namingIssues.length > 0) {
|
|
759
|
-
const conventionMixCount = namingIssues.filter(
|
|
760
|
-
(i) => i.type === "convention-mix"
|
|
761
|
-
).length;
|
|
762
|
-
if (conventionMixCount > 0) {
|
|
763
|
-
recommendations.push(
|
|
764
|
-
`Standardize naming conventions: Found ${conventionMixCount} snake_case variables in TypeScript/JavaScript (use camelCase)`
|
|
765
|
-
);
|
|
766
|
-
}
|
|
767
|
-
const poorNamingCount = namingIssues.filter(
|
|
768
|
-
(i) => i.type === "poor-naming"
|
|
769
|
-
).length;
|
|
770
|
-
if (poorNamingCount > 0) {
|
|
771
|
-
recommendations.push(
|
|
772
|
-
`Improve variable naming: Found ${poorNamingCount} single-letter or unclear variable names`
|
|
773
|
-
);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
if (patternIssues.length > 0) {
|
|
777
|
-
const errorHandlingIssues = patternIssues.filter(
|
|
778
|
-
(i) => i.type === "error-handling"
|
|
779
|
-
);
|
|
780
|
-
if (errorHandlingIssues.length > 0) {
|
|
781
|
-
recommendations.push(
|
|
782
|
-
"Standardize error handling strategy across the codebase (prefer try-catch with typed errors)"
|
|
783
|
-
);
|
|
784
|
-
}
|
|
785
|
-
const asyncIssues = patternIssues.filter((i) => i.type === "async-style");
|
|
786
|
-
if (asyncIssues.length > 0) {
|
|
787
|
-
recommendations.push(
|
|
788
|
-
"Use async/await consistently instead of mixing with promise chains or callbacks"
|
|
789
|
-
);
|
|
790
|
-
}
|
|
791
|
-
const importIssues = patternIssues.filter((i) => i.type === "import-style");
|
|
792
|
-
if (importIssues.length > 0) {
|
|
793
|
-
recommendations.push(
|
|
794
|
-
"Use ES modules consistently across the project (avoid mixing with CommonJS)"
|
|
795
|
-
);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
if (recommendations.length === 0) {
|
|
799
|
-
recommendations.push(
|
|
800
|
-
"No major consistency issues found! Your codebase follows good practices."
|
|
801
|
-
);
|
|
802
|
-
}
|
|
803
|
-
return recommendations;
|
|
804
|
-
}
|
|
805
749
|
|
|
806
750
|
// src/cli.ts
|
|
807
751
|
var import_chalk = __toESM(require("chalk"));
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -36,7 +36,7 @@ interface NamingIssue {
|
|
|
36
36
|
}
|
|
37
37
|
interface PatternIssue {
|
|
38
38
|
files: string[];
|
|
39
|
-
type: 'error-handling' | 'async-style' | 'import-style' | 'api-design';
|
|
39
|
+
type: 'error-handling' | 'async-style' | 'import-style' | 'api-design' | 'pattern-inconsistency';
|
|
40
40
|
description: string;
|
|
41
41
|
examples: string[];
|
|
42
42
|
severity: Severity;
|
|
@@ -74,6 +74,8 @@ declare function analyzeNamingAST(filePaths: string[]): Promise<NamingIssue[]>;
|
|
|
74
74
|
/**
|
|
75
75
|
* Legacy regex-based naming analyzer
|
|
76
76
|
* (Used as fallback or for languages without AST support)
|
|
77
|
+
* @param filePaths - Array of file paths to analyze
|
|
78
|
+
* @returns Array of naming issues found
|
|
77
79
|
*/
|
|
78
80
|
declare function analyzeNaming(filePaths: string[]): Promise<NamingIssue[]>;
|
|
79
81
|
|
package/dist/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ interface NamingIssue {
|
|
|
36
36
|
}
|
|
37
37
|
interface PatternIssue {
|
|
38
38
|
files: string[];
|
|
39
|
-
type: 'error-handling' | 'async-style' | 'import-style' | 'api-design';
|
|
39
|
+
type: 'error-handling' | 'async-style' | 'import-style' | 'api-design' | 'pattern-inconsistency';
|
|
40
40
|
description: string;
|
|
41
41
|
examples: string[];
|
|
42
42
|
severity: Severity;
|
|
@@ -74,6 +74,8 @@ declare function analyzeNamingAST(filePaths: string[]): Promise<NamingIssue[]>;
|
|
|
74
74
|
/**
|
|
75
75
|
* Legacy regex-based naming analyzer
|
|
76
76
|
* (Used as fallback or for languages without AST support)
|
|
77
|
+
* @param filePaths - Array of file paths to analyze
|
|
78
|
+
* @returns Array of naming issues found
|
|
77
79
|
*/
|
|
78
80
|
declare function analyzeNaming(filePaths: string[]): Promise<NamingIssue[]>;
|
|
79
81
|
|