UNPKG

@mkpro118/semantic-change-detector

Version:

Semantic change detection for TypeScript and TSX code with GitHub Actions integration

292 lines 9.47 kB
/** * Maps change kinds to their logical groups for organization and bulk control. */ export const CHANGE_KIND_GROUPS = { 'core-structural': [ 'functionAdded', 'functionRemoved', 'functionSignatureChanged', 'classStructureChanged', 'exportAdded', 'exportRemoved', 'exportSignatureChanged', 'interfaceModified', ], 'data-flow': [ 'variableDeclarationChanged', 'variableAssignmentChanged', 'destructuringAdded', 'destructuringRemoved', 'arrayMutation', 'objectMutation', ], 'control-flow': [ 'conditionalAdded', 'conditionalModified', 'conditionalRemoved', 'loopAdded', 'loopModified', 'loopRemoved', 'logicalOperatorChanged', 'comparisonOperatorChanged', 'ternaryAdded', 'ternaryRemoved', ], 'react-hooks': [ 'hookAdded', 'hookRemoved', 'hookDependencyChanged', ], 'jsx-rendering': [ 'jsxElementAdded', 'jsxElementRemoved', 'jsxPropsChanged', 'componentReferenceChanged', 'componentStructureChanged', ], 'jsx-logic': [ 'jsxLogicAdded', 'eventHandlerChanged', ], 'imports-exports': [ 'importAdded', 'importRemoved', 'importStructureChanged', 'sideEffectImportAdded', ], 'async-patterns': [ 'asyncAwaitAdded', 'asyncAwaitRemoved', 'promiseAdded', 'promiseRemoved', 'effectAdded', 'effectRemoved', ], 'type-system': [ 'typeDefinitionChanged', ], 'side-effects': [ 'functionCallAdded', 'functionCallChanged', 'functionCallModified', 'functionCallRemoved', ], 'complexity': [ 'functionComplexityChanged', 'spreadOperatorAdded', 'spreadOperatorRemoved', ], 'error-handling': [ 'throwAdded', 'throwRemoved', 'tryCatchAdded', 'tryCatchModified', ], }; /** * Default severity assignments for each change kind. * These represent the baseline production-ready severity levels. */ export const DEFAULT_CHANGE_SEVERITIES = { // CRITICAL CHANGES - Always require tests 'functionSignatureChanged': 'high', 'exportRemoved': 'high', 'exportSignatureChanged': 'high', 'hookDependencyChanged': 'high', 'functionCallAdded': 'high', 'classStructureChanged': 'high', 'interfaceModified': 'high', 'conditionalAdded': 'high', 'conditionalModified': 'high', 'loopAdded': 'high', 'loopModified': 'high', 'functionComplexityChanged': 'high', // SIGNIFICANT CHANGES - Usually require tests 'functionAdded': 'medium', 'exportAdded': 'medium', 'functionRemoved': 'medium', 'hookAdded': 'medium', 'hookRemoved': 'medium', 'variableAssignmentChanged': 'medium', 'arrayMutation': 'medium', 'objectMutation': 'medium', 'conditionalRemoved': 'medium', 'loopRemoved': 'medium', 'functionCallChanged': 'medium', 'functionCallModified': 'medium', 'functionCallRemoved': 'medium', 'asyncAwaitAdded': 'medium', 'asyncAwaitRemoved': 'medium', 'promiseAdded': 'medium', 'promiseRemoved': 'medium', 'throwAdded': 'medium', 'throwRemoved': 'medium', 'tryCatchAdded': 'medium', 'tryCatchModified': 'medium', 'logicalOperatorChanged': 'medium', 'comparisonOperatorChanged': 'medium', 'typeDefinitionChanged': 'medium', 'sideEffectImportAdded': 'medium', 'stateManagementChanged': 'medium', // MINOR CHANGES - Often cosmetic but context-dependent 'importAdded': 'low', 'importRemoved': 'low', 'importStructureChanged': 'low', 'variableDeclarationChanged': 'low', 'destructuringAdded': 'low', 'destructuringRemoved': 'low', 'ternaryAdded': 'low', 'ternaryRemoved': 'low', 'spreadOperatorAdded': 'low', 'spreadOperatorRemoved': 'low', 'effectAdded': 'low', 'effectRemoved': 'low', // JSX CHANGES - Context dependent, often low unless behavioral 'jsxElementAdded': 'low', 'jsxElementRemoved': 'low', 'jsxPropsChanged': 'low', 'jsxLogicAdded': 'medium', // Conditional rendering is more significant 'componentReferenceChanged': 'medium', 'componentStructureChanged': 'low', 'eventHandlerChanged': 'low', // Often just prop drilling }; /** * Default enhanced configuration with production-ready settings. */ export const DEFAULT_ENHANCED_CONFIG = { // Legacy compatibility include: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], exclude: ['node_modules/**', '**/*.test.*', '**/*.spec.*', '**/*.d.ts', 'dist/**', 'build/**'], sideEffectCallees: [ 'console.*', 'fetch', '*.api.*', '*.service.*', 'track*', 'log*', 'analytics.*', 'gtag', 'dataLayer.*', ], sideEffectModules: [], testGlobs: ['**/*.test.*', '**/*.spec.*'], bypassLabels: ['skip-tests', 'docs-only', 'trivial'], timeoutMs: 120000, maxMemoryMB: 512, // Enhanced configuration changeKindGroups: { enabled: [ 'core-structural', 'data-flow', 'control-flow', 'react-hooks', 'jsx-rendering', 'imports-exports', 'async-patterns', 'type-system', 'side-effects', 'complexity', 'error-handling', ], disabled: [ 'jsx-logic', // Disabled by default as requested - JSX logic often not semantically important ], }, severityOverrides: { // Example overrides for teams that want stricter/looser requirements // 'importAdded': 'medium', // Some teams want to flag all new dependencies // 'jsxElementAdded': 'high', // Some teams want to test all UI changes }, disabledChangeKinds: [ // Individual change kinds that are typically noise // Teams can add specific changes they don't care about ], jsxConfig: { enabled: true, ignoreLogicChanges: true, // Don't flag "isLoading ? 'Loading' : 'Load More'" type changes treatAsLowSeverity: false, // Keep normal severity assessment for structural JSX changes eventHandlerComplexityThreshold: 3, // Only flag complex event handlers }, performance: { skipDisabledAnalyzers: true, // Skip analysis for disabled groups for better performance enableEarlyExit: true, // Enable early exit optimizations }, testRequirements: { alwaysRequireTests: [ 'functionSignatureChanged', 'exportRemoved', 'hookDependencyChanged', 'classStructureChanged', ], neverRequireTests: [ // JSX logic changes as requested 'jsxLogicAdded', 'eventHandlerChanged', ], minimumSeverityForTests: null, // Use individual change kind settings }, }; /** * Resolves the effective severity for a change kind, considering config overrides. */ export function getEffectiveSeverity(changeKind, config) { return config.severityOverrides[changeKind] ?? DEFAULT_CHANGE_SEVERITIES[changeKind]; } /** * Checks if a change kind is enabled based on group and individual settings. */ export function isChangeKindEnabled(changeKind, config) { // Check if explicitly disabled if (config.disabledChangeKinds.includes(changeKind)) { return false; } // Find which group this change kind belongs to const group = Object.entries(CHANGE_KIND_GROUPS).find(([, kinds]) => kinds.includes(changeKind))?.[0]; if (!group) { // If not in any group, default to enabled return true; } // Check if group is explicitly disabled if (config.changeKindGroups.disabled.includes(group)) { return false; } // Check if group is in enabled list (if enabled list is not empty, use it as allowlist) if (config.changeKindGroups.enabled.length > 0) { return config.changeKindGroups.enabled.includes(group); } // Default to enabled return true; } /** * Determines if tests should be required for a specific change based on enhanced config. */ export function shouldRequireTestsForChange(changeKind, severity, config) { // Check explicit always/never lists first if (config.testRequirements.alwaysRequireTests.includes(changeKind)) { return true; } if (config.testRequirements.neverRequireTests.includes(changeKind)) { return false; } // Check minimum severity requirement if (config.testRequirements.minimumSeverityForTests) { const severityLevels = { low: 0, medium: 1, high: 2 }; return severityLevels[severity] >= severityLevels[config.testRequirements.minimumSeverityForTests]; } // Default to requiring tests for high severity changes return severity === 'high'; } /** * Gets all change kinds in a specific group. */ export function getChangeKindsInGroup(group) { return CHANGE_KIND_GROUPS[group] || []; } /** * Gets the group that a change kind belongs to. */ export function getGroupForChangeKind(changeKind) { const entry = Object.entries(CHANGE_KIND_GROUPS).find(([, kinds]) => kinds.includes(changeKind)); return entry ? entry[0] : null; } //# sourceMappingURL=enhanced-config.js.map