@danielszlaski/envguard 0.1.0

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.
Files changed (75) hide show
  1. package/.envguardrc.example.json +17 -0
  2. package/LICENSE +21 -0
  3. package/README.md +320 -0
  4. package/dist/analyzer/envAnalyzer.d.ts +8 -0
  5. package/dist/analyzer/envAnalyzer.d.ts.map +1 -0
  6. package/dist/analyzer/envAnalyzer.js +112 -0
  7. package/dist/analyzer/envAnalyzer.js.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +52 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/check.d.ts +5 -0
  13. package/dist/commands/check.d.ts.map +1 -0
  14. package/dist/commands/check.js +9 -0
  15. package/dist/commands/check.js.map +1 -0
  16. package/dist/commands/fix.d.ts +4 -0
  17. package/dist/commands/fix.d.ts.map +1 -0
  18. package/dist/commands/fix.js +115 -0
  19. package/dist/commands/fix.js.map +1 -0
  20. package/dist/commands/scan.d.ts +9 -0
  21. package/dist/commands/scan.d.ts.map +1 -0
  22. package/dist/commands/scan.js +274 -0
  23. package/dist/commands/scan.js.map +1 -0
  24. package/dist/config/configLoader.d.ts +35 -0
  25. package/dist/config/configLoader.d.ts.map +1 -0
  26. package/dist/config/configLoader.js +141 -0
  27. package/dist/config/configLoader.js.map +1 -0
  28. package/dist/constants/knownEnvVars.d.ts +38 -0
  29. package/dist/constants/knownEnvVars.d.ts.map +1 -0
  30. package/dist/constants/knownEnvVars.js +111 -0
  31. package/dist/constants/knownEnvVars.js.map +1 -0
  32. package/dist/index.d.ts +5 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +25 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/parser/envParser.d.ts +13 -0
  37. package/dist/parser/envParser.d.ts.map +1 -0
  38. package/dist/parser/envParser.js +126 -0
  39. package/dist/parser/envParser.js.map +1 -0
  40. package/dist/parser/serverlessParser.d.ts +27 -0
  41. package/dist/parser/serverlessParser.d.ts.map +1 -0
  42. package/dist/parser/serverlessParser.js +162 -0
  43. package/dist/parser/serverlessParser.js.map +1 -0
  44. package/dist/scanner/codeScanner.d.ts +13 -0
  45. package/dist/scanner/codeScanner.d.ts.map +1 -0
  46. package/dist/scanner/codeScanner.js +157 -0
  47. package/dist/scanner/codeScanner.js.map +1 -0
  48. package/dist/types.d.ts +24 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +3 -0
  51. package/dist/types.js.map +1 -0
  52. package/package.json +40 -0
  53. package/src/analyzer/envAnalyzer.ts +133 -0
  54. package/src/cli.ts +54 -0
  55. package/src/commands/check.ts +6 -0
  56. package/src/commands/fix.ts +104 -0
  57. package/src/commands/scan.ts +289 -0
  58. package/src/config/configLoader.ts +131 -0
  59. package/src/constants/knownEnvVars.ts +108 -0
  60. package/src/index.ts +4 -0
  61. package/src/parser/envParser.ts +114 -0
  62. package/src/parser/serverlessParser.ts +146 -0
  63. package/src/scanner/codeScanner.ts +148 -0
  64. package/src/types.ts +26 -0
  65. package/test-project/.envguardrc.json +7 -0
  66. package/test-project/src/lambda1/.env.example +11 -0
  67. package/test-project/src/lambda1/handler.js +14 -0
  68. package/test-project/src/lambda2/.env.example +9 -0
  69. package/test-project/src/lambda2/handler.js +11 -0
  70. package/test-project/src/lambda2/handler2.js +13 -0
  71. package/test-project/src/lambda2/serverless.yml +50 -0
  72. package/test-project/src/payment/.env.example +23 -0
  73. package/test-project/src/payment/payment.js +14 -0
  74. package/test-project/src/payment/server.ts +11 -0
  75. package/tsconfig.json +19 -0
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.fixCommand = fixCommand;
40
+ const path = __importStar(require("path"));
41
+ const fs = __importStar(require("fs"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const codeScanner_1 = require("../scanner/codeScanner");
44
+ const envParser_1 = require("../parser/envParser");
45
+ const envAnalyzer_1 = require("../analyzer/envAnalyzer");
46
+ async function fixCommand() {
47
+ const rootDir = process.cwd();
48
+ console.log(chalk_1.default.blue('🔧 Generating .env.example files...\n'));
49
+ // Step 1: Find all .env files
50
+ const scanner = new codeScanner_1.CodeScanner(rootDir);
51
+ const envFiles = await scanner.findEnvFiles();
52
+ if (envFiles.length === 0) {
53
+ console.log(chalk_1.default.yellow('⚠️ No .env files found in the project\n'));
54
+ return { success: false };
55
+ }
56
+ console.log(chalk_1.default.green(`✓ Found ${envFiles.length} .env file(s)\n`));
57
+ const parser = new envParser_1.EnvParser();
58
+ const analyzer = new envAnalyzer_1.EnvAnalyzer();
59
+ let totalVars = 0;
60
+ // Step 2: Process each .env file
61
+ for (const envFilePath of envFiles) {
62
+ const envDir = path.dirname(envFilePath);
63
+ const relativePath = path.relative(rootDir, envDir);
64
+ const displayPath = relativePath || '.';
65
+ console.log(chalk_1.default.cyan(`📂 Processing ${displayPath}/`));
66
+ // Step 3: Scan code files in this directory and subdirectories
67
+ const usedVars = await scanDirectoryForVars(rootDir, envDir, scanner);
68
+ if (usedVars.size === 0) {
69
+ console.log(chalk_1.default.gray(` No environment variables found in code\n`));
70
+ continue;
71
+ }
72
+ console.log(chalk_1.default.green(` ✓ Found ${usedVars.size} variable(s) used in this directory\n`));
73
+ // Step 4: Parse existing .env.example to preserve comments
74
+ const examplePath = path.join(envDir, '.env.example');
75
+ const existingEntries = parser.parse(examplePath);
76
+ // Step 5: Generate new .env.example content
77
+ const newContent = analyzer.generateExampleContent(usedVars, existingEntries);
78
+ // Step 6: Write to .env.example
79
+ fs.writeFileSync(examplePath, newContent, 'utf-8');
80
+ console.log(chalk_1.default.green(` ✅ Generated ${path.relative(rootDir, examplePath)}\n`));
81
+ totalVars += usedVars.size;
82
+ // Step 7: Show summary for this directory
83
+ const definedVars = parser.parse(envFilePath);
84
+ const missingFromEnv = Array.from(usedVars.keys()).filter(v => !definedVars.has(v));
85
+ if (missingFromEnv.length > 0) {
86
+ console.log(chalk_1.default.yellow(` ⚠️ Missing from .env: ${missingFromEnv.join(', ')}\n`));
87
+ }
88
+ }
89
+ console.log(chalk_1.default.green(`🎉 Done! Generated ${envFiles.length} .env.example file(s) with ${totalVars} total variables\n`));
90
+ return { success: true };
91
+ }
92
+ async function scanDirectoryForVars(rootDir, targetDir, scanner) {
93
+ const envVars = new Map();
94
+ const { glob } = require('glob');
95
+ // Find all code files in this directory and subdirectories
96
+ const relativeDir = path.relative(rootDir, targetDir);
97
+ const pattern = relativeDir ? `${relativeDir}/**/*.{js,ts,jsx,tsx,mjs,cjs}` : '**/*.{js,ts,jsx,tsx,mjs,cjs}';
98
+ const files = await glob(pattern, {
99
+ cwd: rootDir,
100
+ ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**'],
101
+ absolute: true,
102
+ });
103
+ for (const file of files) {
104
+ const vars = await scanner.scanFile(file);
105
+ for (const varName of vars) {
106
+ const relativePath = path.relative(rootDir, file);
107
+ if (!envVars.has(varName)) {
108
+ envVars.set(varName, []);
109
+ }
110
+ envVars.get(varName).push(relativePath);
111
+ }
112
+ }
113
+ return envVars;
114
+ }
115
+ //# sourceMappingURL=fix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.js","sourceRoot":"","sources":["../../src/commands/fix.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Issue } from '../types';
2
+ export declare function scanCommand(options: {
3
+ ci?: boolean;
4
+ strict?: boolean;
5
+ }): Promise<{
6
+ success: boolean;
7
+ issues: Issue[];
8
+ }>;
9
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAIjC,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE;;;GAqN5E"}
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.scanCommand = scanCommand;
40
+ const path = __importStar(require("path"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const glob_1 = require("glob");
43
+ const codeScanner_1 = require("../scanner/codeScanner");
44
+ const envParser_1 = require("../parser/envParser");
45
+ const serverlessParser_1 = require("../parser/serverlessParser");
46
+ const envAnalyzer_1 = require("../analyzer/envAnalyzer");
47
+ const knownEnvVars_1 = require("../constants/knownEnvVars");
48
+ const configLoader_1 = require("../config/configLoader");
49
+ async function scanCommand(options) {
50
+ const rootDir = process.cwd();
51
+ // Load configuration
52
+ const config = configLoader_1.ConfigLoader.loadConfig(rootDir);
53
+ // CLI options override config file
54
+ const strictMode = options.strict !== undefined ? options.strict : config.strict;
55
+ console.log(chalk_1.default.blue('🔍 Scanning codebase for environment variables...\n'));
56
+ // Step 1: Find all .env files and serverless.yml files
57
+ const scanner = new codeScanner_1.CodeScanner(rootDir);
58
+ const envFiles = await scanner.findEnvFiles();
59
+ const serverlessFiles = await scanner.findServerlessFiles();
60
+ if (envFiles.length === 0 && serverlessFiles.length === 0) {
61
+ console.log(chalk_1.default.yellow('⚠️ No .env or serverless.yml files found in the project\n'));
62
+ return { success: false, issues: [] };
63
+ }
64
+ console.log(chalk_1.default.green(`✓ Found ${envFiles.length} .env file(s) and ${serverlessFiles.length} serverless.yml file(s)\n`));
65
+ const parser = new envParser_1.EnvParser();
66
+ const serverlessParser = new serverlessParser_1.ServerlessParser();
67
+ const analyzer = new envAnalyzer_1.EnvAnalyzer();
68
+ const allIssues = [];
69
+ // Step 2a: Process serverless.yml files independently
70
+ for (const serverlessFilePath of serverlessFiles) {
71
+ const serverlessDir = path.dirname(serverlessFilePath);
72
+ const relativePath = path.relative(rootDir, serverlessFilePath);
73
+ console.log(chalk_1.default.cyan(`📂 Checking ${relativePath}\n`));
74
+ // Parse serverless.yml
75
+ const serverlessVars = serverlessParser.parse(serverlessFilePath);
76
+ console.log(chalk_1.default.gray(` Found ${serverlessVars.size} variable(s) in serverless.yml`));
77
+ // Scan code files in this directory to see what's actually used
78
+ const usedVars = await scanDirectoryForCodeVars(rootDir, serverlessDir, scanner);
79
+ console.log(chalk_1.default.gray(` Found ${usedVars.size} variable(s) used in code\n`));
80
+ // Check for unused variables in serverless.yml
81
+ const unusedServerlessVars = [];
82
+ for (const [varName] of serverlessVars.entries()) {
83
+ if (!usedVars.has(varName)) {
84
+ // In non-strict mode, skip known runtime variables and custom ignore vars from "unused" warnings
85
+ const isIgnored = (0, knownEnvVars_1.isKnownRuntimeVar)(varName) || configLoader_1.ConfigLoader.shouldIgnoreVar(varName, config);
86
+ if (strictMode || !isIgnored) {
87
+ unusedServerlessVars.push(varName);
88
+ }
89
+ }
90
+ }
91
+ // Check for variables used in code but not defined in serverless.yml
92
+ const missingFromServerless = [];
93
+ const skippedRuntimeVars = [];
94
+ for (const [varName, locations] of usedVars.entries()) {
95
+ if (!serverlessVars.has(varName)) {
96
+ // In non-strict mode, skip known runtime variables and custom ignore vars
97
+ const isCustomIgnored = configLoader_1.ConfigLoader.shouldIgnoreVar(varName, config);
98
+ const isRuntimeVar = (0, knownEnvVars_1.isKnownRuntimeVar)(varName);
99
+ if (!strictMode && (isRuntimeVar || isCustomIgnored)) {
100
+ const category = isCustomIgnored ? 'Custom (from config)' : (0, knownEnvVars_1.getRuntimeVarCategory)(varName);
101
+ if (category) {
102
+ skippedRuntimeVars.push({ varName, category });
103
+ }
104
+ }
105
+ else {
106
+ missingFromServerless.push({ varName, locations });
107
+ }
108
+ }
109
+ }
110
+ if (unusedServerlessVars.length > 0) {
111
+ console.log(chalk_1.default.yellow.bold(' ⚠️ Unused variables in serverless.yml:'));
112
+ unusedServerlessVars.forEach((varName, index) => {
113
+ console.log(chalk_1.default.yellow(` ${index + 1}. ${varName}`));
114
+ allIssues.push({
115
+ type: 'unused',
116
+ varName,
117
+ details: `Defined in serverless.yml but never used in code`,
118
+ });
119
+ });
120
+ console.log();
121
+ }
122
+ if (missingFromServerless.length > 0) {
123
+ console.log(chalk_1.default.red.bold(' 🚨 Missing from serverless.yml:'));
124
+ missingFromServerless.forEach((item, index) => {
125
+ console.log(chalk_1.default.red(` ${index + 1}. ${item.varName}`));
126
+ if (item.locations && item.locations.length > 0) {
127
+ console.log(chalk_1.default.gray(` Used in: ${item.locations.slice(0, 2).join(', ')}`));
128
+ }
129
+ allIssues.push({
130
+ type: 'missing',
131
+ varName: item.varName,
132
+ details: `Used in code but not defined in serverless.yml`,
133
+ locations: item.locations,
134
+ });
135
+ });
136
+ console.log();
137
+ }
138
+ if (unusedServerlessVars.length === 0 && missingFromServerless.length === 0) {
139
+ console.log(chalk_1.default.green(' ✅ No issues in this serverless.yml\n'));
140
+ }
141
+ // Show skipped runtime variables in non-strict mode
142
+ if (!strictMode && skippedRuntimeVars.length > 0) {
143
+ console.log(chalk_1.default.gray(' ℹ️ Skipped known runtime variables (use --strict to show):'));
144
+ // Group by category
145
+ const grouped = new Map();
146
+ for (const { varName, category } of skippedRuntimeVars) {
147
+ if (!grouped.has(category)) {
148
+ grouped.set(category, []);
149
+ }
150
+ grouped.get(category).push(varName);
151
+ }
152
+ for (const [category, vars] of grouped.entries()) {
153
+ console.log(chalk_1.default.gray(` ${category}: ${vars.join(', ')}`));
154
+ }
155
+ console.log();
156
+ }
157
+ }
158
+ // Step 2b: Process each .env file (including directories that also have serverless.yml)
159
+ for (const envFilePath of envFiles) {
160
+ const envDir = path.dirname(envFilePath);
161
+ const relativePath = path.relative(rootDir, envDir);
162
+ const displayPath = relativePath || '.';
163
+ console.log(chalk_1.default.cyan(`📂 Checking ${displayPath}/\n`));
164
+ // Step 3: Scan code files in this directory and subdirectories
165
+ const usedVars = await scanDirectoryForVars(rootDir, envDir, scanner);
166
+ console.log(chalk_1.default.gray(` Found ${usedVars.size} variable(s) used in this scope`));
167
+ // Step 4: Parse .env file
168
+ const definedVars = parser.parse(envFilePath);
169
+ console.log(chalk_1.default.gray(` Found ${definedVars.size} variable(s) in .env`));
170
+ // Step 5: Parse .env.example
171
+ const examplePath = path.join(envDir, '.env.example');
172
+ const exampleVars = parser.parseExample(examplePath);
173
+ console.log(chalk_1.default.gray(` Found ${exampleVars.size} variable(s) in .env.example\n`));
174
+ // Step 6: Analyze and find issues
175
+ const result = analyzer.analyze(usedVars, definedVars, exampleVars);
176
+ if (result.issues.length > 0) {
177
+ // Group issues by type
178
+ const missingIssues = result.issues.filter(i => i.type === 'missing');
179
+ const unusedIssues = result.issues.filter(i => i.type === 'unused');
180
+ const undocumentedIssues = result.issues.filter(i => i.type === 'undocumented');
181
+ if (missingIssues.length > 0) {
182
+ console.log(chalk_1.default.red.bold(' 🚨 Missing from .env:'));
183
+ missingIssues.forEach((issue, index) => {
184
+ console.log(chalk_1.default.red(` ${index + 1}. ${issue.varName}`));
185
+ if (issue.locations && issue.locations.length > 0) {
186
+ console.log(chalk_1.default.gray(` Used in: ${issue.locations.slice(0, 2).join(', ')}`));
187
+ }
188
+ });
189
+ console.log();
190
+ }
191
+ if (unusedIssues.length > 0) {
192
+ console.log(chalk_1.default.yellow.bold(' ⚠️ Unused variables:'));
193
+ unusedIssues.forEach((issue, index) => {
194
+ console.log(chalk_1.default.yellow(` ${index + 1}. ${issue.varName}`));
195
+ });
196
+ console.log();
197
+ }
198
+ if (undocumentedIssues.length > 0) {
199
+ console.log(chalk_1.default.blue.bold(' 📝 Missing from .env.example:'));
200
+ undocumentedIssues.forEach((issue, index) => {
201
+ console.log(chalk_1.default.blue(` ${index + 1}. ${issue.varName}`));
202
+ });
203
+ console.log();
204
+ }
205
+ allIssues.push(...result.issues);
206
+ }
207
+ else {
208
+ console.log(chalk_1.default.green(' ✅ No issues in this directory\n'));
209
+ }
210
+ }
211
+ // Display summary
212
+ console.log(chalk_1.default.bold('─'.repeat(50)));
213
+ if (allIssues.length === 0) {
214
+ console.log(chalk_1.default.green('\n✅ No issues found! All environment variables are in sync.\n'));
215
+ return { success: true, issues: [] };
216
+ }
217
+ console.log(chalk_1.default.yellow(`\n⚠️ Total: ${allIssues.length} issue(s) across ${envFiles.length} location(s)\n`));
218
+ // Suggest fix
219
+ if (!options.ci) {
220
+ console.log(chalk_1.default.cyan('💡 Run `envguard fix` to auto-generate .env.example files\n'));
221
+ }
222
+ // Exit with error code in CI mode
223
+ if (options.ci) {
224
+ console.log(chalk_1.default.red('❌ Issues found. Exiting with error code 1.\n'));
225
+ process.exit(1);
226
+ }
227
+ return { success: false, issues: allIssues };
228
+ }
229
+ async function scanDirectoryForVars(rootDir, targetDir, scanner) {
230
+ const envVars = new Map();
231
+ // Find all code files in this directory and subdirectories
232
+ const relativeDir = path.relative(rootDir, targetDir);
233
+ const pattern = relativeDir ? `${relativeDir}/**/*.{js,ts,jsx,tsx,mjs,cjs}` : '**/*.{js,ts,jsx,tsx,mjs,cjs}';
234
+ const files = await (0, glob_1.glob)(pattern, {
235
+ cwd: rootDir,
236
+ ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**'],
237
+ absolute: true,
238
+ });
239
+ for (const file of files) {
240
+ const vars = await scanner.scanFile(file);
241
+ for (const varName of vars) {
242
+ const relativePath = path.relative(rootDir, file);
243
+ if (!envVars.has(varName)) {
244
+ envVars.set(varName, []);
245
+ }
246
+ envVars.get(varName).push(relativePath);
247
+ }
248
+ }
249
+ return envVars;
250
+ }
251
+ // Scan only code files (JS/TS), not including serverless.yml as a source
252
+ async function scanDirectoryForCodeVars(rootDir, targetDir, scanner) {
253
+ const envVars = new Map();
254
+ // Find all code files in this directory only (not subdirectories for serverless)
255
+ const relativeDir = path.relative(rootDir, targetDir);
256
+ const pattern = relativeDir ? `${relativeDir}/**/*.{js,ts,jsx,tsx,mjs,cjs}` : '**/*.{js,ts,jsx,tsx,mjs,cjs}';
257
+ const files = await (0, glob_1.glob)(pattern, {
258
+ cwd: rootDir,
259
+ ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**'],
260
+ absolute: true,
261
+ });
262
+ for (const file of files) {
263
+ const vars = await scanner.scanFile(file);
264
+ for (const varName of vars) {
265
+ const relativePath = path.relative(rootDir, file);
266
+ if (!envVars.has(varName)) {
267
+ envVars.set(varName, []);
268
+ }
269
+ envVars.get(varName).push(relativePath);
270
+ }
271
+ }
272
+ return envVars;
273
+ }
274
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export interface EnvGuardConfig {
2
+ /**
3
+ * Custom environment variables to ignore in non-strict mode
4
+ * These will be treated like AWS_REGION, NODE_ENV, etc.
5
+ */
6
+ ignoreVars?: string[];
7
+ /**
8
+ * File patterns to exclude from scanning (in addition to defaults)
9
+ */
10
+ exclude?: string[];
11
+ /**
12
+ * Enable strict mode by default
13
+ */
14
+ strict?: boolean;
15
+ }
16
+ /**
17
+ * Load EnvGuard configuration from various sources
18
+ * Priority: CLI args > .envguardrc.json > package.json > defaults
19
+ */
20
+ export declare class ConfigLoader {
21
+ /**
22
+ * Load config from the project root directory
23
+ */
24
+ static loadConfig(rootDir: string): EnvGuardConfig;
25
+ /**
26
+ * Find the config file by searching up the directory tree
27
+ * This allows placing config at repo root and using it in subdirectories
28
+ */
29
+ private static findConfigFile;
30
+ /**
31
+ * Check if a variable should be ignored based on config
32
+ */
33
+ static shouldIgnoreVar(varName: string, config: EnvGuardConfig): boolean;
34
+ }
35
+ //# sourceMappingURL=configLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configLoader.d.ts","sourceRoot":"","sources":["../../src/config/configLoader.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAcD;;;GAGG;AACH,qBAAa,YAAY;IACvB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc;IAuDlD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAwB7B;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO;CAGzE"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ConfigLoader = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const DEFAULT_CONFIG = {
40
+ ignoreVars: [],
41
+ exclude: [],
42
+ strict: false,
43
+ };
44
+ const CONFIG_FILE_NAMES = [
45
+ '.envguardrc.json',
46
+ '.envguardrc',
47
+ 'envguard.config.json',
48
+ ];
49
+ /**
50
+ * Load EnvGuard configuration from various sources
51
+ * Priority: CLI args > .envguardrc.json > package.json > defaults
52
+ */
53
+ class ConfigLoader {
54
+ /**
55
+ * Load config from the project root directory
56
+ */
57
+ static loadConfig(rootDir) {
58
+ // Try to find config file
59
+ const configPath = this.findConfigFile(rootDir);
60
+ if (configPath) {
61
+ try {
62
+ const fileContent = fs.readFileSync(configPath, 'utf-8');
63
+ const userConfig = JSON.parse(fileContent);
64
+ return {
65
+ ...DEFAULT_CONFIG,
66
+ ...userConfig,
67
+ ignoreVars: [
68
+ ...(DEFAULT_CONFIG.ignoreVars || []),
69
+ ...(userConfig.ignoreVars || []),
70
+ ],
71
+ exclude: [
72
+ ...(DEFAULT_CONFIG.exclude || []),
73
+ ...(userConfig.exclude || []),
74
+ ],
75
+ };
76
+ }
77
+ catch (error) {
78
+ console.warn(`Warning: Failed to parse config file ${configPath}:`, error);
79
+ return DEFAULT_CONFIG;
80
+ }
81
+ }
82
+ // Try to load from package.json
83
+ const packageJsonPath = path.join(rootDir, 'package.json');
84
+ if (fs.existsSync(packageJsonPath)) {
85
+ try {
86
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
87
+ if (packageJson.envguard) {
88
+ const userConfig = packageJson.envguard;
89
+ return {
90
+ ...DEFAULT_CONFIG,
91
+ ...userConfig,
92
+ ignoreVars: [
93
+ ...(DEFAULT_CONFIG.ignoreVars || []),
94
+ ...(userConfig.ignoreVars || []),
95
+ ],
96
+ exclude: [
97
+ ...(DEFAULT_CONFIG.exclude || []),
98
+ ...(userConfig.exclude || []),
99
+ ],
100
+ };
101
+ }
102
+ }
103
+ catch (error) {
104
+ // Silently fail if package.json doesn't have envguard config
105
+ }
106
+ }
107
+ return DEFAULT_CONFIG;
108
+ }
109
+ /**
110
+ * Find the config file by searching up the directory tree
111
+ * This allows placing config at repo root and using it in subdirectories
112
+ */
113
+ static findConfigFile(startDir) {
114
+ let currentDir = startDir;
115
+ const root = path.parse(currentDir).root;
116
+ // Search up the directory tree until we hit the filesystem root
117
+ while (currentDir !== root) {
118
+ for (const fileName of CONFIG_FILE_NAMES) {
119
+ const configPath = path.join(currentDir, fileName);
120
+ if (fs.existsSync(configPath)) {
121
+ return configPath;
122
+ }
123
+ }
124
+ // Move up one directory
125
+ const parentDir = path.dirname(currentDir);
126
+ if (parentDir === currentDir) {
127
+ break; // Reached the root
128
+ }
129
+ currentDir = parentDir;
130
+ }
131
+ return null;
132
+ }
133
+ /**
134
+ * Check if a variable should be ignored based on config
135
+ */
136
+ static shouldIgnoreVar(varName, config) {
137
+ return config.ignoreVars?.includes(varName) || false;
138
+ }
139
+ }
140
+ exports.ConfigLoader = ConfigLoader;
141
+ //# sourceMappingURL=configLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configLoader.js","sourceRoot":"","sources":["../../src/config/configLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Well-known environment variables that are provided by runtimes and don't need
3
+ * to be explicitly defined in .env or serverless.yml
4
+ */
5
+ /**
6
+ * AWS Lambda automatically provides these environment variables
7
+ * https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
8
+ */
9
+ export declare const AWS_PROVIDED_VARS: Set<string>;
10
+ /**
11
+ * Common Node.js and development environment variables
12
+ */
13
+ export declare const NODEJS_RUNTIME_VARS: Set<string>;
14
+ /**
15
+ * CI/CD and testing environment variables
16
+ */
17
+ export declare const CI_CD_VARS: Set<string>;
18
+ /**
19
+ * Serverless Framework and local development
20
+ */
21
+ export declare const SERVERLESS_FRAMEWORK_VARS: Set<string>;
22
+ /**
23
+ * Testing framework variables
24
+ */
25
+ export declare const TEST_VARS: Set<string>;
26
+ /**
27
+ * Combine all known runtime variables that don't need to be explicitly defined
28
+ */
29
+ export declare const KNOWN_RUNTIME_VARS: Set<string>;
30
+ /**
31
+ * Check if a variable is a known runtime variable
32
+ */
33
+ export declare function isKnownRuntimeVar(varName: string): boolean;
34
+ /**
35
+ * Get a human-readable category for a known runtime variable
36
+ */
37
+ export declare function getRuntimeVarCategory(varName: string): string | null;
38
+ //# sourceMappingURL=knownEnvVars.d.ts.map