dotenv-diff 1.6.3 → 1.6.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/README.md +21 -0
- package/dist/src/cli/program.js +4 -1
- package/dist/src/cli/run.js +13 -1
- package/dist/src/commands/compare.d.ts +4 -26
- package/dist/src/commands/compare.js +89 -34
- package/dist/src/config/options.d.ts +1 -20
- package/dist/src/config/options.js +33 -0
- package/dist/src/config/types.d.ts +53 -0
- package/dist/src/config/types.js +8 -0
- package/dist/src/core/filterIgnoredKeys.d.ts +1 -0
- package/dist/src/core/filterIgnoredKeys.js +3 -0
- package/package.json +20 -5
package/README.md
CHANGED
|
@@ -43,6 +43,27 @@ When using the `--check-values` option, the tool will also compare the actual va
|
|
|
43
43
|
|
|
44
44
|
`dotenv-diff` warns when a `.env*` file contains the same key multiple times. The last occurrence wins. Suppress these warnings with `--allow-duplicates`.
|
|
45
45
|
|
|
46
|
+
## Only show specific categories
|
|
47
|
+
|
|
48
|
+
Use the `--only` flag to restrict the comparison to specific categories. For example:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
dotenv-diff --only missing,extra
|
|
52
|
+
```
|
|
53
|
+
This will only show missing and extra keys, ignoring empty, mismatched, duplicate keys and so on.
|
|
54
|
+
|
|
55
|
+
## Ignore specific keys
|
|
56
|
+
|
|
57
|
+
Exclude certain keys from the comparison using `--ignore` for exact names or `--ignore-regex` for patterns:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
dotenv-diff --ignore API_KEY,SESSION_ID
|
|
61
|
+
dotenv-diff --ignore-regex '^SECRET_'
|
|
62
|
+
dotenv-diff --ignore API_KEY --ignore-regex '^SECRET_'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Ignored keys are removed from all warnings and do not affect the exit code.
|
|
66
|
+
|
|
46
67
|
## Output format in JSON
|
|
47
68
|
|
|
48
69
|
You can output the results in JSON format using the `--json` option:
|
package/dist/src/cli/program.js
CHANGED
|
@@ -9,5 +9,8 @@ export function createProgram() {
|
|
|
9
9
|
.option('--env <file>', 'Path to a specific .env file')
|
|
10
10
|
.option('--example <file>', 'Path to a specific .env.example file')
|
|
11
11
|
.option('--allow-duplicates', 'Do not warn about duplicate keys in .env* files')
|
|
12
|
-
.option('--
|
|
12
|
+
.option('--ignore <keys>', 'Comma-separated list of keys to ignore')
|
|
13
|
+
.option('--ignore-regex <pattern>', 'Regex pattern to ignore matching keys')
|
|
14
|
+
.option('--json', 'Output results in JSON format')
|
|
15
|
+
.option('--only <list>', 'Comma-separated categories to only run (missing,extra,empty,mismatch,duplicate,gitignore)');
|
|
13
16
|
}
|
package/dist/src/cli/run.js
CHANGED
|
@@ -24,11 +24,20 @@ export async function run(program) {
|
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
const report = [];
|
|
27
|
-
const { exitWithError } = await compareMany([
|
|
27
|
+
const { exitWithError } = await compareMany([
|
|
28
|
+
{
|
|
29
|
+
envName: path.basename(opts.envFlag),
|
|
30
|
+
envPath: opts.envFlag,
|
|
31
|
+
examplePath: opts.exampleFlag,
|
|
32
|
+
},
|
|
33
|
+
], {
|
|
28
34
|
checkValues: opts.checkValues,
|
|
29
35
|
cwd: opts.cwd,
|
|
30
36
|
allowDuplicates: opts.allowDuplicates,
|
|
31
37
|
json: opts.json,
|
|
38
|
+
ignore: opts.ignore,
|
|
39
|
+
ignoreRegex: opts.ignoreRegex,
|
|
40
|
+
only: opts.only,
|
|
32
41
|
collect: (e) => report.push(e),
|
|
33
42
|
});
|
|
34
43
|
if (opts.json) {
|
|
@@ -65,6 +74,9 @@ export async function run(program) {
|
|
|
65
74
|
cwd: opts.cwd,
|
|
66
75
|
allowDuplicates: opts.allowDuplicates,
|
|
67
76
|
json: opts.json,
|
|
77
|
+
ignore: opts.ignore,
|
|
78
|
+
ignoreRegex: opts.ignoreRegex,
|
|
79
|
+
only: opts.only,
|
|
68
80
|
collect: (e) => report.push(e),
|
|
69
81
|
});
|
|
70
82
|
if (opts.json) {
|
|
@@ -1,29 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
env: string;
|
|
3
|
-
example: string;
|
|
4
|
-
skipped?: {
|
|
5
|
-
reason: string;
|
|
6
|
-
};
|
|
7
|
-
duplicates?: {
|
|
8
|
-
env?: Array<{
|
|
9
|
-
key: string;
|
|
10
|
-
count: number;
|
|
11
|
-
}>;
|
|
12
|
-
example?: Array<{
|
|
13
|
-
key: string;
|
|
14
|
-
count: number;
|
|
15
|
-
}>;
|
|
16
|
-
};
|
|
17
|
-
missing?: string[];
|
|
18
|
-
extra?: string[];
|
|
19
|
-
empty?: string[];
|
|
20
|
-
valueMismatches?: Array<{
|
|
21
|
-
key: string;
|
|
22
|
-
expected: string;
|
|
23
|
-
actual: string;
|
|
24
|
-
}>;
|
|
25
|
-
ok?: boolean;
|
|
26
|
-
};
|
|
1
|
+
import type { Category, CompareJsonEntry } from '../config/types.js';
|
|
27
2
|
export declare function compareMany(pairs: Array<{
|
|
28
3
|
envName: string;
|
|
29
4
|
envPath: string;
|
|
@@ -33,7 +8,10 @@ export declare function compareMany(pairs: Array<{
|
|
|
33
8
|
cwd: string;
|
|
34
9
|
allowDuplicates?: boolean;
|
|
35
10
|
json?: boolean;
|
|
11
|
+
ignore: string[];
|
|
12
|
+
ignoreRegex: RegExp[];
|
|
36
13
|
collect?: (entry: CompareJsonEntry) => void;
|
|
14
|
+
only?: Category[];
|
|
37
15
|
}): Promise<{
|
|
38
16
|
exitWithError: boolean;
|
|
39
17
|
}>;
|
|
@@ -5,8 +5,21 @@ import { parseEnvFile } from '../lib/parseEnv.js';
|
|
|
5
5
|
import { diffEnv } from '../lib/diffEnv.js';
|
|
6
6
|
import { warnIfEnvNotIgnored } from '../services/git.js';
|
|
7
7
|
import { findDuplicateKeys } from '../services/duplicates.js';
|
|
8
|
+
import { filterIgnoredKeys } from '../core/filterIgnoredKeys.js';
|
|
8
9
|
export async function compareMany(pairs, opts) {
|
|
9
10
|
let exitWithError = false;
|
|
11
|
+
const onlySet = opts.only?.length
|
|
12
|
+
? new Set(opts.only)
|
|
13
|
+
: undefined;
|
|
14
|
+
const run = (cat) => !onlySet || onlySet.has(cat);
|
|
15
|
+
const totals = {
|
|
16
|
+
missing: 0,
|
|
17
|
+
extra: 0,
|
|
18
|
+
empty: 0,
|
|
19
|
+
mismatch: 0,
|
|
20
|
+
duplicate: 0,
|
|
21
|
+
gitignore: 0,
|
|
22
|
+
};
|
|
10
23
|
for (const { envName, envPath, examplePath } of pairs) {
|
|
11
24
|
const exampleName = path.basename(examplePath);
|
|
12
25
|
const entry = { env: envName, example: exampleName };
|
|
@@ -24,18 +37,29 @@ export async function compareMany(pairs, opts) {
|
|
|
24
37
|
console.log(chalk.bold(`🔍 Comparing ${envName} ↔ ${exampleName}...`));
|
|
25
38
|
}
|
|
26
39
|
// Git ignore hint (only when not JSON)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
let gitignoreUnsafe = false;
|
|
41
|
+
if (run('gitignore')) {
|
|
42
|
+
warnIfEnvNotIgnored({
|
|
43
|
+
cwd: opts.cwd,
|
|
44
|
+
envFile: envName,
|
|
45
|
+
log: (msg) => {
|
|
46
|
+
gitignoreUnsafe = true;
|
|
47
|
+
if (!opts.json)
|
|
48
|
+
console.log(msg.replace(/^/gm, ' '));
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// still call to keep previous hints? No—masked by --only.
|
|
54
|
+
}
|
|
55
|
+
// Duplicate detection (skip entirely if --only excludes it)
|
|
56
|
+
let dupsEnv = [];
|
|
57
|
+
let dupsEx = [];
|
|
58
|
+
if (!opts.allowDuplicates && run('duplicate')) {
|
|
59
|
+
dupsEnv = findDuplicateKeys(envPath).filter(({ key }) => !opts.ignore.includes(key) &&
|
|
60
|
+
!opts.ignoreRegex.some((rx) => rx.test(key)));
|
|
61
|
+
dupsEx = findDuplicateKeys(examplePath).filter(({ key }) => !opts.ignore.includes(key) &&
|
|
62
|
+
!opts.ignoreRegex.some((rx) => rx.test(key)));
|
|
39
63
|
if (dupsEnv.length || dupsEx.length) {
|
|
40
64
|
entry.duplicates = {};
|
|
41
65
|
}
|
|
@@ -55,16 +79,29 @@ export async function compareMany(pairs, opts) {
|
|
|
55
79
|
}
|
|
56
80
|
}
|
|
57
81
|
// Diff + empty
|
|
58
|
-
const
|
|
59
|
-
const
|
|
82
|
+
const currentFull = parseEnvFile(envPath);
|
|
83
|
+
const exampleFull = parseEnvFile(examplePath);
|
|
84
|
+
const currentKeys = filterIgnoredKeys(Object.keys(currentFull), opts.ignore, opts.ignoreRegex);
|
|
85
|
+
const exampleKeys = filterIgnoredKeys(Object.keys(exampleFull), opts.ignore, opts.ignoreRegex);
|
|
86
|
+
const current = Object.fromEntries(currentKeys.map((k) => [k, currentFull[k]]));
|
|
87
|
+
const example = Object.fromEntries(exampleKeys.map((k) => [k, exampleFull[k]]));
|
|
60
88
|
const diff = diffEnv(current, example, opts.checkValues);
|
|
61
89
|
const emptyKeys = Object.entries(current)
|
|
62
90
|
.filter(([, v]) => (v ?? '').trim() === '')
|
|
63
91
|
.map(([k]) => k);
|
|
64
|
-
const
|
|
65
|
-
diff.
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
const filtered = {
|
|
93
|
+
missing: run('missing') ? diff.missing : [],
|
|
94
|
+
extra: run('extra') ? diff.extra : [],
|
|
95
|
+
empty: run('empty') ? emptyKeys : [],
|
|
96
|
+
mismatches: run('mismatch') && opts.checkValues ? diff.valueMismatches : [],
|
|
97
|
+
duplicatesEnv: run('duplicate') ? dupsEnv : [],
|
|
98
|
+
duplicatesEx: run('duplicate') ? dupsEx : [],
|
|
99
|
+
gitignoreUnsafe: run('gitignore') ? gitignoreUnsafe : false,
|
|
100
|
+
};
|
|
101
|
+
const allOk = filtered.missing.length === 0 &&
|
|
102
|
+
filtered.extra.length === 0 &&
|
|
103
|
+
filtered.empty.length === 0 &&
|
|
104
|
+
filtered.mismatches.length === 0;
|
|
68
105
|
if (allOk) {
|
|
69
106
|
entry.ok = true;
|
|
70
107
|
if (!opts.json) {
|
|
@@ -74,33 +111,51 @@ export async function compareMany(pairs, opts) {
|
|
|
74
111
|
opts.collect?.(entry);
|
|
75
112
|
continue;
|
|
76
113
|
}
|
|
77
|
-
if (
|
|
78
|
-
entry.missing =
|
|
114
|
+
if (filtered.missing.length) {
|
|
115
|
+
entry.missing = filtered.missing;
|
|
116
|
+
exitWithError = true;
|
|
117
|
+
totals.missing += filtered.missing.length;
|
|
118
|
+
}
|
|
119
|
+
if (filtered.extra.length) {
|
|
120
|
+
entry.extra = filtered.extra;
|
|
121
|
+
exitWithError = true;
|
|
122
|
+
totals.extra += filtered.extra.length;
|
|
123
|
+
}
|
|
124
|
+
if (filtered.empty.length) {
|
|
125
|
+
entry.empty = filtered.empty;
|
|
79
126
|
exitWithError = true;
|
|
127
|
+
totals.empty += filtered.empty.length;
|
|
80
128
|
}
|
|
81
|
-
if (
|
|
82
|
-
entry.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
129
|
+
if (filtered.mismatches.length) {
|
|
130
|
+
entry.valueMismatches = filtered.mismatches;
|
|
131
|
+
totals.mismatch += filtered.mismatches.length;
|
|
132
|
+
exitWithError = true;
|
|
133
|
+
}
|
|
134
|
+
if (filtered.duplicatesEnv.length || filtered.duplicatesEx.length) {
|
|
135
|
+
totals.duplicate +=
|
|
136
|
+
filtered.duplicatesEnv.length + filtered.duplicatesEx.length;
|
|
137
|
+
exitWithError = true;
|
|
138
|
+
}
|
|
139
|
+
if (filtered.gitignoreUnsafe) {
|
|
140
|
+
totals.gitignore += 1;
|
|
141
|
+
exitWithError = true;
|
|
87
142
|
}
|
|
88
143
|
if (!opts.json) {
|
|
89
|
-
if (
|
|
144
|
+
if (filtered.missing.length) {
|
|
90
145
|
console.log(chalk.red(' ❌ Missing keys:'));
|
|
91
|
-
|
|
146
|
+
filtered.missing.forEach((key) => console.log(chalk.red(` - ${key}`)));
|
|
92
147
|
}
|
|
93
|
-
if (
|
|
148
|
+
if (filtered.extra.length) {
|
|
94
149
|
console.log(chalk.yellow(' ⚠️ Extra keys (not in example):'));
|
|
95
|
-
|
|
150
|
+
filtered.extra.forEach((key) => console.log(chalk.yellow(` - ${key}`)));
|
|
96
151
|
}
|
|
97
|
-
if (
|
|
152
|
+
if (filtered.empty.length) {
|
|
98
153
|
console.log(chalk.yellow(' ⚠️ Empty values:'));
|
|
99
|
-
|
|
154
|
+
filtered.empty.forEach((key) => console.log(chalk.yellow(` - ${key}`)));
|
|
100
155
|
}
|
|
101
|
-
if (
|
|
156
|
+
if (filtered.mismatches.length) {
|
|
102
157
|
console.log(chalk.yellow(' ⚠️ Value mismatches:'));
|
|
103
|
-
|
|
158
|
+
filtered.mismatches.forEach(({ key, expected, actual }) => console.log(chalk.yellow(` - ${key}: expected '${expected}', but got '${actual}'`)));
|
|
104
159
|
}
|
|
105
160
|
console.log();
|
|
106
161
|
}
|
|
@@ -1,21 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
checkValues: boolean;
|
|
3
|
-
isCiMode: boolean;
|
|
4
|
-
isYesMode: boolean;
|
|
5
|
-
allowDuplicates: boolean;
|
|
6
|
-
json: boolean;
|
|
7
|
-
envFlag: string | null;
|
|
8
|
-
exampleFlag: string | null;
|
|
9
|
-
cwd: string;
|
|
10
|
-
};
|
|
11
|
-
type RawOptions = {
|
|
12
|
-
checkValues?: boolean;
|
|
13
|
-
ci?: boolean;
|
|
14
|
-
yes?: boolean;
|
|
15
|
-
allowDuplicates?: boolean;
|
|
16
|
-
json?: boolean;
|
|
17
|
-
env?: string;
|
|
18
|
-
example?: string;
|
|
19
|
-
};
|
|
1
|
+
import { Options, RawOptions } from './types.js';
|
|
20
2
|
export declare function normalizeOptions(raw: RawOptions): Options;
|
|
21
|
-
export {};
|
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { ALLOWED_CATEGORIES } from './types.js';
|
|
4
|
+
function parseList(val) {
|
|
5
|
+
const arr = Array.isArray(val) ? val : val ? [val] : [];
|
|
6
|
+
return arr
|
|
7
|
+
.flatMap((s) => String(s).split(','))
|
|
8
|
+
.map((s) => s.trim())
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
}
|
|
11
|
+
function parseCategories(val, flagName = '') {
|
|
12
|
+
const raw = parseList(val);
|
|
13
|
+
const bad = raw.filter((c) => !ALLOWED_CATEGORIES.includes(c));
|
|
14
|
+
if (bad.length) {
|
|
15
|
+
console.error(chalk.red(`❌ Error: invalid ${flagName} value(s): ${bad.join(', ')}. Allowed: ${ALLOWED_CATEGORIES.join(', ')}`));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
return raw;
|
|
19
|
+
}
|
|
3
20
|
export function normalizeOptions(raw) {
|
|
4
21
|
const checkValues = raw.checkValues ?? false;
|
|
5
22
|
const isCiMode = Boolean(raw.ci);
|
|
6
23
|
const isYesMode = Boolean(raw.yes);
|
|
7
24
|
const allowDuplicates = Boolean(raw.allowDuplicates);
|
|
8
25
|
const json = Boolean(raw.json);
|
|
26
|
+
const onlyParsed = parseCategories(raw.only, '--only');
|
|
27
|
+
const only = onlyParsed.length ? onlyParsed : undefined;
|
|
28
|
+
const ignore = parseList(raw.ignore);
|
|
29
|
+
const ignoreRegex = [];
|
|
30
|
+
for (const pattern of parseList(raw.ignoreRegex)) {
|
|
31
|
+
try {
|
|
32
|
+
ignoreRegex.push(new RegExp(pattern));
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
console.error(chalk.red(`❌ Error: invalid --ignore-regex pattern: ${pattern}`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
9
39
|
if (isCiMode && isYesMode) {
|
|
10
40
|
console.log(chalk.yellow('⚠️ Both --ci and --yes provided; proceeding with --yes.'));
|
|
11
41
|
}
|
|
@@ -20,6 +50,9 @@ export function normalizeOptions(raw) {
|
|
|
20
50
|
json,
|
|
21
51
|
envFlag,
|
|
22
52
|
exampleFlag,
|
|
53
|
+
ignore,
|
|
54
|
+
ignoreRegex,
|
|
23
55
|
cwd,
|
|
56
|
+
only,
|
|
24
57
|
};
|
|
25
58
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export declare const ALLOWED_CATEGORIES: readonly ["missing", "extra", "empty", "mismatch", "duplicate", "gitignore"];
|
|
2
|
+
export type Category = (typeof ALLOWED_CATEGORIES)[number];
|
|
3
|
+
export type Options = {
|
|
4
|
+
checkValues: boolean;
|
|
5
|
+
isCiMode: boolean;
|
|
6
|
+
isYesMode: boolean;
|
|
7
|
+
allowDuplicates: boolean;
|
|
8
|
+
json: boolean;
|
|
9
|
+
envFlag: string | null;
|
|
10
|
+
exampleFlag: string | null;
|
|
11
|
+
ignore: string[];
|
|
12
|
+
ignoreRegex: RegExp[];
|
|
13
|
+
cwd: string;
|
|
14
|
+
only?: Category[];
|
|
15
|
+
};
|
|
16
|
+
export type RawOptions = {
|
|
17
|
+
checkValues?: boolean;
|
|
18
|
+
ci?: boolean;
|
|
19
|
+
yes?: boolean;
|
|
20
|
+
allowDuplicates?: boolean;
|
|
21
|
+
json?: boolean;
|
|
22
|
+
env?: string;
|
|
23
|
+
example?: string;
|
|
24
|
+
ignore?: string | string[];
|
|
25
|
+
ignoreRegex?: string | string[];
|
|
26
|
+
only?: string | string[];
|
|
27
|
+
};
|
|
28
|
+
export type CompareJsonEntry = {
|
|
29
|
+
env: string;
|
|
30
|
+
example: string;
|
|
31
|
+
skipped?: {
|
|
32
|
+
reason: string;
|
|
33
|
+
};
|
|
34
|
+
duplicates?: {
|
|
35
|
+
env?: Array<{
|
|
36
|
+
key: string;
|
|
37
|
+
count: number;
|
|
38
|
+
}>;
|
|
39
|
+
example?: Array<{
|
|
40
|
+
key: string;
|
|
41
|
+
count: number;
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
44
|
+
missing?: string[];
|
|
45
|
+
extra?: string[];
|
|
46
|
+
empty?: string[];
|
|
47
|
+
valueMismatches?: Array<{
|
|
48
|
+
key: string;
|
|
49
|
+
expected: string;
|
|
50
|
+
actual: string;
|
|
51
|
+
}>;
|
|
52
|
+
ok?: boolean;
|
|
53
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function filterIgnoredKeys(keys: string[], ignore: string[], ignoreRegex: RegExp[]): string[];
|
package/package.json
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotenv-diff",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "A
|
|
5
|
+
"description": "A CLI tool to find differences between .env and .env.example / .env.* files.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"dotenv-diff": "dist/bin/dotenv-diff.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
11
18
|
"files": [
|
|
12
19
|
"dist/",
|
|
13
20
|
"README.md",
|
|
14
21
|
"LICENSE"
|
|
15
22
|
],
|
|
23
|
+
"sideEffects": false,
|
|
16
24
|
"scripts": {
|
|
17
25
|
"build": "tsc",
|
|
18
26
|
"dev": "vitest --watch",
|
|
19
|
-
"test": "vitest",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:unit": "vitest run test/unit",
|
|
29
|
+
"test:e2e": "vitest run test/e2e",
|
|
20
30
|
"lint": "eslint ./src --ext .ts",
|
|
21
31
|
"format": "prettier --write \"src/**/*.ts\" \"src/*.ts\"",
|
|
22
|
-
"start": "node dist/bin/dotenv-diff.js"
|
|
32
|
+
"start": "node dist/bin/dotenv-diff.js",
|
|
33
|
+
"prepublishOnly": "npm run lint && npm test && npm run build"
|
|
23
34
|
},
|
|
24
35
|
"author": "Chrilleweb",
|
|
25
36
|
"license": "MIT",
|
|
@@ -36,8 +47,12 @@
|
|
|
36
47
|
"type": "git",
|
|
37
48
|
"url": "https://github.com/Chrilleweb/dotenv-diff.git"
|
|
38
49
|
},
|
|
50
|
+
"homepage": "https://github.com/Chrilleweb/dotenv-diff#readme",
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/Chrilleweb/dotenv-diff/issues"
|
|
53
|
+
},
|
|
39
54
|
"engines": {
|
|
40
|
-
"node": ">=
|
|
55
|
+
"node": ">=20.0.0"
|
|
41
56
|
},
|
|
42
57
|
"dependencies": {
|
|
43
58
|
"chalk": "^5.4.1",
|