import type { ScrapingConfig, CodeAnalysisOptions, DependencyAnalysisOptions } from '../types/index.js';
export class Validators {
/**
* Validate URL format
*/
static isValidUrl(url: string): boolean {
try {
new URL(url);
return true;
} catch {
return false;
}
}
/**
* Validate file path
*/
static isValidFilePath(path: string): boolean {
// Basic validation - check for invalid characters
const invalidChars = /[<>:"|?*\x00-\x1f]/;
return !invalidChars.test(path);
}
/**
* Validate scraping config
*/
static validateScrapingConfig(config: ScrapingConfig): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (!config.url) {
errors.push('URL is required');
} else if (!this.isValidUrl(config.url)) {
errors.push('Invalid URL format');
}
if (config.timeout !== undefined && config.timeout < 0) {
errors.push('Timeout must be a positive number');
}
if (config.maxRedirects !== undefined && config.maxRedirects < 0) {
errors.push('Max redirects must be a positive number');
}
return {
valid: errors.length === 0,
errors,
};
}
/**
* Validate code analysis options
*/
static validateCodeAnalysisOptions(options: CodeAnalysisOptions): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (options.maxComplexity !== undefined && options.maxComplexity < 0) {
errors.push('Max complexity must be a positive number');
}
if (options.minLinesForDuplication !== undefined && options.minLinesForDuplication < 0) {
errors.push('Min lines for duplication must be a positive number');
}
return {
valid: errors.length === 0,
errors,
};
}
/**
* Validate dependency analysis options
*/
static validateDependencyAnalysisOptions(options: DependencyAnalysisOptions): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (options.depth !== undefined && options.depth < 0) {
errors.push('Depth must be a positive number');
}
return {
valid: errors.length === 0,
errors,
};
}
/**
* Validate file pattern (glob)
*/
static isValidFilePattern(pattern: string): boolean {
// Basic validation - check if it's a valid glob pattern
if (!pattern || pattern.trim().length === 0) {
return false;
}
return true;
}
/**
* Sanitize file path to prevent directory traversal
*/
static sanitizePath(path: string): string {
// Remove any directory traversal attempts
return path.replace(/\.\./g, '').replace(/\/\//g, '/');
}
/**
* Validate selector (CSS/XPath)
*/
static isValidSelector(selector: string): boolean {
if (!selector || selector.trim().length === 0) {
return false;
}
// Basic validation - check for common selector patterns
return /^[a-zA-Z0-9\s#.\[\]:\-_>+~=,"'()]+$/.test(selector);
}
}