Files
lobehub/scripts/checkConsoleLog.mts
Innei fcdaf9d814 🔧 chore: update eslint v2 configuration and suppressions (#12133)
* v2 init

* chore: update eslint suppressions and package dependencies

- Removed several eslint suppressions related to array sorting and reversing from eslint-suppressions.json to clean up the configuration.
- Updated @lobehub/lint package version from 2.0.0-beta.6 to 2.0.0-beta.7 in package.json for improvements and bug fixes.
- Made minor formatting adjustments in vitest.config.mts and various SKILL.md files for better readability and consistency.

Signed-off-by: Innei <tukon479@gmail.com>

* fix: clean up import statements and formatting

- Removed unnecessary whitespace in replaceComponentImports.ts for improved readability.
- Standardized import statements in contextEngineering.ts and createAgentExecutors.ts by adding missing spaces for consistency.

Signed-off-by: Innei <tukon479@gmail.com>

* chore: update eslint suppressions and clean up code formatting

* 🐛 fix: use vi.hoisted for mock variable initialization

Fix TDZ error in persona service test by using vi.hoisted() to ensure
mock variables are available when vi.mock factory runs.

---------

Signed-off-by: Innei <tukon479@gmail.com>
2026-02-11 13:04:48 +08:00

151 lines
4.2 KiB
TypeScript

#!/usr/bin/env tsx
import { execSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
interface WhitelistConfig {
files?: string[];
patterns?: string[];
}
const WHITELIST_PATH = '.console-log-whitelist.json';
/**
* Load whitelist configuration
*/
const loadWhitelist = (): WhitelistConfig => {
try {
const content = readFileSync(WHITELIST_PATH, 'utf8');
return JSON.parse(content);
} catch {
return { files: [], patterns: [] };
}
};
/**
* Check if a file is whitelisted
*/
const isWhitelisted = (filePath: string, whitelist: WhitelistConfig): boolean => {
const normalizedPath = filePath.replaceAll('\\', '/');
// Check exact file matches
if (whitelist.files?.some((f) => normalizedPath.includes(f.replaceAll('\\', '/')))) {
return true;
}
// Check pattern matches (simple glob-like patterns)
if (whitelist.patterns) {
for (const pattern of whitelist.patterns) {
// Escape dots and replace glob patterns
// Use a placeholder for ** to avoid conflicts with single *
let regexPattern = pattern
.replaceAll('.', '\\.')
.replaceAll('**', '\u0000DOUBLESTAR\u0000')
.replaceAll('*', '[^/]*')
.replaceAll('\u0000DOUBLESTAR\u0000', '.*');
// If pattern ends with /**, match everything under that directory
// If pattern ends with **, just match everything from that point
const regex = new RegExp(`^${regexPattern}`);
if (regex.test(normalizedPath)) {
return true;
}
}
}
return false;
};
/**
* Main check function
*/
const checkConsoleLogs = () => {
const whitelist = loadWhitelist();
console.log('🔍 Checking for console.log statements...\n');
try {
// Search for console.log in TypeScript and JavaScript files
const output = execSync(
`git grep -n "console\\.log" -- "*.ts" "*.tsx" "*.js" "*.jsx" "*.mts" "*.cts" || true`,
{ encoding: 'utf8' },
);
if (!output.trim()) {
console.log('✅ No console.log statements found!');
return;
}
const lines = output.trim().split('\n');
const violations: Array<{ content: string; file: string; line: string }> = [];
for (const line of lines) {
// Parse git grep output: filename:lineNumber:content
const match = line.match(/^([^:]+):(\d+):(.+)$/);
if (!match) continue;
const [, filePath, lineNumber, content] = match;
// Skip if whitelisted
if (isWhitelisted(filePath, whitelist)) {
continue;
}
// Skip comments
const trimmedContent = content.trim();
if (trimmedContent.startsWith('//') || trimmedContent.startsWith('*')) {
continue;
}
violations.push({
content: content.trim(),
file: filePath,
line: lineNumber,
});
}
if (violations.length === 0) {
console.log(
'✅ No console.log violations found (all matches are whitelisted or in comments)!',
);
return;
}
// Report violations as warnings
console.log('⚠️ Found console.log statements in the following files:\n');
// Use GitHub Actions annotation format for better visibility in CI
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
for (const violation of violations) {
if (isCI) {
// GitHub Actions warning annotation format
console.log(
`::warning file=${violation.file},line=${violation.line}::console.log found: ${violation.content}`,
);
} else {
console.log(` ${violation.file}:${violation.line}`);
console.log(` ${violation.content}\n`);
}
}
console.log(`\n💡 Total violations: ${violations.length}`);
console.log(`\n📝 To whitelist files, add them to ${WHITELIST_PATH} in the following format:`);
console.log(`{
"files": ["path/to/file.ts"],
"patterns": ["scripts/**/*.mts", "**/*.test.ts"]
}\n`);
// Exit with 0 to not block CI, but warnings will still be visible
process.exit(0);
} catch (error: unknown) {
if (error instanceof Error && 'status' in error && error.status !== 0) {
console.error('❌ Error running git grep:', error.message);
process.exit(1);
}
throw error;
}
};
checkConsoleLogs();