@sun-asterisk/impact-analyzer 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +116 -0
- package/.github/prompts/README.md +91 -0
- package/.github/prompts/task-001-refactor.prompt.md +241 -0
- package/.specify/bugs/bug-001-database-detector.md +222 -0
- package/.specify/plans/architecture.md +186 -0
- package/.specify/specs/features/api-impact-detection.md +317 -0
- package/.specify/specs/features/component-impact-detection.md +263 -0
- package/.specify/specs/features/database-impact-detection.md +247 -0
- package/.specify/tasks/task-001-refactor-api-detector.md +284 -0
- package/.specify/tasks/task-002-database-detector.md +593 -0
- package/.specify/tasks/task-003-component-detector.md +0 -0
- package/.specify/tasks/task-004-report.md +484 -0
- package/README.md +13 -19
- package/core/detectors/database-detector.js +702 -0
- package/{modules → core}/detectors/endpoint-detector.js +11 -8
- package/{modules → core}/report-generator.js +102 -20
- package/core/utils/logger.js +12 -0
- package/index.js +6 -5
- package/package.json +1 -1
- package/modules/detectors/database-detector.js +0 -182
- /package/{modules → core}/change-detector.js +0 -0
- /package/{modules → core}/impact-analyzer.js +0 -0
- /package/{modules → core}/utils/ast-parser.js +0 -0
- /package/{modules → core}/utils/dependency-graph.js +0 -0
- /package/{modules → core}/utils/file-utils.js +0 -0
- /package/{modules → core}/utils/git-utils.js +0 -0
- /package/{modules → core}/utils/method-call-graph.js +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Impact Analyzer - AI Code Generation Guide
|
|
2
|
+
|
|
3
|
+
## What This Tool Does
|
|
4
|
+
|
|
5
|
+
Analyzes code changes in TypeScript/JavaScript projects to identify impacts on APIs, databases, and logic dependencies. Generates severity-based reports (LOW/MEDIUM/HIGH/CRITICAL).
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
core/
|
|
11
|
+
├── change-detector.js # Git diff parsing + AST symbol extraction
|
|
12
|
+
├── impact-analyzer.js # Main orchestrator
|
|
13
|
+
├── report-generator.js # Console/markdown/JSON output
|
|
14
|
+
├── detectors/
|
|
15
|
+
│ ├── endpoint-detector.js # Find affected API endpoints
|
|
16
|
+
│ └── database-detector.js # Detect DB table/field changes
|
|
17
|
+
└── utils/
|
|
18
|
+
├── ast-parser.js # Parse TS/JS with ts-morph
|
|
19
|
+
├── method-call-graph.js # Build caller/callee maps
|
|
20
|
+
├── dependency-graph.js # Track dependencies
|
|
21
|
+
├── file-utils.js # File operations
|
|
22
|
+
└── git-utils.js # Git operations
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Core Logic Flow
|
|
26
|
+
|
|
27
|
+
1. **Detect Changes** → Parse git diff, extract changed symbols
|
|
28
|
+
2. **Build Call Graph** → Map methods to callers/callees
|
|
29
|
+
3. **Find Impacts** → Traverse graph upward to find affected endpoints and DB ops
|
|
30
|
+
4. **Calculate Score** → Score = (Endpoints×10) + (DB×5) + (Callers×3) + (Indirect×1)
|
|
31
|
+
5. **Generate Report** → Output with severity level
|
|
32
|
+
|
|
33
|
+
## Code Rules for AI Generation
|
|
34
|
+
|
|
35
|
+
### Essential Patterns
|
|
36
|
+
|
|
37
|
+
**Import/Export**
|
|
38
|
+
```javascript
|
|
39
|
+
import { Project } from 'ts-morph';
|
|
40
|
+
export function analyzeImpact(files) { }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Async Operations**
|
|
44
|
+
```javascript
|
|
45
|
+
async function detectChanges() {
|
|
46
|
+
const files = await getChangedFiles();
|
|
47
|
+
return await Promise.all(files.map(analyzeFile));
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Error Handling**
|
|
52
|
+
```javascript
|
|
53
|
+
try {
|
|
54
|
+
await operation();
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error('Context:', { file, method }, error);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Call Graph Traversal**
|
|
61
|
+
```javascript
|
|
62
|
+
function findAffectedEndpoints(method, callGraph) {
|
|
63
|
+
const callers = traverseUpward(method, callGraph);
|
|
64
|
+
return callers.filter(hasHttpDecorator);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Code Quality Rules
|
|
69
|
+
|
|
70
|
+
- **Rule C005** - One function does one thing
|
|
71
|
+
- **Rule C006** - Function names use verb-noun (e.g., `detectEndpoints`, `buildCallGraph`)
|
|
72
|
+
- **Rule C007** - No comments that restate code
|
|
73
|
+
- **Rule C015** - Use domain language (e.g., `endpoint`, `impact`, `severity`)
|
|
74
|
+
- **Rule C031** - Separate validation logic
|
|
75
|
+
- **Rule C033** - Separate data access from business logic
|
|
76
|
+
|
|
77
|
+
### Naming Conventions
|
|
78
|
+
|
|
79
|
+
- Functions: `camelCase` (e.g., `analyzeImpact`)
|
|
80
|
+
- Classes: `PascalCase` (e.g., `ImpactAnalyzer`)
|
|
81
|
+
- Constants: `UPPER_SNAKE_CASE` (e.g., `SEVERITY_LEVELS`)
|
|
82
|
+
- Files: `kebab-case.js` (e.g., `call-graph.js`)
|
|
83
|
+
|
|
84
|
+
### Required Patterns
|
|
85
|
+
|
|
86
|
+
**Always use:**
|
|
87
|
+
- ES Modules (`import/export`)
|
|
88
|
+
- `async/await` (never callbacks)
|
|
89
|
+
- `ts-morph` for AST parsing
|
|
90
|
+
- Descriptive variable names from domain
|
|
91
|
+
|
|
92
|
+
**Never do:**
|
|
93
|
+
- Use `new` in business logic (use dependency injection)
|
|
94
|
+
- Log errors without context
|
|
95
|
+
- Mix validation with business logic
|
|
96
|
+
- Return raw strings from API handlers
|
|
97
|
+
|
|
98
|
+
## CLI Usage
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Basic
|
|
102
|
+
npx @sun-asterisk/impact-analyzer --input=src --base=origin/main
|
|
103
|
+
|
|
104
|
+
# With reports
|
|
105
|
+
npx @sun-asterisk/impact-analyzer --input=src --base=origin/main --output=report.md --json=report.json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Severity Calculation
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
score = (endpoints × 10) + (dbTables × 5) + (directCallers × 3) + (indirectCallers × 1)
|
|
112
|
+
if (highRiskLogic) score *= 1.5
|
|
113
|
+
if (dbMigration) score += 20
|
|
114
|
+
|
|
115
|
+
severity = score < 21 ? 'LOW' : score < 51 ? 'MEDIUM' : score < 101 ? 'HIGH' : 'CRITICAL'
|
|
116
|
+
```
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Prompts for GitHub Copilot CLI
|
|
2
|
+
|
|
3
|
+
## Do You Need Prompts?
|
|
4
|
+
|
|
5
|
+
**Short Answer: NO** - For most tasks, you can directly reference the task file:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Direct approach (RECOMMENDED)
|
|
9
|
+
@task-001-refactor-api-detector.md read this task and implement it
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Why Direct Reference Works:**
|
|
13
|
+
- Task files are already structured for AI (clear goals, code examples, acceptance criteria)
|
|
14
|
+
- GitHub Copilot CLI can read and understand markdown task files directly
|
|
15
|
+
- Less overhead, fewer files to maintain
|
|
16
|
+
- Task files contain all necessary context
|
|
17
|
+
|
|
18
|
+
## When to Use Prompts?
|
|
19
|
+
|
|
20
|
+
Use prompts ONLY when you need to:
|
|
21
|
+
|
|
22
|
+
1. **Reuse across multiple tasks** - Common patterns used in many places
|
|
23
|
+
2. **Add constraints not in task** - Team-specific rules, environment limitations
|
|
24
|
+
3. **Provide context not in codebase** - External dependencies, business rules
|
|
25
|
+
4. **Break down complex tasks** - Multi-step workflows that need orchestration
|
|
26
|
+
|
|
27
|
+
## Current Prompts
|
|
28
|
+
|
|
29
|
+
### task-001-refactor.prompt.md
|
|
30
|
+
|
|
31
|
+
**Purpose:** Provides step-by-step implementation guide for Task 001 refactoring
|
|
32
|
+
|
|
33
|
+
**Why it exists:**
|
|
34
|
+
- Breaks down large refactor into smaller, sequential steps
|
|
35
|
+
- Adds verification steps after each phase
|
|
36
|
+
- Includes rollback instructions for safety
|
|
37
|
+
- Provides consistent implementation pattern for future refactors
|
|
38
|
+
|
|
39
|
+
**When to use:**
|
|
40
|
+
```bash
|
|
41
|
+
# Step-by-step guided refactor
|
|
42
|
+
@task-001-refactor.prompt.md implement this refactor step by step
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**When NOT to use:**
|
|
46
|
+
```bash
|
|
47
|
+
# Simple, direct implementation
|
|
48
|
+
@task-001-refactor-api-detector.md implement this task
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Prompt Guidelines
|
|
52
|
+
|
|
53
|
+
If you create a new prompt, follow these rules:
|
|
54
|
+
|
|
55
|
+
**Keep it simple:**
|
|
56
|
+
- One prompt = One specific purpose
|
|
57
|
+
- Max 100 lines
|
|
58
|
+
- Clear structure with sections
|
|
59
|
+
|
|
60
|
+
**Make it actionable:**
|
|
61
|
+
- Use concrete code examples
|
|
62
|
+
- Provide expected outcomes
|
|
63
|
+
- Include verification commands
|
|
64
|
+
|
|
65
|
+
**Avoid duplication:**
|
|
66
|
+
- Don't repeat what's in task files
|
|
67
|
+
- Don't repeat what's in copilot-instructions.md
|
|
68
|
+
- Reference existing docs instead
|
|
69
|
+
|
|
70
|
+
## Prompt Template
|
|
71
|
+
|
|
72
|
+
```markdown
|
|
73
|
+
# Prompt: [Name]
|
|
74
|
+
|
|
75
|
+
## Purpose
|
|
76
|
+
[Why this prompt exists]
|
|
77
|
+
|
|
78
|
+
## Context
|
|
79
|
+
[What AI needs to know]
|
|
80
|
+
|
|
81
|
+
## Implementation Steps
|
|
82
|
+
1. [Step 1]
|
|
83
|
+
2. [Step 2]
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
## Verification
|
|
87
|
+
[How to verify it worked]
|
|
88
|
+
|
|
89
|
+
## References
|
|
90
|
+
- [Link to related docs]
|
|
91
|
+
```
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Prompt: Task 001 Refactor Implementation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Step-by-step implementation guide for refactoring API detector from modules/ to core/ with performance optimization.
|
|
6
|
+
|
|
7
|
+
## Why This Prompt Exists
|
|
8
|
+
|
|
9
|
+
While the task file contains all requirements, this prompt:
|
|
10
|
+
1. **Breaks down into safe phases** - Prevents breaking changes
|
|
11
|
+
2. **Adds verification steps** - Ensures each phase works before moving on
|
|
12
|
+
3. **Provides rollback strategy** - Safety net if something goes wrong
|
|
13
|
+
4. **Sequential execution** - Avoids doing everything at once
|
|
14
|
+
|
|
15
|
+
## Phase 1: Audit Current Structure
|
|
16
|
+
|
|
17
|
+
**Goal:** Understand what exists before changing it
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Find all files in modules/ or related to API detection
|
|
21
|
+
find . -name "*api*" -o -name "*endpoint*" -o -name "*detector*" | grep -v node_modules
|
|
22
|
+
|
|
23
|
+
# Check imports
|
|
24
|
+
grep -r "from.*modules" --include="*.js" | head -20
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Document:**
|
|
28
|
+
- Which files exist?
|
|
29
|
+
- Which files import from modules/?
|
|
30
|
+
- Are there tests?
|
|
31
|
+
|
|
32
|
+
## Phase 2: Create New Structure (No Breaking Changes)
|
|
33
|
+
|
|
34
|
+
**Goal:** Create new files in core/ without touching old code
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
// Step 1: Create core/utils/logger.js
|
|
38
|
+
export function createLogger(verbose = false) {
|
|
39
|
+
return {
|
|
40
|
+
info: (msg) => console.log(msg),
|
|
41
|
+
debug: (msg) => verbose && console.log(`[DEBUG] ${msg}`),
|
|
42
|
+
verbose: (component, msg) => verbose && console.log(`[${component}] ${msg}`)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Step 2: Create core/detectors/endpoint-detector.js
|
|
47
|
+
// Copy existing logic, add logger, optimize
|
|
48
|
+
import { createLogger } from '../utils/logger.js';
|
|
49
|
+
|
|
50
|
+
export function findAffectedEndpoints(changedMethods, callGraph, options = {}) {
|
|
51
|
+
const logger = createLogger(options.verbose);
|
|
52
|
+
const endpoints = [];
|
|
53
|
+
|
|
54
|
+
logger.info('🔍 Analyzing API impacts...');
|
|
55
|
+
logger.verbose('EndpointDetector', `Processing ${changedMethods.length} methods`);
|
|
56
|
+
|
|
57
|
+
for (const method of changedMethods) {
|
|
58
|
+
const found = traverseToEndpoint(method, callGraph, logger);
|
|
59
|
+
endpoints.push(...found);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
logger.info(`📡 Found ${endpoints.length} affected endpoints`);
|
|
63
|
+
return endpoints;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function traverseToEndpoint(method, callGraph, logger, visited = new Set(), depth = 0) {
|
|
67
|
+
// Max depth check
|
|
68
|
+
if (depth > 10) {
|
|
69
|
+
logger.verbose('EndpointDetector', `Max depth reached for ${method.name}`);
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Cycle detection with Set (O(1) lookup)
|
|
74
|
+
if (visited.has(method.name)) return [];
|
|
75
|
+
visited.add(method.name);
|
|
76
|
+
|
|
77
|
+
logger.verbose('EndpointDetector', `Traversing ${method.name} (depth: ${depth})`);
|
|
78
|
+
|
|
79
|
+
// Check if endpoint
|
|
80
|
+
if (isHttpEndpoint(method)) {
|
|
81
|
+
const info = extractEndpointInfo(method);
|
|
82
|
+
logger.verbose('EndpointDetector', `Found endpoint: ${info.method} ${info.path}`);
|
|
83
|
+
return [info];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Traverse callers
|
|
87
|
+
const endpoints = [];
|
|
88
|
+
const callers = callGraph.getCallers(method.name) || [];
|
|
89
|
+
|
|
90
|
+
for (const caller of callers) {
|
|
91
|
+
const found = traverseToEndpoint(caller, callGraph, logger, visited, depth + 1);
|
|
92
|
+
endpoints.push(...found);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return endpoints;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function isHttpEndpoint(method) {
|
|
99
|
+
if (!method.decorators) return false;
|
|
100
|
+
const httpMethods = ['Get', 'Post', 'Put', 'Delete', 'Patch'];
|
|
101
|
+
return method.decorators.some(d => httpMethods.includes(d.name));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function extractEndpointInfo(method) {
|
|
105
|
+
const httpDecorator = method.decorators.find(d =>
|
|
106
|
+
['Get', 'Post', 'Put', 'Delete', 'Patch'].includes(d.name)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const controllerDecorator = method.class?.decorators?.find(d =>
|
|
110
|
+
d.name === 'Controller'
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const basePath = controllerDecorator?.arguments?.[0] || '';
|
|
114
|
+
const subPath = httpDecorator?.arguments?.[0] || '';
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
type: 'endpoint',
|
|
118
|
+
method: httpDecorator.name.toUpperCase(),
|
|
119
|
+
path: joinPath(basePath, subPath),
|
|
120
|
+
controller: `${method.class.name}.${method.name}`,
|
|
121
|
+
file: method.file
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function joinPath(base, sub) {
|
|
126
|
+
const cleanBase = base.replace(/\/$/, '');
|
|
127
|
+
const cleanSub = sub.replace(/^\//, '');
|
|
128
|
+
return cleanSub ? `/${cleanBase}/${cleanSub}`.replace(/\/+/g, '/') : `/${cleanBase}`;
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Verify:**
|
|
133
|
+
```bash
|
|
134
|
+
# Check files created
|
|
135
|
+
ls -la core/detectors/
|
|
136
|
+
ls -la core/utils/logger.js
|
|
137
|
+
|
|
138
|
+
# Verify no syntax errors
|
|
139
|
+
node -c core/detectors/endpoint-detector.js
|
|
140
|
+
node -c core/utils/logger.js
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Phase 3: Update Imports (One File at a Time)
|
|
144
|
+
|
|
145
|
+
**Goal:** Switch to new structure gradually
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// Find main entry point
|
|
149
|
+
// Example: core/impact-analyzer.js
|
|
150
|
+
|
|
151
|
+
// Old import
|
|
152
|
+
// import { findEndpoints } from '../modules/api-detector.js';
|
|
153
|
+
|
|
154
|
+
// New import
|
|
155
|
+
import { findAffectedEndpoints } from './detectors/endpoint-detector.js';
|
|
156
|
+
|
|
157
|
+
// Update function call
|
|
158
|
+
const endpoints = findAffectedEndpoints(changedMethods, callGraph, { verbose });
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Verify after each change:**
|
|
162
|
+
```bash
|
|
163
|
+
# Test the tool still works
|
|
164
|
+
node cli.js --input=src --base=origin/main --verbose
|
|
165
|
+
|
|
166
|
+
# Check output is correct
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Phase 4: Remove Unused Code
|
|
170
|
+
|
|
171
|
+
**Goal:** Clean up old files only after new code is verified
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# First, verify nothing imports from modules/
|
|
175
|
+
grep -r "from.*modules" --include="*.js" .
|
|
176
|
+
|
|
177
|
+
# If clear, remove old files
|
|
178
|
+
rm -rf modules/ # Or move to backup first
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Safety:** Keep backup before deleting
|
|
182
|
+
```bash
|
|
183
|
+
mkdir -p .backup
|
|
184
|
+
cp -r modules/ .backup/modules-$(date +%Y%m%d)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Phase 5: Performance Verification
|
|
188
|
+
|
|
189
|
+
**Goal:** Ensure optimizations worked
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Add timing to verbose output
|
|
193
|
+
# In endpoint-detector.js:
|
|
194
|
+
const startTime = Date.now();
|
|
195
|
+
// ... detection logic
|
|
196
|
+
const duration = Date.now() - startTime;
|
|
197
|
+
logger.verbose('EndpointDetector', `Completed in ${duration}ms`);
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Test with verbose mode:**
|
|
201
|
+
```bash
|
|
202
|
+
node cli.js --input=src --base=origin/main --verbose
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Check:**
|
|
206
|
+
- Is depth limit working? (should see "Max depth reached" if hit)
|
|
207
|
+
- Are visited nodes tracked? (no infinite loops)
|
|
208
|
+
- Is timing shown? (< 50ms per method is good)
|
|
209
|
+
|
|
210
|
+
## Rollback Strategy
|
|
211
|
+
|
|
212
|
+
If something breaks:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Restore from backup
|
|
216
|
+
cp -r .backup/modules-YYYYMMDD modules/
|
|
217
|
+
|
|
218
|
+
# Revert imports in git
|
|
219
|
+
git checkout -- core/impact-analyzer.js
|
|
220
|
+
|
|
221
|
+
# Or revert entire change
|
|
222
|
+
git reset --hard HEAD
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Acceptance Checklist
|
|
226
|
+
|
|
227
|
+
- [ ] Phase 1 complete: Current structure documented
|
|
228
|
+
- [ ] Phase 2 complete: New files created in core/
|
|
229
|
+
- [ ] Phase 3 complete: Imports updated, tool still works
|
|
230
|
+
- [ ] Phase 4 complete: Old code removed
|
|
231
|
+
- [ ] Phase 5 complete: Performance verified
|
|
232
|
+
- [ ] Verbose mode works (`--verbose` flag)
|
|
233
|
+
- [ ] Normal mode works (clean output)
|
|
234
|
+
- [ ] No errors in console
|
|
235
|
+
- [ ] Tests pass (if any)
|
|
236
|
+
|
|
237
|
+
## References
|
|
238
|
+
|
|
239
|
+
- Task File: `.specify/tasks/task-001-refactor-api-detector.md`
|
|
240
|
+
- API Spec: `.specify/specs/features/api-impact-detection.md`
|
|
241
|
+
- Code Rules: `.github/copilot-instructions.md`
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# BUG-001: Database Detector Missing SELECT Operations
|
|
2
|
+
|
|
3
|
+
**Bug ID:** BUG-001
|
|
4
|
+
**Status:** ✅ RESOLVED
|
|
5
|
+
**Priority:** HIGH
|
|
6
|
+
**Severity:** Medium
|
|
7
|
+
**Created:** 2025-12-25
|
|
8
|
+
**Updated:** 2025-12-25
|
|
9
|
+
**Resolved:** 2025-12-25
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Problem Statement
|
|
14
|
+
|
|
15
|
+
Database detector only catches INSERT/UPDATE/DELETE operations but misses SELECT queries, resulting in incomplete database impact reports.
|
|
16
|
+
|
|
17
|
+
### Observed Behavior
|
|
18
|
+
|
|
19
|
+
When code changes include SELECT operations, they are **not detected**:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// ❌ Not detected:
|
|
23
|
+
await repository.find({ where: { status: 'active' } });
|
|
24
|
+
await repository.findOne({ where: { id } });
|
|
25
|
+
await queryBuilder.select(['name', 'email']).getMany();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Expected Behavior
|
|
29
|
+
|
|
30
|
+
All database operations including SELECT should be detected and reported in the impact analysis.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Root Cause
|
|
35
|
+
|
|
36
|
+
**File:** `core/detectors/database-detector.js` (line ~295)
|
|
37
|
+
|
|
38
|
+
The `typeOrmOps` mapping object only includes write operations (INSERT/UPDATE/DELETE) and does not include read operations (SELECT):
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
const typeOrmOps = {
|
|
42
|
+
'insert': 'INSERT',
|
|
43
|
+
'save': 'INSERT/UPDATE',
|
|
44
|
+
'create': 'INSERT',
|
|
45
|
+
'update': 'UPDATE',
|
|
46
|
+
'merge': 'UPDATE',
|
|
47
|
+
'delete': 'DELETE',
|
|
48
|
+
'remove': 'DELETE',
|
|
49
|
+
'softDelete': 'SOFT_DELETE',
|
|
50
|
+
// ❌ Missing: find, findOne, select, query, getMany, getOne
|
|
51
|
+
};
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The `analyzeChangedCodeForDatabaseOps()` method iterates through this map to detect database operations. Since SELECT operations are not in the map, they are skipped.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Fix Strategy
|
|
59
|
+
|
|
60
|
+
### Approach
|
|
61
|
+
|
|
62
|
+
Add SELECT operation methods to the `typeOrmOps` mapping. This is a **low-risk, non-breaking change** that extends existing detection without modifying the core logic.
|
|
63
|
+
|
|
64
|
+
### Implementation
|
|
65
|
+
|
|
66
|
+
**Step 1:** Locate the `typeOrmOps` definition in `core/detectors/database-detector.js` (~line 295)
|
|
67
|
+
|
|
68
|
+
**Step 2:** Add SELECT operations:
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
const typeOrmOps = {
|
|
72
|
+
// Existing operations (keep as-is)
|
|
73
|
+
'insert': 'INSERT',
|
|
74
|
+
'save': 'INSERT/UPDATE',
|
|
75
|
+
'create': 'INSERT',
|
|
76
|
+
'update': 'UPDATE',
|
|
77
|
+
'merge': 'UPDATE',
|
|
78
|
+
'delete': 'DELETE',
|
|
79
|
+
'remove': 'DELETE',
|
|
80
|
+
'softDelete': 'SOFT_DELETE',
|
|
81
|
+
|
|
82
|
+
// Add SELECT operations
|
|
83
|
+
'find': 'SELECT',
|
|
84
|
+
'findOne': 'SELECT',
|
|
85
|
+
'findBy': 'SELECT',
|
|
86
|
+
'findOneBy': 'SELECT',
|
|
87
|
+
'findAndCount': 'SELECT',
|
|
88
|
+
'select': 'SELECT',
|
|
89
|
+
'query': 'SELECT',
|
|
90
|
+
'getMany': 'SELECT',
|
|
91
|
+
'getOne': 'SELECT',
|
|
92
|
+
};
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Step 3:** No other changes needed. The existing `analyzeChangedCodeForDatabaseOps()` method will automatically handle SELECT operations.
|
|
96
|
+
|
|
97
|
+
### Why This Works
|
|
98
|
+
|
|
99
|
+
The method already:
|
|
100
|
+
1. Iterates through `typeOrmOps` entries
|
|
101
|
+
2. Detects method calls matching the keys
|
|
102
|
+
3. Adds operations to the `operations` Set
|
|
103
|
+
4. Formats output correctly
|
|
104
|
+
|
|
105
|
+
Adding new keys will be processed by the existing logic flow.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Verification
|
|
110
|
+
|
|
111
|
+
### Test Case
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Create a test diff with SELECT operations
|
|
115
|
+
cat > test.diff << 'EOF'
|
|
116
|
+
+ await repository.find({ where: { id } });
|
|
117
|
+
+ await repository.findOne({ where: { status: 'active' } });
|
|
118
|
+
+ const users = await queryBuilder.select(['id', 'name']).getMany();
|
|
119
|
+
EOF
|
|
120
|
+
|
|
121
|
+
# Run detector and verify output contains:
|
|
122
|
+
# - operations: ["SELECT"]
|
|
123
|
+
# - Correct table detection
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Expected Output
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
{
|
|
130
|
+
tableName: "users",
|
|
131
|
+
modelName: "UserEntity",
|
|
132
|
+
operations: ["SELECT"], // ✅ Now detected
|
|
133
|
+
fields: ["id", "name", "status"],
|
|
134
|
+
severity: "low" // SELECT is typically low severity
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Impact Assessment
|
|
141
|
+
|
|
142
|
+
### Risk Level: **LOW** ✅
|
|
143
|
+
|
|
144
|
+
**Why Low Risk:**
|
|
145
|
+
- Only adds new entries to existing map
|
|
146
|
+
- No changes to detection logic
|
|
147
|
+
- No changes to data structures
|
|
148
|
+
- Backward compatible (existing detections unaffected)
|
|
149
|
+
|
|
150
|
+
### Areas Affected
|
|
151
|
+
|
|
152
|
+
| Component | Change Type | Risk |
|
|
153
|
+
|-----------|-------------|------|
|
|
154
|
+
| `database-detector.js` | Addition only | Low |
|
|
155
|
+
| Report output | Enhanced data | None |
|
|
156
|
+
| Existing detections | None | None |
|
|
157
|
+
|
|
158
|
+
### Testing Required
|
|
159
|
+
|
|
160
|
+
- [ ] Unit test: Verify SELECT operations are detected
|
|
161
|
+
- [ ] Integration test: Check report includes SELECT in operations array
|
|
162
|
+
- [ ] Regression test: Verify existing INSERT/UPDATE/DELETE still work
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Implementation Checklist
|
|
167
|
+
|
|
168
|
+
- [x] Update `typeOrmOps` in `database-detector.js`
|
|
169
|
+
- [x] Test with `find()` operation
|
|
170
|
+
- [x] Test with `findOne()` operation
|
|
171
|
+
- [x] Test with `select()` operation
|
|
172
|
+
- [x] Test with `query()` operation
|
|
173
|
+
- [x] Verify report output shows SELECT
|
|
174
|
+
- [x] Check console output displays correctly
|
|
175
|
+
- [x] Verify JSON output includes SELECT
|
|
176
|
+
- [ ] Update CHANGELOG if needed
|
|
177
|
+
- [x] Mark bug as RESOLVED
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## References
|
|
182
|
+
|
|
183
|
+
**Code Files:**
|
|
184
|
+
- `core/detectors/database-detector.js` (line ~295)
|
|
185
|
+
- `core/report-generator.js` (displays operations)
|
|
186
|
+
|
|
187
|
+
**Related:**
|
|
188
|
+
- Task 002: `.specify/tasks/task-002-database-detector.md`
|
|
189
|
+
- Spec: `.specify/specs/features/database-impact-detection.md`
|
|
190
|
+
|
|
191
|
+
**TypeORM Documentation:**
|
|
192
|
+
- Repository API: https://typeorm.io/repository-api
|
|
193
|
+
- Select operations: `find`, `findOne`, `findBy`, etc.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Notes
|
|
198
|
+
|
|
199
|
+
- SELECT operations should be marked as lower severity than write operations
|
|
200
|
+
- This fix will make reports more complete and accurate
|
|
201
|
+
- Future enhancement: Track which fields are being selected
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
**Estimated Effort:** 5 minutes
|
|
206
|
+
**Actual Effort:** 3 minutes
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Resolution Summary
|
|
211
|
+
|
|
212
|
+
**Fixed on:** 2025-12-25
|
|
213
|
+
|
|
214
|
+
**Changes Made:**
|
|
215
|
+
1. Updated `typeOrmOps` map in `analyzeChangedCodeForDatabaseOps()` method (line 295)
|
|
216
|
+
2. Updated `typeOrmOps` map in `detectDatabaseOperationFromCall()` method (line 552)
|
|
217
|
+
3. Added 9 SELECT operation methods: find, findOne, findBy, findOneBy, findAndCount, select, query, getMany, getOne
|
|
218
|
+
|
|
219
|
+
**Files Modified:**
|
|
220
|
+
- `core/detectors/database-detector.js` (2 locations updated)
|
|
221
|
+
|
|
222
|
+
**Result:** SELECT operations are now fully detected and will appear in database impact reports.
|