pury
Version:
🛡️ AI-powered security scanner with advanced threat detection, dual reporting system (detailed & summary), and comprehensive code analysis
110 lines • 3.61 kB
JavaScript
import { Severity, FindingType } from '../types/index.js';
import { fileExists } from './file-utils.js';
export class ValidationError extends Error {
field;
constructor(message, field) {
super(message);
this.field = field;
this.name = 'ValidationError';
}
}
export async function validateScanOptions(options) {
if (!options.path) {
throw new ValidationError('Scan path is required', 'path');
}
if (!(await fileExists(options.path))) {
throw new ValidationError(`Scan path does not exist: ${options.path}`, 'path');
}
if (options.maxFileSize && options.maxFileSize < 0) {
throw new ValidationError('maxFileSize must be positive', 'maxFileSize');
}
if (options.exclude && !Array.isArray(options.exclude)) {
throw new ValidationError('exclude must be an array of strings', 'exclude');
}
if (options.include && !Array.isArray(options.include)) {
throw new ValidationError('include must be an array of strings', 'include');
}
}
export function validateConfig(config) {
const defaultConfig = {
scanner: {
exclude: [
'node_modules/**',
'dist/**',
'build/**',
'.git/**',
'*.min.js',
'*.map',
'coverage/**'
],
include: ['**/*'],
maxFileSize: 1024 * 1024, // 1MB
followSymlinks: false
},
analyzers: {
malware: { enabled: true, sensitivity: 'medium' },
secrets: { enabled: true, sensitivity: 'medium' },
vulnerabilities: { enabled: true, sensitivity: 'medium' },
codeQuality: { enabled: false, sensitivity: 'medium' }
},
ai: {
provider: 'gemini',
gemini: {
model: 'gemini-2.5-flash',
temperature: 0.1,
maxTokens: 2048
}
},
output: {
format: 'console',
verbose: false
}
};
return mergeDeep(defaultConfig, config);
}
export function validateSeverity(severity) {
if (!Object.values(Severity).includes(severity)) {
throw new ValidationError(`Invalid severity: ${severity}. Must be one of: ${Object.values(Severity).join(', ')}`);
}
return severity;
}
export function validateFindingType(type) {
if (!Object.values(FindingType).includes(type)) {
throw new ValidationError(`Invalid finding type: ${type}. Must be one of: ${Object.values(FindingType).join(', ')}`);
}
return type;
}
export function validateApiKey(apiKey) {
if (!apiKey || apiKey.trim().length === 0) {
throw new ValidationError('API key is required for AI analysis');
}
if (apiKey.length < 10) {
throw new ValidationError('API key appears to be invalid (too short)');
}
}
export function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
export function validateUrl(url) {
try {
new URL(url);
return true;
}
catch {
return false;
}
}
function mergeDeep(target, source) {
const result = { ...target };
for (const key in source) {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
result[key] = mergeDeep(result[key] || {}, source[key]);
}
else if (source[key] !== undefined) {
result[key] = source[key];
}
}
return result;
}
//# sourceMappingURL=validation.js.map