@sun-asterisk/impact-analyzer 1.0.6 → 1.0.7
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/.specify/bugs/bug-004-fix-summary.md +59 -0
- package/.specify/bugs/bug-004-raw-sql-detection.md +158 -0
- package/.specify/bugs/bug-005-queue-processor-detection.md +197 -0
- package/.specify/tasks/task-005-cli-optimization.md +284 -0
- package/.specify/tasks/task-005-completion.md +99 -0
- package/README.md +150 -36
- package/cli.js +68 -0
- package/config/default-config.js +5 -9
- package/core/detectors/database-detector.js +408 -3
- package/core/utils/logger.js +2 -1
- package/core/utils/method-call-graph.js +249 -4
- package/index.js +6 -0
- package/package.json +5 -2
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# BUG-004 Fix Summary
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
✅ **FIXED**
|
|
5
|
+
|
|
6
|
+
## What Was Fixed
|
|
7
|
+
Raw SQL detection now correctly identifies database changes even when modifications are deep inside multi-line template literals.
|
|
8
|
+
|
|
9
|
+
## Root Cause
|
|
10
|
+
The original implementation processed diff lines without accessing the full file content. This meant it couldn't see the `.query()` method call when the change was in the SQL string body.
|
|
11
|
+
|
|
12
|
+
## Solution
|
|
13
|
+
Refactored to use **full file content** instead of diff-only approach:
|
|
14
|
+
|
|
15
|
+
### New Flow
|
|
16
|
+
```
|
|
17
|
+
1. Read full file from disk
|
|
18
|
+
2. Parse diff → get changed line numbers
|
|
19
|
+
3. For each changed line:
|
|
20
|
+
- Search backwards for `.query(` or `.execute(`
|
|
21
|
+
- Search forward for statement end (`;`)
|
|
22
|
+
- Extract complete statement
|
|
23
|
+
- Parse SQL from template literal
|
|
24
|
+
- Report tables/fields
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Key Changes
|
|
28
|
+
| Method | Change | Purpose |
|
|
29
|
+
|--------|--------|---------|
|
|
30
|
+
| `detectRawSQLQueries()` | Added `filePath` param | Read full file content |
|
|
31
|
+
| `extractChangedLineNumbers()` | New method | Parse diff hunks |
|
|
32
|
+
| `findQueryStatementContainingLine()` | New method | Find parent SQL statement |
|
|
33
|
+
| `extractSQLFromStatement()` | Simplified | Extract SQL from template |
|
|
34
|
+
|
|
35
|
+
## Test Case
|
|
36
|
+
```typescript
|
|
37
|
+
// Before: ❌ Not detected
|
|
38
|
+
// After: ✅ Detected
|
|
39
|
+
|
|
40
|
+
const [result] = await queryRunner.manager.query<Array<{ count: string }>>(
|
|
41
|
+
`
|
|
42
|
+
SELECT COUNT(*) as count
|
|
43
|
+
FROM t003
|
|
44
|
+
WHERE t003.field_1 = $1
|
|
45
|
+
AND t003.field_3 = ANY($3) // <- Change here
|
|
46
|
+
`,
|
|
47
|
+
[var1, var2, [1, 2, 3]],
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Result**: ✅ Detects `t003` table, `field_3` field, `SELECT` operation
|
|
52
|
+
|
|
53
|
+
## Files Modified
|
|
54
|
+
- `core/detectors/database-detector.js` (~180 lines changed)
|
|
55
|
+
|
|
56
|
+
## Verified
|
|
57
|
+
✅ Syntax check passed
|
|
58
|
+
✅ No breaking changes to existing API
|
|
59
|
+
✅ Maintains backward compatibility
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# BUG-004: Raw SQL Detection in Database Changes
|
|
2
|
+
|
|
3
|
+
**Bug ID:** BUG-004
|
|
4
|
+
**Status:** ✅ Fixed
|
|
5
|
+
**Priority:** High
|
|
6
|
+
**Component:** `core/detectors/database-detector.js`
|
|
7
|
+
**Created:** 2025-01-29
|
|
8
|
+
**Fixed:** 2025-01-30
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
Database detector fails to detect changes in raw SQL queries when:
|
|
15
|
+
1. SQL queries span multiple lines (template literals)
|
|
16
|
+
2. Changes occur in WHERE conditions (e.g., `= $1` → `= ANY($1)`)
|
|
17
|
+
3. SQL is in `queryRunner.manager.query()` or similar methods
|
|
18
|
+
|
|
19
|
+
**Example:**
|
|
20
|
+
```typescript
|
|
21
|
+
await queryRunner.manager.query(`
|
|
22
|
+
SELECT COUNT(*) as count
|
|
23
|
+
FROM user
|
|
24
|
+
WHERE user.id = $1
|
|
25
|
+
- AND user.name = $2
|
|
26
|
+
+ AND user.name = ANY($2) // <- change not detected
|
|
27
|
+
`)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Expected:** Detect `user` table and `name` field
|
|
31
|
+
**Actual:** No detection or incomplete detection
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Root Cause
|
|
36
|
+
|
|
37
|
+
Current `detectRawSQLQueries()` processes diff **line-by-line**:
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
for (const line of lines) {
|
|
41
|
+
if (line.startsWith('+')) {
|
|
42
|
+
if (added.includes('.query(')) {
|
|
43
|
+
const sqlMatch = added.match(/`([^`]+)`/);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Problems:**
|
|
50
|
+
1. ❌ Cannot capture multi-line SQL (template literals span multiple lines)
|
|
51
|
+
2. ❌ Only checks added lines (`+`), misses modified/context lines
|
|
52
|
+
3. ❌ Assumes SQL starts and ends on same line
|
|
53
|
+
4. ❌ Fragile pattern matching - breaks with formatting changes
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Fix Strategy
|
|
58
|
+
|
|
59
|
+
### Change Detection Approach
|
|
60
|
+
|
|
61
|
+
**From:** Line-by-line iteration → **To:** Block-based detection
|
|
62
|
+
|
|
63
|
+
**New Algorithm:**
|
|
64
|
+
1. Extract full file content (not just diff)
|
|
65
|
+
2. Find all SQL query blocks using regex (template literals, .query() calls)
|
|
66
|
+
3. Match changed line numbers to SQL block ranges
|
|
67
|
+
4. Parse affected SQL blocks to extract tables/fields
|
|
68
|
+
|
|
69
|
+
### Implementation Steps
|
|
70
|
+
|
|
71
|
+
**Step 1:** Add `extractSQLBlocks(fileContent)` - Find all SQL blocks with line ranges
|
|
72
|
+
|
|
73
|
+
**Step 2:** Add `findAffectedSQLBlocks(sqlBlocks, diff)` - Match diff changes to blocks
|
|
74
|
+
|
|
75
|
+
**Step 3:** Improve `parseSQLForSchema(sql)` - Extract tables/fields from full SQL
|
|
76
|
+
|
|
77
|
+
**Step 4:** Refactor `detectRawSQLQueries(file, diff)` - Use block-based approach
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Test Cases
|
|
82
|
+
|
|
83
|
+
**Test 1:** Multi-line WHERE condition change
|
|
84
|
+
```sql
|
|
85
|
+
WHERE user.id = $1
|
|
86
|
+
- AND user.name = $2
|
|
87
|
+
+ AND user.name = ANY($2)
|
|
88
|
+
```
|
|
89
|
+
Expected: Detect `user.name` field change
|
|
90
|
+
|
|
91
|
+
**Test 2:** JOIN type change
|
|
92
|
+
```typescript
|
|
93
|
+
- .innerJoin('orders', 'orders.user_id = user.id')
|
|
94
|
+
+ .leftJoin('orders', 'orders.user_id = user.id')
|
|
95
|
+
```
|
|
96
|
+
Expected: Detect JOIN operation change on `orders`, `user` tables
|
|
97
|
+
|
|
98
|
+
**Test 3:** SELECT field addition
|
|
99
|
+
```sql
|
|
100
|
+
- SELECT user.id, user.name FROM user
|
|
101
|
+
+ SELECT user.id, user.name, user.email FROM user
|
|
102
|
+
```
|
|
103
|
+
Expected: Detect new `user.email` field
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Checklist
|
|
108
|
+
|
|
109
|
+
- [x] Implement changed-line-first approach instead of pattern-first
|
|
110
|
+
- [x] Implement `findParentSQLBlock()` - find parent block containing SQL method
|
|
111
|
+
- [x] Implement `extractSQLFromBlock()` - extract SQL from code block
|
|
112
|
+
- [x] Refactor `detectRawSQLQueries()` to use new approach
|
|
113
|
+
- [x] Remove old `extractSQLFromMethodCall()` and `extractStringLiteral()` methods
|
|
114
|
+
- [ ] Add tests for multi-line SQL changes
|
|
115
|
+
- [ ] Verify no regression
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Fix Applied
|
|
120
|
+
|
|
121
|
+
**Date:** 2025-01-30
|
|
122
|
+
|
|
123
|
+
**Approach Changed:**
|
|
124
|
+
- **OLD (Incorrect):** Pattern-first → Find all `.query()` in file → Check if overlaps with changes
|
|
125
|
+
- **NEW (Correct):** Change-first → Start from changed lines → Find parent block → Check if contains `.query()`
|
|
126
|
+
|
|
127
|
+
**Implementation:**
|
|
128
|
+
|
|
129
|
+
1. **`detectRawSQLQueries()`** - New change-driven approach:
|
|
130
|
+
- Parse diff to find all changed line numbers (+ or -)
|
|
131
|
+
- For each changed line, find parent SQL block
|
|
132
|
+
- Extract SQL only from blocks that changed
|
|
133
|
+
|
|
134
|
+
2. **`findParentSQLBlock()`** - Find parent function containing SQL:
|
|
135
|
+
- Search backward from changed line for `.query()` or `.execute()`
|
|
136
|
+
- Search forward to find statement end (handle parentheses depth)
|
|
137
|
+
- Return complete block with boundaries
|
|
138
|
+
|
|
139
|
+
3. **`extractSQLFromBlock()`** - Extract SQL string:
|
|
140
|
+
- Find string literal after `.query()` or `.execute()`
|
|
141
|
+
- Handle template literals, single/double quotes
|
|
142
|
+
- Return cleaned SQL content
|
|
143
|
+
|
|
144
|
+
**Why This Works:**
|
|
145
|
+
- Starts from **what changed** (diff lines), not patterns
|
|
146
|
+
- Finds **context around changes** (parent block)
|
|
147
|
+
- Only processes **blocks that actually changed**
|
|
148
|
+
- Handles multi-line statements correctly
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Impact
|
|
153
|
+
|
|
154
|
+
- **Severity:** High - Missing critical database changes
|
|
155
|
+
- **Files Affected:** `core/detectors/database-detector.js` (~150-200 lines)
|
|
156
|
+
- **Related:** BUG-001, BUG-002, BUG-003
|
|
157
|
+
|
|
158
|
+
**Key Insight:** Need to parse full code structure first, then identify affected regions - not analyze line-by-line diffs.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# BUG-005: Queue Processor Endpoint Detection Missing
|
|
2
|
+
|
|
3
|
+
**Bug ID:** BUG-005
|
|
4
|
+
**Created:** 2025-12-30
|
|
5
|
+
**Status:** Fixed
|
|
6
|
+
**Severity:** Medium
|
|
7
|
+
**Component:** endpoint-detector.js, method-call-graph.js
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Problem
|
|
12
|
+
|
|
13
|
+
**Current behavior:**
|
|
14
|
+
Queue processors using `@nestjs/bull` pattern are not detected as endpoints.
|
|
15
|
+
|
|
16
|
+
**Example pattern not detected:**
|
|
17
|
+
```typescript
|
|
18
|
+
// Processor (worker)
|
|
19
|
+
@Processor('update-queue')
|
|
20
|
+
export class UpdateFactoryProcessor {
|
|
21
|
+
constructor(
|
|
22
|
+
@InjectRepository(UserEntity)
|
|
23
|
+
private readonly userRepository: Repository<UserEntity>,
|
|
24
|
+
) {}
|
|
25
|
+
|
|
26
|
+
@Process('update-task')
|
|
27
|
+
async handleUpdateTask(job: Job) {
|
|
28
|
+
// This method is not detected as endpoint
|
|
29
|
+
const result = await this.userRepository.update(...);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Controller (producer)
|
|
35
|
+
@Controller('users')
|
|
36
|
+
export class UserController {
|
|
37
|
+
constructor(
|
|
38
|
+
@InjectQueue('update-queue')
|
|
39
|
+
private readonly updateQueue: Queue,
|
|
40
|
+
) {}
|
|
41
|
+
|
|
42
|
+
@Post('trigger-update')
|
|
43
|
+
async triggerUpdate() {
|
|
44
|
+
await this.updateQueue.add('update-task', { ... });
|
|
45
|
+
return { message: 'Job queued' };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Expected:** Should detect both:
|
|
51
|
+
- Queue processor method `handleUpdateTask` as async endpoint
|
|
52
|
+
- Controller method `triggerUpdate` that triggers the queue
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Root Cause
|
|
57
|
+
|
|
58
|
+
**Location:** `core/detectors/endpoint-detector.js`
|
|
59
|
+
|
|
60
|
+
1. **Only detects HTTP decorators** - Current implementation only looks for `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch`
|
|
61
|
+
2. **Ignores queue patterns** - Does not recognize `@Processor()` and `@Process()` decorators
|
|
62
|
+
3. **Missing queue linkage** - Does not connect controller `@InjectQueue()` to processor `@Processor()`
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Impact
|
|
67
|
+
|
|
68
|
+
- **Missing queue-based endpoints** in impact analysis
|
|
69
|
+
- **Incomplete call chains** when changes affect queue processors
|
|
70
|
+
- **False negatives** for async job handlers
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Fix Strategy
|
|
75
|
+
|
|
76
|
+
### Step 1: Detect Queue Processors
|
|
77
|
+
Add pattern detection in `methodCallGraph` or `endpoint-detector`:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
// Detect @Processor('queue-name')
|
|
81
|
+
const processorPattern = /@Processor\(['"`]([^'"`]+)['"`]\)/;
|
|
82
|
+
|
|
83
|
+
// Detect @Process('job-name') methods
|
|
84
|
+
const processPattern = /@Process\(['"`]([^'"`]+)['"`]\)/;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Step 2: Detect Queue Injection
|
|
88
|
+
```javascript
|
|
89
|
+
// Detect @InjectQueue('queue-name') in controllers
|
|
90
|
+
const injectQueuePattern = /@InjectQueue\(['"`]([^'"`]+)['"`]\)/;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Step 3: Link Controller to Processor
|
|
94
|
+
```javascript
|
|
95
|
+
// When controller has @InjectQueue('update-queue')
|
|
96
|
+
// and calls this.updateQueue.add('update-task', ...)
|
|
97
|
+
// Link to @Processor('update-queue') @Process('update-task')
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Step 4: Report Format
|
|
101
|
+
```javascript
|
|
102
|
+
{
|
|
103
|
+
method: 'QUEUE',
|
|
104
|
+
path: '/queue/update-queue/update-task',
|
|
105
|
+
handler: 'UpdateFactoryProcessor.handleUpdateTask',
|
|
106
|
+
triggeredBy: 'UserController.triggerUpdate (POST /users/trigger-update)',
|
|
107
|
+
layers: ['Controller', 'Queue', 'Processor', 'Repository']
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Checklist
|
|
114
|
+
|
|
115
|
+
- [x] Add queue processor detection patterns
|
|
116
|
+
- [x] Add queue injection detection in controllers
|
|
117
|
+
- [x] Link queue producers to consumers
|
|
118
|
+
- [x] Update report to show queue-based endpoints
|
|
119
|
+
- [ ] Test with @nestjs/bull examples
|
|
120
|
+
- [ ] Update documentation
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Fix Implementation
|
|
125
|
+
|
|
126
|
+
### Changes Made (2025-12-30)
|
|
127
|
+
|
|
128
|
+
**File:** `core/utils/method-call-graph.js`
|
|
129
|
+
|
|
130
|
+
**Change 1:** Detect queue dispatches in ALL methods (line ~128-134)
|
|
131
|
+
```javascript
|
|
132
|
+
// OLD: Only in endpoint methods
|
|
133
|
+
if (httpDecorator) {
|
|
134
|
+
this.detectCommandDispatches(method, fullMethodName);
|
|
135
|
+
this.detectQueueDispatches(method, fullMethodName);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// NEW: In all methods (endpoints + services)
|
|
139
|
+
this.detectCommandDispatches(method, fullMethodName);
|
|
140
|
+
this.detectQueueDispatches(method, fullMethodName);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Change 2:** Enhanced `findEndpointsByQueue()` method (line ~867-941)
|
|
144
|
+
- **Pattern 1 (Direct)**: Controller → Queue.add() → Processor
|
|
145
|
+
- **Pattern 2 (Indirect)**: Controller → Service → Queue.add() → Processor
|
|
146
|
+
|
|
147
|
+
When a service method triggers a queue:
|
|
148
|
+
1. Find which controllers call that service
|
|
149
|
+
2. Build full call chain: Processor ← Queue ← Service ← Controller
|
|
150
|
+
3. Report controller endpoints
|
|
151
|
+
|
|
152
|
+
### How It Works
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
1. Processor file changes
|
|
156
|
+
└─> Extract changed method: UpdateProcessor.handleJob
|
|
157
|
+
|
|
158
|
+
2. Check if queue processor
|
|
159
|
+
└─> Found @Process decorator → queue: 'update-queue'
|
|
160
|
+
|
|
161
|
+
3. Find methods calling queue.add('update-queue')
|
|
162
|
+
└─> Found: UpdateService.triggerUpdate
|
|
163
|
+
|
|
164
|
+
4. Trace service callers
|
|
165
|
+
└─> Found: UpdateController.update
|
|
166
|
+
|
|
167
|
+
5. Report endpoint
|
|
168
|
+
└─> POST /api/update is affected
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Checklist
|
|
174
|
+
|
|
175
|
+
- [ ] Add queue processor detection patterns
|
|
176
|
+
- [ ] Add queue injection detection in controllers
|
|
177
|
+
- [ ] Link queue producers to consumers
|
|
178
|
+
- [ ] Update report to show queue-based endpoints
|
|
179
|
+
- [ ] Test with @nestjs/bull examples
|
|
180
|
+
- [ ] Update documentation
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## References
|
|
185
|
+
|
|
186
|
+
- NestJS Bull Documentation: https://docs.nestjs.com/techniques/queues
|
|
187
|
+
- Current implementation: `core/detectors/endpoint-detector.js`
|
|
188
|
+
- Call graph: `core/analyzers/method-call-graph.js`
|
|
189
|
+
- API Impact Detection Spec: `.specify/specs/features/api-impact-detection.md`
|
|
190
|
+
- Architecture Doc: `.specify/plans/architecture.md`
|
|
191
|
+
- Code Rules: `.github/copilot-instructions.md`
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Notes
|
|
196
|
+
|
|
197
|
+
Queue-based patterns are common in microservices and async processing. Missing these endpoints leads to incomplete impact analysis for background job changes.
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# TASK-005: CLI Optimization & Default Configuration
|
|
2
|
+
|
|
3
|
+
**Status:** 📋 TODO
|
|
4
|
+
**Priority:** Medium
|
|
5
|
+
**Estimated Effort:** 2-3 hours
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📋 Overview
|
|
10
|
+
|
|
11
|
+
Improve CLI usability by adding default configurations and comprehensive usage documentation. Make the tool easier to use with sensible defaults while maintaining flexibility.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🎯 Objectives
|
|
16
|
+
|
|
17
|
+
1. ✅ Add default values for optional CLI arguments
|
|
18
|
+
2. ✅ Improve help text and usage documentation
|
|
19
|
+
3. ✅ Add validation and better error messages
|
|
20
|
+
4. ✅ Support config file (`.impactrc.json`)
|
|
21
|
+
5. ✅ Update README with complete usage guide
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 📝 Requirements
|
|
26
|
+
|
|
27
|
+
### 1. CLI Argument Defaults
|
|
28
|
+
|
|
29
|
+
**Current behavior:**
|
|
30
|
+
- `--base` is required
|
|
31
|
+
- Other args require explicit values
|
|
32
|
+
- No fallback configuration
|
|
33
|
+
|
|
34
|
+
**Expected behavior:**
|
|
35
|
+
```bash
|
|
36
|
+
# Minimal command (use defaults for base)
|
|
37
|
+
npx impact-analyzer
|
|
38
|
+
|
|
39
|
+
# Full command (override defaults)
|
|
40
|
+
npx impact-analyzer --input=src --base=HEAD~1 --head=HEAD --output=report.md --json=report.json --verbose
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Default values:**
|
|
44
|
+
- `--input`: `src` (or auto-detect from `package.json` or `tsconfig.json`)
|
|
45
|
+
- `--base`: `HEAD~1` (NEW: no longer required, use HEAD~1 as default)
|
|
46
|
+
- `--head`: `HEAD`
|
|
47
|
+
- `--output`: No default (console only)
|
|
48
|
+
- `--json`: No default (console only)
|
|
49
|
+
- `--verbose`: `false`
|
|
50
|
+
|
|
51
|
+
### 2. Config File Support
|
|
52
|
+
|
|
53
|
+
Support `.impactrc.json` for project-level defaults:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"input": "src",
|
|
58
|
+
"excludePaths": ["node_modules", "dist", "**/*.test.ts"],
|
|
59
|
+
"verbose": false,
|
|
60
|
+
"severity": {
|
|
61
|
+
"low": 20,
|
|
62
|
+
"medium": 50,
|
|
63
|
+
"high": 100
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Priority:** CLI args > `.impactrc.json` > built-in defaults
|
|
69
|
+
|
|
70
|
+
### 3. Help Command
|
|
71
|
+
|
|
72
|
+
Add `--help` or `-h` flag:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx impact-analyzer --help
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Output:**
|
|
79
|
+
```
|
|
80
|
+
Impact Analyzer - Code change impact analysis tool
|
|
81
|
+
|
|
82
|
+
USAGE:
|
|
83
|
+
npx impact-analyzer [options]
|
|
84
|
+
|
|
85
|
+
OPTIONS:
|
|
86
|
+
--input=<path> Source directory (default: src)
|
|
87
|
+
--base=<ref> Git base reference (default: HEAD~1)
|
|
88
|
+
--head=<ref> Git head reference (default: HEAD)
|
|
89
|
+
--output=<path> Markdown report output path
|
|
90
|
+
--json=<path> JSON report output path
|
|
91
|
+
--verbose Enable verbose logging
|
|
92
|
+
--help, -h Show this help message
|
|
93
|
+
|
|
94
|
+
EXAMPLES:
|
|
95
|
+
# Basic analysis (compare HEAD~1 to HEAD)
|
|
96
|
+
npx impact-analyzer
|
|
97
|
+
|
|
98
|
+
# Compare with specific branch
|
|
99
|
+
npx impact-analyzer --base=origin/main
|
|
100
|
+
|
|
101
|
+
# With custom input directory
|
|
102
|
+
npx impact-analyzer --input=backend/src --base=origin/develop
|
|
103
|
+
|
|
104
|
+
# Generate reports
|
|
105
|
+
npx impact-analyzer --output=impact.md --json=impact.json
|
|
106
|
+
|
|
107
|
+
# Verbose mode
|
|
108
|
+
npx impact-analyzer --verbose
|
|
109
|
+
|
|
110
|
+
MORE INFO:
|
|
111
|
+
Documentation: https://github.com/sun-asterisk/impact-analyzer
|
|
112
|
+
Report issues: https://github.com/sun-asterisk/impact-analyzer/issues
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 4. Validation & Error Messages
|
|
116
|
+
|
|
117
|
+
**Validate:**
|
|
118
|
+
- ✅ `--input` directory exists
|
|
119
|
+
- ✅ Git repository is valid
|
|
120
|
+
- ✅ Base/head refs exist
|
|
121
|
+
|
|
122
|
+
**Error messages:**
|
|
123
|
+
```bash
|
|
124
|
+
# Invalid path
|
|
125
|
+
❌ Error: Input directory not found: 'invalid/path'
|
|
126
|
+
Please provide a valid directory path with --input
|
|
127
|
+
|
|
128
|
+
# Invalid git ref
|
|
129
|
+
❌ Error: Git reference not found: 'origin/invalid'
|
|
130
|
+
Run 'git fetch' or verify the branch exists
|
|
131
|
+
|
|
132
|
+
# Not in git repository
|
|
133
|
+
❌ Error: Not a git repository
|
|
134
|
+
Please run this tool inside a git repository
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🔧 Implementation Plan
|
|
140
|
+
|
|
141
|
+
### Phase 1: Add Default Configuration
|
|
142
|
+
|
|
143
|
+
**File:** `cli.js`
|
|
144
|
+
|
|
145
|
+
1. Add default values to `CLI` class:
|
|
146
|
+
```javascript
|
|
147
|
+
const DEFAULTS = {
|
|
148
|
+
input: 'src',
|
|
149
|
+
base: 'HEAD~1',
|
|
150
|
+
head: 'HEAD',
|
|
151
|
+
verbose: false
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. Update `getArg()` method:
|
|
156
|
+
```javascript
|
|
157
|
+
getArg(key, defaultValue = DEFAULTS[key] || '') {
|
|
158
|
+
return this.args.get(key) || defaultValue;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Phase 2: Add Config File Support
|
|
163
|
+
|
|
164
|
+
**File:** `config/config-loader.js` (new)
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
export class ConfigLoader {
|
|
168
|
+
static load(cwd = process.cwd()) {
|
|
169
|
+
// Try .impactrc.json
|
|
170
|
+
// Try package.json "impact" field
|
|
171
|
+
// Return defaults
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Phase 3: Add Help Command
|
|
177
|
+
|
|
178
|
+
**File:** `cli.js`
|
|
179
|
+
|
|
180
|
+
Add method:
|
|
181
|
+
```javascript
|
|
182
|
+
showHelp() {
|
|
183
|
+
console.log(`
|
|
184
|
+
Impact Analyzer - Code change impact analysis tool
|
|
185
|
+
|
|
186
|
+
USAGE: ...
|
|
187
|
+
`);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Check in `index.js`:
|
|
192
|
+
```javascript
|
|
193
|
+
if (cli.hasArg('help') || cli.hasArg('h')) {
|
|
194
|
+
cli.showHelp();
|
|
195
|
+
process.exit(0);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Phase 4: Add Validation
|
|
200
|
+
|
|
201
|
+
**File:** `core/validator.js` (new)
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
export class CLIValidator {
|
|
205
|
+
static validate(args) {
|
|
206
|
+
// Check required args
|
|
207
|
+
// Check paths exist
|
|
208
|
+
// Check git refs
|
|
209
|
+
// Return { valid: true/false, errors: [] }
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Phase 5: Update Documentation
|
|
215
|
+
|
|
216
|
+
**File:** `README.md`
|
|
217
|
+
|
|
218
|
+
Add sections:
|
|
219
|
+
- ✅ Configuration file usage
|
|
220
|
+
- ✅ Default values table
|
|
221
|
+
- ✅ Troubleshooting guide
|
|
222
|
+
- ✅ More examples
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## ✅ Acceptance Criteria
|
|
227
|
+
|
|
228
|
+
- [ ] NO required arguments (all have defaults)
|
|
229
|
+
- [ ] `--base` defaults to `HEAD~1`
|
|
230
|
+
- [ ] `--input` defaults to `src` directory
|
|
231
|
+
- [ ] `--head` defaults to `HEAD`
|
|
232
|
+
- [ ] `--help` displays usage information
|
|
233
|
+
- [ ] `.impactrc.json` config file is supported
|
|
234
|
+
- [ ] Clear validation error messages
|
|
235
|
+
- [ ] README documentation is complete
|
|
236
|
+
- [ ] Works without any args: `npx impact-analyzer`
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 🧪 Testing
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Test defaults (should work with no args)
|
|
244
|
+
npx impact-analyzer
|
|
245
|
+
|
|
246
|
+
# Test with base ref
|
|
247
|
+
npx impact-analyzer --base=origin/main
|
|
248
|
+
|
|
249
|
+
# Test help
|
|
250
|
+
npx impact-analyzer --help
|
|
251
|
+
|
|
252
|
+
# Test validation
|
|
253
|
+
npx impact-analyzer --base=invalid-ref # Should show error
|
|
254
|
+
npx impact-analyzer --input=invalid-path # Should show error
|
|
255
|
+
|
|
256
|
+
# Test config file
|
|
257
|
+
echo '{"input":"backend/src","base":"origin/develop"}' > .impactrc.json
|
|
258
|
+
npx impact-analyzer
|
|
259
|
+
|
|
260
|
+
# Test override
|
|
261
|
+
npx impact-analyzer --base=origin/main --input=custom/path
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## 📚 References
|
|
267
|
+
|
|
268
|
+
### External Resources
|
|
269
|
+
- CLI best practices: https://clig.dev/
|
|
270
|
+
- Commander.js (if we want to use a library): https://github.com/tj/commander.js
|
|
271
|
+
- Yargs (alternative): https://yargs.js.org/
|
|
272
|
+
|
|
273
|
+
### Internal Coding Standards
|
|
274
|
+
Follow these coding rules from `.github/copilot-instructions.md`:
|
|
275
|
+
- **Rule C005** – Each function should do one thing only
|
|
276
|
+
- **Rule C006** – Function names must be verb/verb-noun
|
|
277
|
+
- **Rule C007** – Avoid comments that just describe the code
|
|
278
|
+
- **Rule C012** – Separate Command and Query (CQS principle)
|
|
279
|
+
- **Rule C014** – Use Dependency Injection instead of direct `new` in logic
|
|
280
|
+
- **Rule C015** – Use domain language in class/function names
|
|
281
|
+
- **Rule C031** – Data validation logic must be separated
|
|
282
|
+
- **Rule C035** – When handling errors, log full context information
|
|
283
|
+
- **Rule C037** – API handlers should return standard response objects
|
|
284
|
+
- **Rule C040** – Don't scatter validation logic across multiple classes
|