Skip to content

Commit a26d6b5

Browse files
authored
Fix: Fixed bug in --fix for compare mode (#251)
* chore: removed unused code * fix: fixed bug in --fix for compare mode
1 parent a4ee8c2 commit a26d6b5

10 files changed

Lines changed: 66 additions & 115 deletions

File tree

src/commands/compare.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,14 @@ export async function compareMany(
129129
}
130130

131131
// Print duplicates
132-
printDuplicates(envName, exampleName, dupsEnv, dupsEx, opts.json ?? false);
132+
printDuplicates(
133+
envName,
134+
exampleName,
135+
dupsEnv,
136+
dupsEx,
137+
opts.json ?? false,
138+
opts.fix ?? false,
139+
);
133140

134141
// Calculate stats for JSON entry
135142
const stats = calculateStats(
@@ -160,9 +167,9 @@ export async function compareMany(
160167
}
161168

162169
// Print all issues
163-
printIssues(filtered, opts.json ?? false);
170+
printIssues(filtered, opts.json ?? false, opts.fix ?? false);
164171

165-
if (filtered.gitignoreIssue && !opts.json) {
172+
if (filtered.gitignoreIssue && !opts.json && !opts.fix) {
166173
printGitignoreWarning({
167174
envFile: envName,
168175
reason: filtered.gitignoreIssue.reason,
@@ -182,7 +189,6 @@ export async function compareMany(
182189
if (opts.fix) {
183190
const { changed, result } = applyFixes({
184191
envPath,
185-
examplePath,
186192
missingKeys: filtered.missing,
187193
duplicateKeys: dupsEnv.map((d) => d.key),
188194
ensureGitignore: hasGitignoreIssue,

src/core/fixEnv.ts

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { DEFAULT_GITIGNORE_ENV_PATTERNS } from '../config/constants.js';
88
*/
99
interface ApplyFixesOptions {
1010
envPath: string;
11-
examplePath: string;
1211
missingKeys: string[];
1312
duplicateKeys: string[];
1413
ensureGitignore?: boolean;
@@ -20,17 +19,15 @@ interface ApplyFixesOptions {
2019
interface FixResult {
2120
removedDuplicates: string[];
2221
addedEnv: string[];
23-
addedExample: string[];
2422
gitignoreUpdated: boolean;
2523
}
2624

2725
/**
28-
* Applies fixes to the .env and .env.example files based on the detected issues.
26+
* Applies fixes to the .env file based on the detected issues.
2927
*
3028
* This function will:
3129
* - Remove duplicate keys from .env (keeping the last occurrence)
32-
* - Add missing keys to .env with empty values
33-
* - Add missing keys to .env.example (if not already present)
30+
* - Add missing keys to .env file (with empty values)
3431
* - Ensure .env is ignored in .gitignore (if in a git repo and ensureGitignore is true)
3532
*
3633
* @param options - Fix options including file paths and keys to fix
@@ -42,7 +39,6 @@ export function applyFixes(options: ApplyFixesOptions): {
4239
} {
4340
const {
4441
envPath,
45-
examplePath,
4642
missingKeys = [],
4743
duplicateKeys = [],
4844
ensureGitignore = false,
@@ -51,7 +47,6 @@ export function applyFixes(options: ApplyFixesOptions): {
5147
const result: FixResult = {
5248
removedDuplicates: [],
5349
addedEnv: [],
54-
addedExample: [],
5550
gitignoreUpdated: false,
5651
};
5752

@@ -94,29 +89,6 @@ export function applyFixes(options: ApplyFixesOptions): {
9489
fs.writeFileSync(envPath, newContent);
9590
result.addedEnv = missingKeys;
9691
}
97-
98-
// --- Add missing keys to .env.example ---
99-
if (examplePath && missingKeys.length) {
100-
const exContent = fs.readFileSync(examplePath, 'utf-8');
101-
const existingExKeys = new Set(
102-
exContent
103-
.split('\n')
104-
.map((l) => l.trim().split('=')[0])
105-
.filter(Boolean),
106-
);
107-
const newExampleKeys = missingKeys.filter((k) => !existingExKeys.has(k));
108-
109-
if (newExampleKeys.length) {
110-
const newExContent =
111-
exContent +
112-
(exContent.endsWith('\n') ? '' : '\n') +
113-
newExampleKeys.join('\n') +
114-
'\n';
115-
fs.writeFileSync(examplePath, newExContent);
116-
result.addedExample = newExampleKeys;
117-
}
118-
}
119-
12092
// --- Ensure .env is ignored in .gitignore ---
12193
if (ensureGitignore) {
12294
result.gitignoreUpdated = updateGitignoreForEnv(envPath);
@@ -125,7 +97,6 @@ export function applyFixes(options: ApplyFixesOptions): {
12597
const changed =
12698
result.removedDuplicates.length > 0 ||
12799
result.addedEnv.length > 0 ||
128-
result.addedExample.length > 0 ||
129100
result.gitignoreUpdated;
130101

131102
return { changed, result };

src/services/printScanResult.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ export function printScanResult(
196196
{
197197
removedDuplicates: fixContext.removedDuplicates,
198198
addedEnv: fixContext.addedEnv,
199-
addedExample: opts.examplePath ? fixContext.addedEnv : [],
200199
},
201200
comparedAgainst || DEFAULT_ENV_FILE,
202201
opts.examplePath ? path.basename(opts.examplePath) : 'example file',

src/services/processComparisonFile.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ interface ProcessComparisonResult {
2929
fixApplied: boolean;
3030
removedDuplicates: string[];
3131
addedEnv: string[];
32-
addedExample: string[];
3332
gitignoreUpdated: boolean;
3433
exampleFull?: Record<string, string> | undefined;
3534
uppercaseWarnings?: UppercaseWarning[];
@@ -62,7 +61,6 @@ export function processComparisonFile(
6261
let fixApplied = false;
6362
let removedDuplicates: string[] = [];
6463
let addedEnv: string[] = [];
65-
let addedExample: string[] = [];
6664
let gitignoreUpdated = false;
6765
let exampleFull: Record<string, string> | undefined = undefined;
6866
let uppercaseWarnings: UppercaseWarning[] = [];
@@ -138,9 +136,6 @@ export function processComparisonFile(
138136
) {
139137
const { changed, result } = applyFixes({
140138
envPath: compareFile.path,
141-
examplePath: opts.examplePath
142-
? resolveFromCwd(opts.cwd, opts.examplePath)
143-
: '',
144139
missingKeys: scanResult.missing,
145140
duplicateKeys: dupsEnv.map((d) => d.key),
146141
ensureGitignore: true,
@@ -150,7 +145,6 @@ export function processComparisonFile(
150145
fixApplied = true;
151146
removedDuplicates = result.removedDuplicates;
152147
addedEnv = result.addedEnv;
153-
addedExample = result.addedExample;
154148
gitignoreUpdated = result.gitignoreUpdated;
155149

156150
scanResult.missing = [];
@@ -178,7 +172,6 @@ export function processComparisonFile(
178172
fixApplied,
179173
removedDuplicates,
180174
addedEnv,
181-
addedExample,
182175
gitignoreUpdated,
183176
exampleFull,
184177
uppercaseWarnings,
@@ -201,7 +194,6 @@ export function processComparisonFile(
201194
fixApplied,
202195
removedDuplicates,
203196
addedEnv,
204-
addedExample,
205197
gitignoreUpdated,
206198
exampleFull,
207199
uppercaseWarnings,

src/ui/compare/printIssues.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ import type { Filtered } from '../../config/types.js';
55
* Prints the issues found during the comparison.
66
* @param filtered The filtered comparison results.
77
* @param json Whether to output in JSON format.
8+
* @param fix Whether fix mode is enabled (skips printing missing keys as they will be fixed).
89
* @returns void
910
*/
10-
export function printIssues(filtered: Filtered, json: boolean): void {
11+
export function printIssues(
12+
filtered: Filtered,
13+
json: boolean,
14+
fix = false,
15+
): void {
1116
if (json) return;
12-
if (filtered.missing.length) {
17+
if (filtered.missing.length && !fix) {
1318
const header = chalk.red('❌ Missing keys:');
1419
console.log(header);
1520
filtered.missing.forEach((key) => console.log(chalk.red(` - ${key}`)));

src/ui/shared/printAutoFix.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import chalk from 'chalk';
33
interface AutoFixResult {
44
removedDuplicates: string[];
55
addedEnv: string[];
6-
addedExample: string[];
76
}
87

98
/**
@@ -41,13 +40,6 @@ export function printAutoFix(
4140
),
4241
);
4342
}
44-
if (result.addedExample.length && !result.addedEnv.length) {
45-
console.log(
46-
chalk.green(
47-
` - Synced ${result.addedExample.length} keys to ${exampleName}: ${result.addedExample.join(', ')}`,
48-
),
49-
);
50-
}
5143
if (gitignoreUpdated) {
5244
console.log(chalk.green(` - Added ${envName} to .gitignore`));
5345
}

src/ui/shared/printDuplicates.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import chalk from 'chalk';
77
* @param dEnv Array of duplicate keys in the environment file with their counts.
88
* @param dEx Array of duplicate keys in the example file with their counts.
99
* @param json Whether to output in JSON format.
10+
* @param fix Whether fix mode is enabled (skips printing duplicates as they will be fixed).
1011
* @returns void
1112
*/
1213
export function printDuplicates(
@@ -15,9 +16,10 @@ export function printDuplicates(
1516
dEnv: Array<{ key: string; count: number }>,
1617
dEx: Array<{ key: string; count: number }>,
1718
json: boolean,
19+
fix = false,
1820
): void {
1921
if (json) return;
20-
if (dEnv.length) {
22+
if (dEnv.length && !fix) {
2123
console.log(
2224
chalk.yellow(`⚠️ Duplicate keys in ${envName} (last occurrence wins):`),
2325
);

test/e2e/cli.flags.e2e.test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ describe('duplicate detection', () => {
258258
it('will detect duplicates in scan mode', () => {
259259
const cwd = tmpDir();
260260
fs.writeFileSync(path.join(cwd, '.env'), 'A=1\nA=2\nC=3\n');
261-
fs.writeFileSync(
261+
fs.writeFileSync(
262262
path.join(cwd, 'app.js'),
263263
`
264264
const api = process.env.A;
@@ -376,6 +376,40 @@ describe('duplicate detection', () => {
376376
expect(output.stats).toBeDefined();
377377
});
378378
});
379+
380+
it('when adding missing keys, remove duplicates and add .env til gitignore dont print issues', () => {
381+
const cwd = tmpDir();
382+
fs.writeFileSync(
383+
path.join(cwd, '.env'),
384+
'EXISTING=value\nEXISTING=value2\n',
385+
);
386+
fs.writeFileSync(
387+
path.join(cwd, 'app.js'),
388+
`
389+
const newVar = process.env.NEW_VAR;
390+
`,
391+
);
392+
393+
const res = runCli(cwd, ['--scan-usage', '--fix']);
394+
expect(res.status).toBe(0);
395+
expect(res.stdout).toContain('Auto-fix applied');
396+
expect(res.stdout).toContain('Added 1 missing keys to .env');
397+
expect(res.stdout).toContain('Removed 1 duplicate keys from .env');
398+
});
399+
400+
it('when adding missing keys, remove duplicates and add .env til gitignore dont print issues in --compare', () => {
401+
const cwd = tmpDir();
402+
fs.writeFileSync(
403+
path.join(cwd, '.env'),
404+
'EXISTING=value\nEXISTING=value2\n',
405+
);
406+
fs.writeFileSync(path.join(cwd, '.env.example'), 'EXISTING=\nNEW_KEY=\n');
407+
const res = runCli(cwd, ['--compare', '--fix']);
408+
expect(res.stdout).toContain('Auto-fix applied');
409+
expect(res.stdout).toContain('Added 1 missing keys to .env');
410+
expect(res.stdout).toContain('Removed 1 duplicate keys from .env');
411+
});
412+
379413
it('does not duplicate keys in .env.example when they already exist', () => {
380414
const cwd = tmpDir();
381415
fs.writeFileSync(path.join(cwd, '.env'), 'EXISTING=value\n');

test/unit/commands/compare.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ describe('compareMany', () => {
220220
missing: ['KEY3'],
221221
}),
222222
false,
223+
false,
223224
);
224225
});
225226

@@ -240,6 +241,7 @@ describe('compareMany', () => {
240241
extra: ['EXTRA_KEY'],
241242
}),
242243
false,
244+
false,
243245
);
244246
});
245247

@@ -261,6 +263,7 @@ describe('compareMany', () => {
261263
empty: ['KEY1'],
262264
}),
263265
false,
266+
false,
264267
);
265268
});
266269

@@ -286,6 +289,7 @@ describe('compareMany', () => {
286289
[{ key: 'DUP_KEY', count: 2 }],
287290
[{ key: 'DUP_EX', count: 3 }],
288291
false,
292+
false,
289293
);
290294
});
291295

@@ -303,6 +307,7 @@ describe('compareMany', () => {
303307
[],
304308
[],
305309
false,
310+
false,
306311
);
307312
});
308313

@@ -346,6 +351,7 @@ describe('compareMany', () => {
346351
mismatches: [{ key: 'KEY1', expected: 'expected', actual: 'actual' }],
347352
}),
348353
false,
354+
false,
349355
);
350356
});
351357

@@ -362,7 +368,6 @@ describe('compareMany', () => {
362368
removedDuplicates: [],
363369
addedEnv: ['MISSING_KEY'],
364370
gitignoreUpdated: false,
365-
addedExample: [],
366371
},
367372
});
368373

@@ -373,7 +378,6 @@ describe('compareMany', () => {
373378

374379
expect(mockApplyFixes).toHaveBeenCalledWith({
375380
envPath,
376-
examplePath,
377381
missingKeys: ['MISSING_KEY'],
378382
duplicateKeys: [],
379383
ensureGitignore: false,
@@ -412,7 +416,6 @@ describe('compareMany', () => {
412416
removedDuplicates: ['DUPLICATE_KEY', 'ANOTHER_DUP'],
413417
addedEnv: [],
414418
gitignoreUpdated: false,
415-
addedExample: [],
416419
},
417420
});
418421

@@ -423,7 +426,6 @@ describe('compareMany', () => {
423426

424427
expect(mockApplyFixes).toHaveBeenCalledWith({
425428
envPath,
426-
examplePath,
427429
missingKeys: [],
428430
duplicateKeys: ['DUPLICATE_KEY', 'ANOTHER_DUP'],
429431
ensureGitignore: false,
@@ -531,6 +533,7 @@ describe('compareMany', () => {
531533
extra: [],
532534
}),
533535
false,
536+
false,
534537
);
535538
});
536539

@@ -711,6 +714,7 @@ describe('compareMany', () => {
711714
empty: expect.arrayContaining(['KEY1', 'KEY2']),
712715
}),
713716
false,
717+
false,
714718
);
715719
});
716720

@@ -790,7 +794,6 @@ describe('compareMany', () => {
790794
removedDuplicates: [],
791795
addedEnv: [],
792796
gitignoreUpdated: true,
793-
addedExample: [],
794797
},
795798
});
796799

@@ -832,6 +835,7 @@ describe('compareMany', () => {
832835
mismatches: [{ key: 'KEY1', expected: 'exp', actual: 'act' }],
833836
}),
834837
false,
838+
false,
835839
);
836840
expect(mockPrintGitignoreWarning).toHaveBeenCalled();
837841
});

0 commit comments

Comments
 (0)