Skip to content

Commit d67b60c

Browse files
authored
Merge pull request #104 from Chrilleweb/cmn/dev
Codebase + readme update + security.md
2 parents e8d4bab + 6829011 commit d67b60c

File tree

9 files changed

+66
-34
lines changed

9 files changed

+66
-34
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Scan your codebase to detect which environment variables are used in your code.
77
Optimized for SvelteKit and Next.js. </br>
88
Also works well in modern JavaScript/TypeScript projects and frameworks like Node.js, Nuxt, and Vue — or any other setup where you want reliable .env file comparison / scanning.
99

10+
![CI](https://github.com/chrilleweb/dotenv-diff/actions/workflows/ci.yml/badge.svg)
1011
[![npm version](https://img.shields.io/npm/v/dotenv-diff.svg)](https://www.npmjs.com/package/dotenv-diff)
1112
[![npm downloads](https://img.shields.io/npm/dt/dotenv-diff.svg)](https://www.npmjs.com/package/dotenv-diff)
1213

@@ -347,12 +348,19 @@ This makes it quick to set up environment files without manually copying or rety
347348
`dotenv-diff` will warn you if your `.env` file is **not** ignored by Git.
348349
This helps prevent accidentally committing sensitive environment variables.
349350

351+
## Exit codes
352+
353+
- `0` → No errors (warnings may be present unless `--strict`)
354+
- `1` → Errors found (or warnings when using `--strict`)
355+
350356
## 🤝 Contributing
351357

352-
Contributions are welcome! Feel free to open an issue or a pull request.
358+
Issues, feature requests and pull requests are welcome.
359+
360+
If you plan a larger change, please open an issue first to discuss scope and approach.
353361

354362
## License
355363

356-
MIT
364+
Licensed under the [MIT](LICENSE) license.
357365

358366
### Created by [chrilleweb](https://github.com/chrilleweb)

SECURITY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Security Policy
2+
3+
If you discover a security vulnerability, please report it responsibly.
4+
5+
Send us an email to [email protected] and **don't** open a public issue.

package.json

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "dotenv-diff",
33
"version": "2.3.11",
44
"type": "module",
5-
"description": "Scan your codebase to find environment variables in use.",
5+
"description": "Detects environment variable issues, usage, and potential security risks.",
66
"bin": {
77
"dotenv-diff": "dist/bin/dotenv-diff.js"
88
},
@@ -40,11 +40,17 @@
4040
"dotenv",
4141
"env",
4242
"dotenv-diff",
43+
"env-check",
44+
"env-validate",
45+
"env-scan",
4346
"cli",
44-
"compare",
45-
"environment variables",
46-
"dotenv validator",
47-
"scan codebase"
47+
"config",
48+
"security",
49+
"ci",
50+
"monorepo",
51+
"sveltekit",
52+
"nextjs",
53+
"node"
4854
],
4955
"repository": {
5056
"type": "git",

src/cli/run.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import fs from 'fs';
33
import path from 'path';
44
import { normalizeOptions } from '../config/options.js';
55
import { discoverEnvFiles } from '../services/envDiscovery.js';
6-
import { pairWithExample } from '../services/envPairing.js';
6+
import { pairWithExample } from '../core/envPairing.js';
77
import { ensureFilesOrPrompt } from '../services/ensureFilesOrPrompt.js';
88
import { compareMany } from '../commands/compare.js';
99
import {

src/core/determineComparisonFile.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,26 @@ import path from 'path';
33
import { type ScanUsageOptions } from '../config/types.js';
44
import { resolveFromCwd } from './helpers/resolveFromCwd.js';
55

6+
type ComparisonFile = {
7+
path: string;
8+
name: string;
9+
};
10+
11+
const DEFAULT_ENV_FILES = [
12+
'.env',
13+
'.env.example',
14+
'.env.local',
15+
'.env.production',
16+
] as const;
17+
618
/**
719
* Determines which file to use for comparison based on provided options
820
* @param {ScanUsageOptions} opts - Scan configuration options
9-
* @returns {Object|null} - The comparison file information or undefined if not found
21+
* @returns Comparison file info with absolute path and basename, or undefined if not found
1022
*/
1123
export function determineComparisonFile(
1224
opts: ScanUsageOptions,
13-
): { path: string; name: string } | undefined {
25+
): ComparisonFile | undefined {
1426
// Priority: explicit flags first, then auto-discovery
1527

1628
if (opts.examplePath) {
@@ -28,8 +40,7 @@ export function determineComparisonFile(
2840
}
2941

3042
// Auto-discovery: look for common env files relative to cwd
31-
const candidates = ['.env', '.env.example', '.env.local', '.env.production'];
32-
for (const candidate of candidates) {
43+
for (const candidate of DEFAULT_ENV_FILES) {
3344
const fullPath = path.resolve(opts.cwd, candidate);
3445
if (fs.existsSync(fullPath)) {
3546
return { path: fullPath, name: candidate };
Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
import fs from 'fs';
22
import path from 'path';
3-
import type { Discovery } from './envDiscovery.js';
3+
import type { Discovery } from '../services/envDiscovery.js';
4+
import type { FilePair } from '../config/types.js';
45

56
/**
67
* Pairs each environment file with its corresponding example file.
78
* @param d - The discovery object containing environment and example file information.
89
* @returns An array of objects containing the environment name, path, and example path.
910
*/
10-
export function pairWithExample(
11-
d: Discovery,
12-
): Array<{ envName: string; envPath: string; examplePath: string }> {
13-
const pairs: Array<{
14-
envName: string;
15-
envPath: string;
16-
examplePath: string;
17-
}> = [];
11+
export function pairWithExample(d: Discovery): Array<FilePair> {
12+
const pairs: Array<FilePair> = [];
1813
const list = d.envFiles.length > 0 ? d.envFiles : [d.primaryEnv];
1914

2015
for (const envName of list) {

src/services/duplicates.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fs from 'fs';
2+
import type { Duplicate } from '../config/types.js';
23

34
/**
45
* Scan a .env-like file for duplicate keys.
@@ -9,9 +10,7 @@ import fs from 'fs';
910
* @param filePath - Path to the .env file to scan
1011
* @returns An array of objects representing duplicate keys and their counts.
1112
*/
12-
export function findDuplicateKeys(
13-
filePath: string,
14-
): Array<{ key: string; count: number }> {
13+
export function findDuplicateKeys(filePath: string): Array<Duplicate> {
1514
if (!fs.existsSync(filePath)) return [];
1615

1716
const raw = fs.readFileSync(filePath, 'utf8');
@@ -32,7 +31,7 @@ export function findDuplicateKeys(
3231
counts.set(key, (counts.get(key) ?? 0) + 1);
3332
}
3433

35-
const duplicates: Array<{ key: string; count: number }> = [];
34+
const duplicates: Array<Duplicate> = [];
3635
for (const [key, count] of counts) {
3736
if (count > 1) duplicates.push({ key, count });
3837
}

src/services/fileWalker.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import {
66
DEFAULT_EXCLUDE_PATTERNS,
77
} from '../core/patterns.js';
88

9+
interface FindFilesOptions {
10+
include?: string[];
11+
exclude?: string[];
12+
files?: string[];
13+
}
14+
915
/**
1016
* Recursively finds all files in the given directory matching the include patterns,
1117
* while excluding files and directories that match the exclude patterns.
@@ -15,7 +21,7 @@ import {
1521
*/
1622
export async function findFiles(
1723
rootDir: string,
18-
opts: { include: string[]; exclude: string[]; files?: string[] },
24+
opts: FindFilesOptions,
1925
): Promise<string[]> {
2026
// If --files provided, keep existing replacement behavior
2127
if (opts.files && opts.files.length > 0) {
@@ -24,7 +30,7 @@ export async function findFiles(
2430

2531
const defaultPatterns = getDefaultPatterns();
2632
const rawInclude =
27-
opts.include.length > 0
33+
opts.include && opts.include.length > 0
2834
? [...defaultPatterns, ...opts.include]
2935
: defaultPatterns;
3036
const includePatterns = rawInclude.flatMap(expandBraceSets);
@@ -69,7 +75,7 @@ export async function findFiles(
6975
if (
7076
shouldExclude(entry.name, relativeToRoot, [
7177
...DEFAULT_EXCLUDE_PATTERNS,
72-
...opts.exclude,
78+
...(opts.exclude ?? []),
7379
])
7480
) {
7581
continue;

src/services/scanOutputToConsole.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ import { printHealthScore } from '../ui/scan/printHealthScore.js';
2424
import { printExpireWarnings } from '../ui/scan/printExpireWarnings.js';
2525
import { printInconsistentNamingWarning } from '../ui/scan/printInconsistentNamingWarning.js';
2626

27+
interface FixContext {
28+
fixApplied: boolean;
29+
removedDuplicates: string[];
30+
addedEnv: string[];
31+
gitignoreUpdated: boolean;
32+
}
33+
2734
/**
2835
* Outputs the scan results to the console.
2936
* @param scanResult - The result of the scan.
@@ -35,12 +42,7 @@ export function outputToConsole(
3542
scanResult: ScanResult,
3643
opts: ScanUsageOptions,
3744
comparedAgainst: string,
38-
fixContext?: {
39-
fixApplied: boolean;
40-
removedDuplicates: string[];
41-
addedEnv: string[];
42-
gitignoreUpdated: boolean;
43-
},
45+
fixContext?: FixContext,
4446
): { exitWithError: boolean } {
4547
let exitWithError = false;
4648

0 commit comments

Comments
 (0)