mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-03-26 00:57:23 +01:00
Task 2: Apply automated Biome linter fixes - No auto-fixes available (223 errors remain)
This commit is contained in:
parent
7dbfc542b3
commit
45afc24aef
11 changed files with 1065 additions and 404 deletions
78
scripts/README.md
Normal file
78
scripts/README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# TypeScript Error Cataloging Scripts
|
||||
|
||||
## Overview
|
||||
|
||||
This directory contains scripts for analyzing and cataloging TypeScript errors in the Fantasy Map Generator codebase.
|
||||
|
||||
## catalog-errors.ts
|
||||
|
||||
A script that runs `tsc --noEmit` to capture TypeScript errors, parses them into structured JSON format, categorizes them, and generates reports.
|
||||
|
||||
### Usage
|
||||
|
||||
```bash
|
||||
npm run catalog-errors
|
||||
```
|
||||
|
||||
### Output Files
|
||||
|
||||
The script generates two files in the project root:
|
||||
|
||||
1. **error-catalog.json** - Structured JSON catalog containing:
|
||||
- Timestamp of analysis
|
||||
- Total error count
|
||||
- Array of all errors with file, line, column, code, message, category, and severity
|
||||
- Errors grouped by category
|
||||
- Errors grouped by file
|
||||
|
||||
2. **error-report.txt** - Human-readable report containing:
|
||||
- Summary statistics
|
||||
- Error counts by category
|
||||
- Error counts by file (sorted by count)
|
||||
- Detailed error listings organized by category
|
||||
|
||||
### Error Categories
|
||||
|
||||
The script categorizes errors into the following types:
|
||||
|
||||
- **implicit-any**: Variables or parameters without explicit type annotations (TS7006, TS7031, TS7034)
|
||||
- **node-protocol**: Missing 'node:' prefix for Node.js built-in module imports
|
||||
- **type-conversion**: Type assignment and conversion issues
|
||||
- **unused-parameter**: Parameters not used in function bodies (TS6133)
|
||||
- **dynamic-import**: Dynamic namespace import access issues
|
||||
- **type-compatibility**: Type compatibility mismatches (TS2345, TS2322)
|
||||
- **global-conflict**: Global variable type declaration conflicts
|
||||
- **other**: Uncategorized errors
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
================================================================================
|
||||
Summary
|
||||
================================================================================
|
||||
Total Errors: 223
|
||||
|
||||
By Category:
|
||||
implicit-any: 180
|
||||
type-conversion: 5
|
||||
type-compatibility: 3
|
||||
other: 35
|
||||
|
||||
Top 5 Files by Error Count:
|
||||
src/modules/states-generator.ts: 40
|
||||
src/modules/provinces-generator.ts: 39
|
||||
src/modules/zones-generator.ts: 32
|
||||
src/modules/burgs-generator.ts: 18
|
||||
src/modules/religions-generator.ts: 17
|
||||
```
|
||||
|
||||
## Integration with Cleanup Process
|
||||
|
||||
This cataloging infrastructure supports the systematic TypeScript cleanup effort by:
|
||||
|
||||
1. Providing baseline error counts before cleanup begins
|
||||
2. Enabling progress tracking as errors are resolved
|
||||
3. Identifying error patterns and priorities
|
||||
4. Supporting automated validation after fixes are applied
|
||||
|
||||
Run the script periodically during cleanup to track progress and verify that fixes are reducing the error count without introducing new issues.
|
||||
279
scripts/catalog-errors.ts
Normal file
279
scripts/catalog-errors.ts
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* TypeScript Error Cataloging Script
|
||||
*
|
||||
* This script runs `tsc --noEmit` to capture TypeScript errors,
|
||||
* parses them into structured JSON format, categorizes them,
|
||||
* and generates a report showing counts by category and file.
|
||||
*/
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
import { writeFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
enum ErrorCategory {
|
||||
ImplicitAny = 'implicit-any',
|
||||
NodeProtocol = 'node-protocol',
|
||||
TypeConversion = 'type-conversion',
|
||||
UnusedParameter = 'unused-parameter',
|
||||
DynamicImport = 'dynamic-import',
|
||||
TypeCompatibility = 'type-compatibility',
|
||||
GlobalConflict = 'global-conflict',
|
||||
Other = 'other'
|
||||
}
|
||||
|
||||
interface TypeScriptError {
|
||||
file: string;
|
||||
line: number;
|
||||
column: number;
|
||||
code: string;
|
||||
message: string;
|
||||
category: ErrorCategory;
|
||||
severity: 'error' | 'warning';
|
||||
}
|
||||
|
||||
interface ErrorCatalog {
|
||||
timestamp: string;
|
||||
totalErrors: number;
|
||||
errors: TypeScriptError[];
|
||||
errorsByCategory: Record<ErrorCategory, TypeScriptError[]>;
|
||||
errorsByFile: Record<string, TypeScriptError[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Categorize a TypeScript error based on its code and message
|
||||
*/
|
||||
function categorizeError(code: string, message: string): ErrorCategory {
|
||||
// Implicit any types
|
||||
if (code === 'TS7006' || code === 'TS7031' || code === 'TS7034') {
|
||||
return ErrorCategory.ImplicitAny;
|
||||
}
|
||||
|
||||
// Node.js import protocol issues
|
||||
if (message.includes("'node:'") || message.includes('node protocol')) {
|
||||
return ErrorCategory.NodeProtocol;
|
||||
}
|
||||
|
||||
// Type conversion issues
|
||||
if (message.includes('Type') && (message.includes('is not assignable to') || message.includes('conversion'))) {
|
||||
return ErrorCategory.TypeConversion;
|
||||
}
|
||||
|
||||
// Unused parameters
|
||||
if (code === 'TS6133' && message.includes('parameter')) {
|
||||
return ErrorCategory.UnusedParameter;
|
||||
}
|
||||
|
||||
// Dynamic import/namespace access
|
||||
if (message.includes('dynamic') || message.includes('namespace')) {
|
||||
return ErrorCategory.DynamicImport;
|
||||
}
|
||||
|
||||
// Type compatibility
|
||||
if (code === 'TS2345' || code === 'TS2322') {
|
||||
return ErrorCategory.TypeCompatibility;
|
||||
}
|
||||
|
||||
// Global variable conflicts
|
||||
if (message.includes('global') || message.includes('duplicate')) {
|
||||
return ErrorCategory.GlobalConflict;
|
||||
}
|
||||
|
||||
return ErrorCategory.Other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse TypeScript compiler output into structured errors
|
||||
*/
|
||||
function parseTypeScriptErrors(output: string): TypeScriptError[] {
|
||||
const errors: TypeScriptError[] = [];
|
||||
const lines = output.split('\n');
|
||||
|
||||
// TypeScript error format: file(line,column): error TSxxxx: message
|
||||
const errorPattern = /^(.+?)\((\d+),(\d+)\):\s+(error|warning)\s+(TS\d+):\s+(.+)$/;
|
||||
|
||||
for (const line of lines) {
|
||||
const match = line.match(errorPattern);
|
||||
if (match) {
|
||||
const [, file, lineNum, column, severity, code, message] = match;
|
||||
errors.push({
|
||||
file: file.trim(),
|
||||
line: parseInt(lineNum, 10),
|
||||
column: parseInt(column, 10),
|
||||
code,
|
||||
message: message.trim(),
|
||||
category: categorizeError(code, message),
|
||||
severity: severity as 'error' | 'warning'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group errors by category
|
||||
*/
|
||||
function groupByCategory(errors: TypeScriptError[]): Record<ErrorCategory, TypeScriptError[]> {
|
||||
const grouped: Record<ErrorCategory, TypeScriptError[]> = {
|
||||
[ErrorCategory.ImplicitAny]: [],
|
||||
[ErrorCategory.NodeProtocol]: [],
|
||||
[ErrorCategory.TypeConversion]: [],
|
||||
[ErrorCategory.UnusedParameter]: [],
|
||||
[ErrorCategory.DynamicImport]: [],
|
||||
[ErrorCategory.TypeCompatibility]: [],
|
||||
[ErrorCategory.GlobalConflict]: [],
|
||||
[ErrorCategory.Other]: []
|
||||
};
|
||||
|
||||
for (const error of errors) {
|
||||
grouped[error.category].push(error);
|
||||
}
|
||||
|
||||
return grouped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group errors by file
|
||||
*/
|
||||
function groupByFile(errors: TypeScriptError[]): Record<string, TypeScriptError[]> {
|
||||
const grouped: Record<string, TypeScriptError[]> = {};
|
||||
|
||||
for (const error of errors) {
|
||||
if (!grouped[error.file]) {
|
||||
grouped[error.file] = [];
|
||||
}
|
||||
grouped[error.file].push(error);
|
||||
}
|
||||
|
||||
return grouped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a human-readable report
|
||||
*/
|
||||
function generateReport(catalog: ErrorCatalog): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
lines.push('='.repeat(80));
|
||||
lines.push('TypeScript Error Catalog Report');
|
||||
lines.push('='.repeat(80));
|
||||
lines.push('');
|
||||
lines.push(`Generated: ${catalog.timestamp}`);
|
||||
lines.push(`Total Errors: ${catalog.totalErrors}`);
|
||||
lines.push('');
|
||||
|
||||
// Errors by category
|
||||
lines.push('-'.repeat(80));
|
||||
lines.push('Errors by Category');
|
||||
lines.push('-'.repeat(80));
|
||||
lines.push('');
|
||||
|
||||
for (const [category, errors] of Object.entries(catalog.errorsByCategory)) {
|
||||
if (errors.length > 0) {
|
||||
lines.push(`${category}: ${errors.length} errors`);
|
||||
}
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// Errors by file
|
||||
lines.push('-'.repeat(80));
|
||||
lines.push('Errors by File');
|
||||
lines.push('-'.repeat(80));
|
||||
lines.push('');
|
||||
|
||||
const sortedFiles = Object.entries(catalog.errorsByFile)
|
||||
.sort((a, b) => b[1].length - a[1].length);
|
||||
|
||||
for (const [file, errors] of sortedFiles) {
|
||||
lines.push(`${file}: ${errors.length} errors`);
|
||||
}
|
||||
lines.push('');
|
||||
|
||||
// Detailed error list by category
|
||||
lines.push('-'.repeat(80));
|
||||
lines.push('Detailed Errors by Category');
|
||||
lines.push('-'.repeat(80));
|
||||
lines.push('');
|
||||
|
||||
for (const [category, errors] of Object.entries(catalog.errorsByCategory)) {
|
||||
if (errors.length > 0) {
|
||||
lines.push('');
|
||||
lines.push(`## ${category} (${errors.length} errors)`);
|
||||
lines.push('');
|
||||
|
||||
for (const error of errors) {
|
||||
lines.push(` ${error.file}(${error.line},${error.column}): ${error.code}`);
|
||||
lines.push(` ${error.message}`);
|
||||
lines.push('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Main execution
|
||||
*/
|
||||
function main() {
|
||||
console.log('Running TypeScript compiler to capture errors...');
|
||||
|
||||
let output = '';
|
||||
try {
|
||||
// Run tsc --noEmit and capture output
|
||||
execSync('npx tsc --noEmit', { encoding: 'utf-8', stdio: 'pipe' });
|
||||
console.log('No TypeScript errors found!');
|
||||
output = '';
|
||||
} catch (error: any) {
|
||||
// tsc exits with non-zero code when errors exist
|
||||
output = error.stdout || error.stderr || '';
|
||||
}
|
||||
|
||||
console.log('Parsing errors...');
|
||||
const errors = parseTypeScriptErrors(output);
|
||||
|
||||
console.log('Categorizing errors...');
|
||||
const errorsByCategory = groupByCategory(errors);
|
||||
const errorsByFile = groupByFile(errors);
|
||||
|
||||
const catalog: ErrorCatalog = {
|
||||
timestamp: new Date().toISOString(),
|
||||
totalErrors: errors.length,
|
||||
errors,
|
||||
errorsByCategory,
|
||||
errorsByFile
|
||||
};
|
||||
|
||||
// Write JSON catalog
|
||||
const jsonPath = resolve(process.cwd(), 'error-catalog.json');
|
||||
writeFileSync(jsonPath, JSON.stringify(catalog, null, 2));
|
||||
console.log(`\nJSON catalog written to: ${jsonPath}`);
|
||||
|
||||
// Write human-readable report
|
||||
const reportPath = resolve(process.cwd(), 'error-report.txt');
|
||||
const report = generateReport(catalog);
|
||||
writeFileSync(reportPath, report);
|
||||
console.log(`Report written to: ${reportPath}`);
|
||||
|
||||
// Print summary to console
|
||||
console.log('\n' + '='.repeat(80));
|
||||
console.log('Summary');
|
||||
console.log('='.repeat(80));
|
||||
console.log(`Total Errors: ${catalog.totalErrors}`);
|
||||
console.log('\nBy Category:');
|
||||
for (const [category, errors] of Object.entries(errorsByCategory)) {
|
||||
if (errors.length > 0) {
|
||||
console.log(` ${category}: ${errors.length}`);
|
||||
}
|
||||
}
|
||||
console.log('\nTop 5 Files by Error Count:');
|
||||
const topFiles = Object.entries(errorsByFile)
|
||||
.sort((a, b) => b[1].length - a[1].length)
|
||||
.slice(0, 5);
|
||||
for (const [file, errors] of topFiles) {
|
||||
console.log(` ${file}: ${errors.length}`);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue