dotenv-diff 2.2.5 → 2.2.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/README.md +11 -0
- package/dist/src/cli/program.d.ts +4 -0
- package/dist/src/cli/program.d.ts.map +1 -1
- package/dist/src/cli/program.js +4 -0
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/cli/run.d.ts.map +1 -1
- package/dist/src/cli/run.js +137 -94
- package/dist/src/cli/run.js.map +1 -1
- package/dist/src/commands/compare.d.ts.map +1 -1
- package/dist/src/commands/compare.js +2 -2
- package/dist/src/commands/compare.js.map +1 -1
- package/dist/src/commands/scanUsage.d.ts +1 -57
- package/dist/src/commands/scanUsage.d.ts.map +1 -1
- package/dist/src/commands/scanUsage.js +8 -225
- package/dist/src/commands/scanUsage.js.map +1 -1
- package/dist/src/config/loadConfig.d.ts +2 -0
- package/dist/src/config/loadConfig.d.ts.map +1 -0
- package/dist/src/config/types.d.ts +100 -0
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/config/types.js +1 -0
- package/dist/src/config/types.js.map +1 -1
- package/dist/src/core/compareScan.d.ts +9 -0
- package/dist/src/core/compareScan.d.ts.map +1 -0
- package/dist/src/core/compareScan.js +18 -0
- package/dist/src/core/compareScan.js.map +1 -0
- package/dist/src/core/determineComparisonFile.d.ts +11 -0
- package/dist/src/core/determineComparisonFile.d.ts.map +1 -0
- package/dist/src/core/determineComparisonFile.js +34 -0
- package/dist/src/core/determineComparisonFile.js.map +1 -0
- package/dist/src/core/diffEnv.d.ts +19 -0
- package/dist/src/core/diffEnv.d.ts.map +1 -0
- package/dist/src/core/diffEnv.js +31 -0
- package/dist/src/core/diffEnv.js.map +1 -0
- package/dist/src/core/helpers/resolveFromCwd.d.ts +8 -0
- package/dist/src/core/helpers/resolveFromCwd.d.ts.map +1 -0
- package/dist/src/core/helpers/resolveFromCwd.js +9 -0
- package/dist/src/core/helpers/resolveFromCwd.js.map +1 -0
- package/dist/src/core/parseEnv.d.ts +11 -0
- package/dist/src/core/parseEnv.d.ts.map +1 -0
- package/dist/src/core/parseEnv.js +26 -0
- package/dist/src/core/parseEnv.js.map +1 -0
- package/dist/src/core/patterns.d.ts +32 -0
- package/dist/src/core/patterns.d.ts.map +1 -0
- package/dist/src/core/patterns.js +69 -0
- package/dist/src/core/patterns.js.map +1 -0
- package/dist/src/core/scanFile.d.ts +10 -0
- package/dist/src/core/scanFile.d.ts.map +1 -0
- package/dist/src/core/scanFile.js +41 -0
- package/dist/src/core/scanFile.js.map +1 -0
- package/dist/src/core/scanJsonOutput.d.ts +11 -0
- package/dist/src/core/scanJsonOutput.d.ts.map +1 -0
- package/dist/src/core/scanJsonOutput.js +56 -0
- package/dist/src/core/scanJsonOutput.js.map +1 -0
- package/dist/src/core/secretDetectors.d.ts.map +1 -1
- package/dist/src/core/secretDetectors.js +33 -15
- package/dist/src/core/secretDetectors.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/services/codeBaseScanner.d.ts +1 -40
- package/dist/src/services/codeBaseScanner.d.ts.map +1 -1
- package/dist/src/services/codeBaseScanner.js +4 -315
- package/dist/src/services/codeBaseScanner.js.map +1 -1
- package/dist/src/services/ensureFilesOrPrompt.d.ts +19 -0
- package/dist/src/services/ensureFilesOrPrompt.d.ts.map +1 -0
- package/dist/src/services/ensureFilesOrPrompt.js +74 -0
- package/dist/src/services/ensureFilesOrPrompt.js.map +1 -0
- package/dist/src/services/fileWalker.d.ts +62 -0
- package/dist/src/services/fileWalker.d.ts.map +1 -0
- package/dist/src/services/fileWalker.js +238 -0
- package/dist/src/services/fileWalker.js.map +1 -0
- package/dist/src/services/scanOutputToConsole.d.ts +12 -0
- package/dist/src/services/scanOutputToConsole.d.ts.map +1 -0
- package/dist/src/services/scanOutputToConsole.js +166 -0
- package/dist/src/services/scanOutputToConsole.js.map +1 -0
- package/dist/types/scanUsage.d.ts +43 -0
- package/dist/types/scanUsage.d.ts.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fsSync from 'fs';
|
|
4
|
+
import { DEFAULT_INCLUDE_EXTENSIONS, DEFAULT_EXCLUDE_PATTERNS, } from '../core/patterns.js';
|
|
5
|
+
/**
|
|
6
|
+
* Recursively finds all files in the given directory matching the include patterns,
|
|
7
|
+
* while excluding files and directories that match the exclude patterns.
|
|
8
|
+
* @param rootDir The root directory to start searching from.
|
|
9
|
+
* @param opts Options for include, exclude patterns and files override.
|
|
10
|
+
* @returns A promise that resolves to an array of file paths.
|
|
11
|
+
*/
|
|
12
|
+
export async function findFiles(rootDir, opts) {
|
|
13
|
+
// If --files provided, keep existing replacement behavior
|
|
14
|
+
if (opts.files && opts.files.length > 0) {
|
|
15
|
+
return findFilesByPatterns(rootDir, opts.files);
|
|
16
|
+
}
|
|
17
|
+
const defaultPatterns = getDefaultPatterns();
|
|
18
|
+
const rawInclude = opts.include.length > 0
|
|
19
|
+
? [...defaultPatterns, ...opts.include]
|
|
20
|
+
: defaultPatterns;
|
|
21
|
+
const includePatterns = rawInclude.flatMap(expandBraceSets);
|
|
22
|
+
const files = [];
|
|
23
|
+
const walked = new Set();
|
|
24
|
+
// Compute additional roots for include patterns that point outside cwd or are absolute
|
|
25
|
+
const extraRoots = new Set();
|
|
26
|
+
for (const p of includePatterns) {
|
|
27
|
+
const hasParentEscape = p.includes('..') || path.isAbsolute(p);
|
|
28
|
+
if (!hasParentEscape)
|
|
29
|
+
continue;
|
|
30
|
+
const dir = getPatternBaseDir(rootDir, p);
|
|
31
|
+
if (dir && !dir.startsWith(rootDir)) {
|
|
32
|
+
extraRoots.add(dir);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function walk(startDir) {
|
|
36
|
+
// prevent duplicate subtree walks
|
|
37
|
+
const key = path.resolve(startDir);
|
|
38
|
+
if (walked.has(key))
|
|
39
|
+
return;
|
|
40
|
+
walked.add(key);
|
|
41
|
+
let entries;
|
|
42
|
+
try {
|
|
43
|
+
entries = await fs.readdir(startDir, { withFileTypes: true });
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const fullPath = path.join(startDir, entry.name);
|
|
50
|
+
const relativeToRoot = path.relative(rootDir, fullPath);
|
|
51
|
+
// Exclude checks should use path relative to *rootDir* (keeps existing semantics)
|
|
52
|
+
if (shouldExclude(entry.name, relativeToRoot, [
|
|
53
|
+
...DEFAULT_EXCLUDE_PATTERNS,
|
|
54
|
+
...opts.exclude,
|
|
55
|
+
])) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
await walk(fullPath);
|
|
60
|
+
}
|
|
61
|
+
else if (entry.isFile() &&
|
|
62
|
+
shouldInclude(entry.name, relativeToRoot, includePatterns)) {
|
|
63
|
+
files.push(fullPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Walk root first (current behavior)
|
|
68
|
+
await walk(rootDir);
|
|
69
|
+
// Walk any extra roots (e.g., ../../packages/…)
|
|
70
|
+
for (const r of extraRoots) {
|
|
71
|
+
await walk(r);
|
|
72
|
+
}
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Expands brace sets in a glob pattern.
|
|
77
|
+
* @param pattern - The glob pattern to expand.
|
|
78
|
+
* @returns An array of expanded glob patterns.
|
|
79
|
+
*/
|
|
80
|
+
export function expandBraceSets(pattern) {
|
|
81
|
+
// Single-level brace expansion: **/*.{js,ts,svelte} -> [**/*.js, **/*.ts, **/*.svelte]
|
|
82
|
+
const m = pattern.match(/\{([^}]+)\}/);
|
|
83
|
+
if (!m || m[1] === undefined)
|
|
84
|
+
return [pattern];
|
|
85
|
+
const variants = m[1]
|
|
86
|
+
.split(',')
|
|
87
|
+
.map((p) => p.trim())
|
|
88
|
+
.filter(Boolean);
|
|
89
|
+
const prefix = pattern.slice(0, m.index);
|
|
90
|
+
const suffix = pattern.slice(m.index + m[0].length);
|
|
91
|
+
return variants.flatMap((v) => expandBraceSets(`${prefix}${v}${suffix}`));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Gets the base directory for a glob pattern.
|
|
95
|
+
* @param rootDir The root directory to resolve against.
|
|
96
|
+
* @param pattern The glob pattern to analyze.
|
|
97
|
+
* @returns The base directory for the pattern, or null if not found.
|
|
98
|
+
*/
|
|
99
|
+
export function getPatternBaseDir(rootDir, pattern) {
|
|
100
|
+
// Stop at first glob char — DO NOT include '/' here
|
|
101
|
+
const idx = pattern.search(/[*?\[\]{}]/); // <— removed '/'
|
|
102
|
+
const raw = idx === -1 ? pattern : pattern.slice(0, idx);
|
|
103
|
+
const base = path.isAbsolute(raw) ? raw : path.resolve(rootDir, raw);
|
|
104
|
+
try {
|
|
105
|
+
const st = fsSync.statSync(base);
|
|
106
|
+
if (st.isDirectory())
|
|
107
|
+
return base;
|
|
108
|
+
if (st.isFile())
|
|
109
|
+
return path.dirname(base);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
const dir = path.dirname(base);
|
|
113
|
+
try {
|
|
114
|
+
const st2 = fsSync.statSync(dir);
|
|
115
|
+
if (st2.isDirectory())
|
|
116
|
+
return dir;
|
|
117
|
+
}
|
|
118
|
+
catch { }
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Find files using the --files patterns (complete replacement mode)
|
|
124
|
+
* @param rootDir The root directory to search within.
|
|
125
|
+
* @param patterns The glob patterns to match files against.
|
|
126
|
+
* @returns A promise that resolves to an array of matching file paths.
|
|
127
|
+
*/
|
|
128
|
+
export async function findFilesByPatterns(rootDir, patterns) {
|
|
129
|
+
const expanded = patterns.flatMap(expandBraceSets);
|
|
130
|
+
const files = [];
|
|
131
|
+
async function walk(currentDir) {
|
|
132
|
+
let entries;
|
|
133
|
+
try {
|
|
134
|
+
entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
141
|
+
const relativePath = path.relative(rootDir, fullPath);
|
|
142
|
+
if (entry.isDirectory()) {
|
|
143
|
+
await walk(fullPath);
|
|
144
|
+
}
|
|
145
|
+
else if (entry.isFile() &&
|
|
146
|
+
shouldInclude(entry.name, relativePath, expanded)) {
|
|
147
|
+
files.push(fullPath);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
await walk(rootDir);
|
|
152
|
+
return files;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Generate default patterns from extensions
|
|
156
|
+
* @returns An array of default glob patterns.
|
|
157
|
+
*/
|
|
158
|
+
export function getDefaultPatterns() {
|
|
159
|
+
return DEFAULT_INCLUDE_EXTENSIONS.map((ext) => `**/*${ext}`);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if a file should be included based on its name, path, and include patterns.
|
|
163
|
+
* @param fileName The name of the file.
|
|
164
|
+
* @param relativePath The relative path of the file.
|
|
165
|
+
* @param patterns The include patterns to match against.
|
|
166
|
+
* @returns True if the file should be included, false otherwise.
|
|
167
|
+
*/
|
|
168
|
+
export function shouldInclude(fileName, relativePath, patterns) {
|
|
169
|
+
// If no include patterns specified, use default extensions
|
|
170
|
+
if (!patterns.length) {
|
|
171
|
+
return DEFAULT_INCLUDE_EXTENSIONS.some((ext) => fileName.endsWith(ext));
|
|
172
|
+
}
|
|
173
|
+
return patterns.some((pattern) => {
|
|
174
|
+
if (pattern.startsWith('**')) {
|
|
175
|
+
// Handle **/*.ext patterns
|
|
176
|
+
const ext = pattern.substring(pattern.lastIndexOf('.'));
|
|
177
|
+
return fileName.endsWith(ext);
|
|
178
|
+
}
|
|
179
|
+
else if (pattern.includes('*')) {
|
|
180
|
+
// Simple glob pattern matching
|
|
181
|
+
return matchesGlobPattern(relativePath, pattern);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Exact match or extension
|
|
185
|
+
return relativePath.endsWith(pattern) || fileName.endsWith(pattern);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Checks if a file should be excluded based on its name, path, and exclude patterns.
|
|
191
|
+
* @param fileName The name of the file.
|
|
192
|
+
* @param relativePath The relative path of the file.
|
|
193
|
+
* @param patterns The exclude patterns to match against.
|
|
194
|
+
* @returns True if the file should be excluded, false otherwise.
|
|
195
|
+
*/
|
|
196
|
+
export function shouldExclude(fileName, relativePath, patterns) {
|
|
197
|
+
// Check if filename or any part of the path should be excluded
|
|
198
|
+
return patterns.some((pattern) => {
|
|
199
|
+
// Direct name match (like 'node_modules')
|
|
200
|
+
if (fileName === pattern)
|
|
201
|
+
return true;
|
|
202
|
+
// Path contains pattern
|
|
203
|
+
if (relativePath.includes(pattern))
|
|
204
|
+
return true;
|
|
205
|
+
// Pattern matching for extensions and wildcards
|
|
206
|
+
if (pattern.includes('*')) {
|
|
207
|
+
return matchesGlobPattern(relativePath, pattern);
|
|
208
|
+
}
|
|
209
|
+
// Special case for test files
|
|
210
|
+
if (pattern.includes('.test.') && fileName.includes('.test.'))
|
|
211
|
+
return true;
|
|
212
|
+
if (pattern.includes('.spec.') && fileName.includes('.spec.'))
|
|
213
|
+
return true;
|
|
214
|
+
return false;
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Checks if a file path matches a glob pattern.
|
|
219
|
+
* A glob pattern is a string that may contain special characters like '*', '**', and '?' to represent wildcards and variable parts of the path.
|
|
220
|
+
* @param filePath The path of the file to check.
|
|
221
|
+
* @param pattern The glob pattern to match against.
|
|
222
|
+
* @returns True if the file path matches the pattern, false otherwise.
|
|
223
|
+
*/
|
|
224
|
+
export function matchesGlobPattern(filePath, pattern) {
|
|
225
|
+
const hasSep = /[\/\\]/.test(pattern);
|
|
226
|
+
const subject = hasSep ? filePath : path.basename(filePath);
|
|
227
|
+
const normalized = subject.replace(/\\/g, '/');
|
|
228
|
+
let normalizedPattern = pattern.replace(/\\/g, '/');
|
|
229
|
+
let regexPattern = normalizedPattern
|
|
230
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
231
|
+
.replace(/\*\*/g, '___DOUBLESTAR___')
|
|
232
|
+
.replace(/\*/g, '[^/]*')
|
|
233
|
+
.replace(/___DOUBLESTAR___/g, '.*')
|
|
234
|
+
.replace(/\?/g, '[^/]');
|
|
235
|
+
const re = new RegExp(`^${regexPattern}$`, 'i');
|
|
236
|
+
return re.test(normalized);
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=fileWalker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileWalker.js","sourceRoot":"","sources":["../../../src/services/fileWalker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ScanUsageOptions, ScanResult } from '../config/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Outputs the scan results to the console.
|
|
4
|
+
* @param scanResult - The result of the scan.
|
|
5
|
+
* @param opts - The scan options.
|
|
6
|
+
* @param comparedAgainst - The file being compared against.
|
|
7
|
+
* @returns An object indicating whether to exit with an error.
|
|
8
|
+
*/
|
|
9
|
+
export declare function outputToConsole(scanResult: ScanResult, opts: ScanUsageOptions, comparedAgainst: string): {
|
|
10
|
+
exitWithError: boolean;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=scanOutputToConsole.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanOutputToConsole.d.ts","sourceRoot":"","sources":["../../../src/services/scanOutputToConsole.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EAGX,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,gBAAgB,EACtB,eAAe,EAAE,MAAM,GACtB;IAAE,aAAa,EAAE,OAAO,CAAA;CAAE,CA2P5B"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { warnIfEnvNotIgnored, isEnvIgnoredByGit } from './git.js';
|
|
3
|
+
/**
|
|
4
|
+
* Outputs the scan results to the console.
|
|
5
|
+
* @param scanResult - The result of the scan.
|
|
6
|
+
* @param opts - The scan options.
|
|
7
|
+
* @param comparedAgainst - The file being compared against.
|
|
8
|
+
* @returns An object indicating whether to exit with an error.
|
|
9
|
+
*/
|
|
10
|
+
export function outputToConsole(scanResult, opts, comparedAgainst) {
|
|
11
|
+
let exitWithError = false;
|
|
12
|
+
// Show what we're comparing against
|
|
13
|
+
if (comparedAgainst) {
|
|
14
|
+
console.log(chalk.magenta(`📋 Comparing codebase usage against: ${comparedAgainst}`));
|
|
15
|
+
console.log();
|
|
16
|
+
}
|
|
17
|
+
// Show stats if requested
|
|
18
|
+
if (opts.showStats) {
|
|
19
|
+
console.log(chalk.magenta('📊 Scan Statistics:'));
|
|
20
|
+
console.log(chalk.magenta.dim(` Files scanned: ${scanResult.stats.filesScanned}`));
|
|
21
|
+
console.log(chalk.magenta.dim(` Total usages found: ${scanResult.stats.totalUsages}`));
|
|
22
|
+
console.log(chalk.magenta.dim(` Unique variables: ${scanResult.stats.uniqueVariables}`));
|
|
23
|
+
console.log();
|
|
24
|
+
}
|
|
25
|
+
// Always show found variables when not comparing or when no missing variables
|
|
26
|
+
if (scanResult.stats.uniqueVariables > 0) {
|
|
27
|
+
console.log(chalk.blue(`🌐 Found ${scanResult.stats.uniqueVariables} unique environment variables in use`));
|
|
28
|
+
console.log();
|
|
29
|
+
// List all variables found (if any)
|
|
30
|
+
if (scanResult.stats.uniqueVariables > 0) {
|
|
31
|
+
// Group by variable to get unique list
|
|
32
|
+
const variableUsages = scanResult.used.reduce((acc, usage) => {
|
|
33
|
+
if (!acc[usage.variable]) {
|
|
34
|
+
acc[usage.variable] = [];
|
|
35
|
+
}
|
|
36
|
+
acc[usage.variable].push(usage);
|
|
37
|
+
return acc;
|
|
38
|
+
}, {});
|
|
39
|
+
// Display each unique variable
|
|
40
|
+
for (const [variable, usages] of Object.entries(variableUsages)) {
|
|
41
|
+
console.log(chalk.blue(` ${variable}`));
|
|
42
|
+
// Show usage details if stats are enabled
|
|
43
|
+
if (opts.showStats) {
|
|
44
|
+
const displayUsages = usages.slice(0, 2);
|
|
45
|
+
displayUsages.forEach((usage) => {
|
|
46
|
+
console.log(chalk.blue.dim(` Used in: ${usage.file}:${usage.line} (${usage.pattern})`));
|
|
47
|
+
});
|
|
48
|
+
if (usages.length > 2) {
|
|
49
|
+
console.log(chalk.gray(` ... and ${usages.length - 2} more locations`));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
console.log();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Missing variables (used in code but not in env file)
|
|
57
|
+
if (scanResult.missing.length > 0) {
|
|
58
|
+
exitWithError = true;
|
|
59
|
+
const fileType = comparedAgainst || 'environment file';
|
|
60
|
+
console.log(chalk.red(`❌ Missing in ${fileType}:`));
|
|
61
|
+
const grouped = scanResult.missing.reduce((acc, variable) => {
|
|
62
|
+
const usages = scanResult.used.filter((u) => u.variable === variable);
|
|
63
|
+
acc[variable] = usages;
|
|
64
|
+
return acc;
|
|
65
|
+
}, {});
|
|
66
|
+
for (const [variable, usages] of Object.entries(grouped)) {
|
|
67
|
+
console.log(chalk.red(` - ${variable}`));
|
|
68
|
+
// Show first few usages
|
|
69
|
+
const maxShow = 3;
|
|
70
|
+
usages.slice(0, maxShow).forEach((usage) => {
|
|
71
|
+
console.log(chalk.red.dim(` Used in: ${usage.file}:${usage.line} (${usage.pattern})`));
|
|
72
|
+
});
|
|
73
|
+
if (usages.length > maxShow) {
|
|
74
|
+
console.log(chalk.gray(` ... and ${usages.length - maxShow} more locations`));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
console.log();
|
|
78
|
+
// CI mode specific message
|
|
79
|
+
if (opts.isCiMode) {
|
|
80
|
+
console.log(chalk.red(`💥 Found ${scanResult.missing.length} missing environment variable(s).`));
|
|
81
|
+
console.log(chalk.red(` Add these variables to ${comparedAgainst || 'your environment file'} to fix this error.`));
|
|
82
|
+
console.log();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Unused variables (in env file but not used in code)
|
|
86
|
+
if (opts.showUnused && scanResult.unused.length > 0) {
|
|
87
|
+
const fileType = comparedAgainst || 'environment file';
|
|
88
|
+
console.log(chalk.yellow(`⚠️ Unused in codebase (defined in ${fileType}):`));
|
|
89
|
+
scanResult.unused.forEach((variable) => {
|
|
90
|
+
console.log(chalk.yellow(` - ${variable}`));
|
|
91
|
+
});
|
|
92
|
+
console.log();
|
|
93
|
+
}
|
|
94
|
+
// Show duplicates if found - NOW AFTER UNUSED VARIABLES
|
|
95
|
+
if (scanResult.duplicates?.env && scanResult.duplicates.env.length > 0) {
|
|
96
|
+
console.log(chalk.yellow(`⚠️ Duplicate keys in ${comparedAgainst} (last occurrence wins):`));
|
|
97
|
+
scanResult.duplicates.env.forEach(({ key, count }) => console.log(chalk.yellow(` - ${key} (${count} occurrences)`)));
|
|
98
|
+
console.log();
|
|
99
|
+
}
|
|
100
|
+
if (scanResult.duplicates?.example &&
|
|
101
|
+
scanResult.duplicates.example.length > 0) {
|
|
102
|
+
console.log(chalk.yellow('⚠️ Duplicate keys in example file (last occurrence wins):'));
|
|
103
|
+
scanResult.duplicates.example.forEach(({ key, count }) => console.log(chalk.yellow(` - ${key} (${count} occurrences)`)));
|
|
104
|
+
console.log();
|
|
105
|
+
}
|
|
106
|
+
if (scanResult.secrets && scanResult.secrets.length > 0) {
|
|
107
|
+
console.log(chalk.yellow('🔒 Potential secrets detected in codebase:'));
|
|
108
|
+
const byFile = new Map();
|
|
109
|
+
for (const f of scanResult.secrets) {
|
|
110
|
+
if (!byFile.has(f.file))
|
|
111
|
+
byFile.set(f.file, []);
|
|
112
|
+
byFile.get(f.file).push(f);
|
|
113
|
+
}
|
|
114
|
+
for (const [file, findings] of byFile) {
|
|
115
|
+
console.log(chalk.bold(` ${file}`));
|
|
116
|
+
for (const f of findings) {
|
|
117
|
+
console.log(chalk.yellow(` - Line ${f.line}: ${f.message}\n ${chalk.dim(f.snippet)}`));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
console.log();
|
|
121
|
+
}
|
|
122
|
+
// Success message for env file comparison
|
|
123
|
+
if (comparedAgainst &&
|
|
124
|
+
scanResult.missing.length === 0 &&
|
|
125
|
+
scanResult.secrets.length > 0 &&
|
|
126
|
+
scanResult.used.length > 0) {
|
|
127
|
+
console.log(chalk.green(`✅ All used environment variables are defined in ${comparedAgainst}`));
|
|
128
|
+
if (opts.showUnused && scanResult.unused.length === 0) {
|
|
129
|
+
console.log(chalk.green('✅ No unused environment variables found'));
|
|
130
|
+
}
|
|
131
|
+
console.log();
|
|
132
|
+
}
|
|
133
|
+
let envNotIgnored = false;
|
|
134
|
+
if (!opts.json) {
|
|
135
|
+
warnIfEnvNotIgnored({ cwd: opts.cwd, envFile: '.env' });
|
|
136
|
+
const ignored = isEnvIgnoredByGit({ cwd: opts.cwd, envFile: '.env' });
|
|
137
|
+
if (ignored === false || ignored === null) {
|
|
138
|
+
envNotIgnored = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (opts.strict) {
|
|
142
|
+
const hasWarnings = scanResult.unused.length > 0 ||
|
|
143
|
+
(scanResult.duplicates?.env?.length ?? 0) > 0 ||
|
|
144
|
+
(scanResult.duplicates?.example?.length ?? 0) > 0 ||
|
|
145
|
+
(scanResult.secrets?.length ?? 0) > 0 ||
|
|
146
|
+
envNotIgnored;
|
|
147
|
+
if (hasWarnings) {
|
|
148
|
+
exitWithError = true;
|
|
149
|
+
const warnings = [];
|
|
150
|
+
if (scanResult.unused.length > 0)
|
|
151
|
+
warnings.push('unused variables');
|
|
152
|
+
if ((scanResult.duplicates?.env?.length ?? 0) > 0)
|
|
153
|
+
warnings.push('duplicate keys in env');
|
|
154
|
+
if ((scanResult.duplicates?.example?.length ?? 0) > 0)
|
|
155
|
+
warnings.push('duplicate keys in example');
|
|
156
|
+
if ((scanResult.secrets?.length ?? 0) > 0)
|
|
157
|
+
warnings.push('potential secrets');
|
|
158
|
+
if (envNotIgnored)
|
|
159
|
+
warnings.push('.env not ignored by git');
|
|
160
|
+
console.log(chalk.red(`💥 Strict mode: Error on warnings → ${warnings.join(', ')}`));
|
|
161
|
+
console.log();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return { exitWithError };
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=scanOutputToConsole.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanOutputToConsole.js","sourceRoot":"","sources":["../../../src/services/scanOutputToConsole.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type SecretFinding } from '../src/core/secretDetectors';
|
|
2
|
+
/**
|
|
3
|
+
* Represents a single usage of an environment variable in the codebase.
|
|
4
|
+
*/
|
|
5
|
+
export interface EnvUsage {
|
|
6
|
+
variable: string;
|
|
7
|
+
file: string;
|
|
8
|
+
line: number;
|
|
9
|
+
column: number;
|
|
10
|
+
pattern: 'process.env' | 'import.meta.env' | 'sveltekit' | 'deno' | 'next' | 'nuxt' | 'php';
|
|
11
|
+
context: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ScanOptions {
|
|
14
|
+
cwd: string;
|
|
15
|
+
include: string[];
|
|
16
|
+
exclude: string[];
|
|
17
|
+
ignore: string[];
|
|
18
|
+
ignoreRegex: RegExp[];
|
|
19
|
+
files?: string[];
|
|
20
|
+
secrets?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ScanResult {
|
|
23
|
+
used: EnvUsage[];
|
|
24
|
+
missing: string[];
|
|
25
|
+
unused: string[];
|
|
26
|
+
stats: {
|
|
27
|
+
filesScanned: number;
|
|
28
|
+
totalUsages: number;
|
|
29
|
+
uniqueVariables: number;
|
|
30
|
+
};
|
|
31
|
+
secrets: SecretFinding[];
|
|
32
|
+
duplicates: {
|
|
33
|
+
env?: Array<{
|
|
34
|
+
key: string;
|
|
35
|
+
count: number;
|
|
36
|
+
}>;
|
|
37
|
+
example?: Array<{
|
|
38
|
+
key: string;
|
|
39
|
+
count: number;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=scanUsage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanUsage.d.ts","sourceRoot":"","sources":["../../types/scanUsage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EACH,aAAa,GACb,iBAAiB,GACjB,WAAW,GACX,MAAM,GACN,MAAM,GACN,MAAM,GACN,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,EAAE;QACV,GAAG,CAAC,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACjD,CAAC;CACH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotenv-diff",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Scan your codebase to find environment variables in use.",
|
|
6
6
|
"bin": {
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"node": ">=20.0.0"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"chalk": "5.
|
|
60
|
+
"chalk": "5.6.2",
|
|
61
61
|
"commander": "^14.0.0",
|
|
62
62
|
"prompts": "^2.4.2"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@types/node": "^
|
|
65
|
+
"@types/node": "^24.5.2",
|
|
66
66
|
"@typescript-eslint/eslint-plugin": "^8.39.0",
|
|
67
67
|
"@typescript-eslint/parser": "^8.39.0",
|
|
68
68
|
"eslint": "^9.32.0",
|