@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,17 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft-07/schema",
3
+ "title": "EnvGuard Configuration",
4
+ "description": "Configuration file for EnvGuard - keep your environment variables in sync",
5
+ "ignoreVars": [
6
+ "MY_COMPANY_VAR",
7
+ "PLATFORM_PROVIDED_VAR"
8
+ ],
9
+ "strict": false,
10
+ "exclude": [
11
+ "**/tmp/**",
12
+ "**/cache/**",
13
+ "**/node_modules/**",
14
+ "**/dist/**",
15
+ "**/test/**"
16
+ ]
17
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,320 @@
1
+ # EnvGuard 🔐
2
+
3
+ Keep your environment variables in sync with your codebase.
4
+
5
+ ## The Problem
6
+
7
+ - `.env.example` is always out of sync with actual `.env`
8
+ - New developers don't know what environment variables they need
9
+ - Production secrets accidentally committed
10
+ - Dead environment variables cluttering your config
11
+
12
+ ## The Solution
13
+
14
+ EnvGuard automatically:
15
+ - Scans your codebase for `process.env.*` usage
16
+ - Compares with your `.env` and `.env.example` files
17
+ - **Supports Serverless Framework** - scans `serverless.yml` environment configurations
18
+ - Alerts you to missing, unused, or undocumented variables
19
+ - Auto-generates `.env.example` with helpful comments
20
+ - **Supports multiple `.env` files** in subdirectories (monorepo-friendly!)
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install -g envguard
26
+ ```
27
+
28
+ Or use with npx:
29
+
30
+ ```bash
31
+ npx envguard scan
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Scan for issues
37
+
38
+ ```bash
39
+ envguard scan
40
+ ```
41
+
42
+ Example output:
43
+
44
+ ```
45
+ 🔍 Scanning codebase for environment variables...
46
+
47
+ ✓ Found 12 unique environment variables in code
48
+ ✓ Found 10 variables in .env
49
+ ✓ Found 8 variables in .env.example
50
+
51
+ ⚠️ Found 5 issue(s):
52
+
53
+ 🚨 Missing from .env:
54
+ 1. STRIPE_SECRET_KEY
55
+ Used in: src/payment.js, src/checkout.ts
56
+ 2. API_KEY
57
+ Used in: src/api/client.ts
58
+
59
+ ⚠️ Unused variables (consider removing):
60
+ 1. OLD_API_URL
61
+ Defined in .env but never used in code
62
+
63
+ 📝 Missing from .env.example:
64
+ 1. DATABASE_URL
65
+ Used in: src/db/connection.ts
66
+ 2. JWT_SECRET
67
+ Used in: src/auth/jwt.ts
68
+
69
+ 💡 Run `envguard fix` to auto-generate .env.example
70
+ ```
71
+
72
+ ### Auto-generate .env.example
73
+
74
+ ```bash
75
+ envguard fix
76
+ ```
77
+
78
+ This will create/update `.env.example` files with:
79
+ - All environment variables used in your code
80
+ - Comments showing where each variable is used
81
+ - Format hints for common variable types (URLs, ports, etc.)
82
+ - **Creates `.env.example` next to each `.env` file** (great for monorepos!)
83
+
84
+ Example generated `.env.example`:
85
+
86
+ ```bash
87
+ # Auto-generated by envguard
88
+ # Do not put actual secrets in this file - use .env instead
89
+
90
+ # Used in: src/db/connection.ts:12, src/models/user.ts:5
91
+ # Format: postgresql://user:pass@host:5432/db
92
+ DATABASE_URL=
93
+
94
+ # Used in: src/payment.js:23
95
+ # Format: sk_test_...
96
+ STRIPE_SECRET_KEY=
97
+
98
+ # Used in: src/server.ts:8
99
+ # Format: 3000
100
+ PORT=
101
+ ```
102
+
103
+ ### CI/CD Integration
104
+
105
+ Use the `check` command in your CI pipeline to fail builds if environment variables are out of sync:
106
+
107
+ ```bash
108
+ envguard check
109
+ ```
110
+
111
+ This is equivalent to `envguard scan --ci` and will exit with code 1 if issues are found.
112
+
113
+ #### GitHub Actions Example
114
+
115
+ ```yaml
116
+ name: Check Env Sync
117
+ on: [pull_request]
118
+
119
+ jobs:
120
+ envguard:
121
+ runs-on: ubuntu-latest
122
+ steps:
123
+ - uses: actions/checkout@v3
124
+ - uses: actions/setup-node@v3
125
+ - run: npx envguard check
126
+ ```
127
+
128
+ ## Supported Languages & Frameworks
129
+
130
+ ### JavaScript/TypeScript
131
+ - JavaScript (`.js`, `.mjs`, `.cjs`)
132
+ - TypeScript (`.ts`, `.tsx`)
133
+ - JSX (`.jsx`)
134
+
135
+ Detects:
136
+ - `process.env.VAR_NAME`
137
+ - `process.env['VAR_NAME']`
138
+ - `const { VAR_NAME } = process.env`
139
+
140
+ ### Serverless Framework
141
+ - Automatically detects `serverless.yml` and `serverless.yaml` files
142
+ - Scans `provider.environment` section
143
+ - Scans function-level `environment` sections
144
+ - Detects references to external sources (SSM, Secrets Manager, etc.)
145
+ - Validates that all defined variables are used in code
146
+ - Reports variables used in code but not defined in serverless.yml
147
+
148
+ ## Configuration
149
+
150
+ EnvGuard works out of the box with sensible defaults. It automatically excludes:
151
+ - `node_modules`
152
+ - `dist`
153
+ - `build`
154
+ - `.git`
155
+
156
+ ### Custom Configuration
157
+
158
+ Create a `.envguardrc.json` file in your project root to customize behavior:
159
+
160
+ ```json
161
+ {
162
+ "ignoreVars": [
163
+ "MY_CUSTOM_VAR",
164
+ "ANOTHER_VAR",
165
+ "COMPANY_INTERNAL_VAR"
166
+ ],
167
+ "strict": false,
168
+ "exclude": [
169
+ "**/build/**",
170
+ "**/tmp/**"
171
+ ]
172
+ }
173
+ ```
174
+
175
+ **Configuration options:**
176
+
177
+ - `ignoreVars` (string[]): Custom environment variables to ignore in non-strict mode. These will be treated like AWS_REGION and won't trigger warnings.
178
+ - `strict` (boolean): Enable strict mode by default (can be overridden with CLI flag)
179
+ - `exclude` (string[]): Additional file patterns to exclude from scanning
180
+
181
+ **Alternative: package.json**
182
+
183
+ You can also add configuration to your `package.json`:
184
+
185
+ ```json
186
+ {
187
+ "envguard": {
188
+ "ignoreVars": ["MY_CUSTOM_VAR"],
189
+ "strict": false
190
+ }
191
+ }
192
+ ```
193
+
194
+ **Use case for ignoreVars:**
195
+ - Company-wide variables that are always available (injected by infrastructure)
196
+ - Framework-specific variables you don't need to track
197
+ - Variables provided by your deployment platform (Vercel, Netlify, etc.)
198
+ - Custom variables for GitHub Apps or CI/CD integrations
199
+
200
+ **Priority:** CLI flags > `.envguardrc.json` > `package.json` > defaults
201
+
202
+ **GitHub Apps & CI/CD:**
203
+ When using EnvGuard as a GitHub App or in CI/CD pipelines, commit your `.envguardrc.json` to the repository. This ensures consistent behavior across all environments and team members.
204
+
205
+ ### Monorepo Support
206
+
207
+ EnvGuard automatically detects all `.env` files in your project, including subdirectories. When you run `envguard fix`, it creates a `.env.example` file next to each `.env` file it finds.
208
+
209
+ Example structure:
210
+ ```
211
+ project/
212
+ ├── .env → generates .env.example
213
+ ├── src/
214
+ │ └── lambda1/
215
+ │ ├── .env → generates lambda1/.env.example
216
+ │ └── handler.js
217
+ └── services/
218
+ └── api/
219
+ ├── .env → generates api/.env.example
220
+ └── server.js
221
+ ```
222
+
223
+ Each `.env.example` only includes variables used in that directory and its subdirectories.
224
+
225
+ ## Serverless Framework Support
226
+
227
+ EnvGuard can scan `serverless.yml` files as a standalone source of environment variable definitions. This is useful for AWS Lambda projects where environment variables are defined in the serverless configuration rather than `.env` files.
228
+
229
+ ### How it works
230
+
231
+ 1. **Detects** `serverless.yml` files in your project
232
+ 2. **Extracts** environment variables from `provider.environment` and function-level `environment` sections
233
+ 3. **Validates** that all defined variables are actually used in your Lambda code
234
+ 4. **Reports** unused variables and missing definitions
235
+
236
+ ### Example serverless.yml
237
+
238
+ ```yaml
239
+ provider:
240
+ name: aws
241
+ runtime: nodejs20.x
242
+ environment:
243
+ NODE_ENV: ${opt:stage}
244
+ API_KEY: ${ssm:/my-app/api-key}
245
+ DATABASE_URL: ${self:custom.dbUrl}
246
+ ```
247
+
248
+ ### Scan output for serverless.yml
249
+
250
+ ```
251
+ 📂 Checking src/lambda/serverless.yml
252
+
253
+ Found 3 variable(s) in serverless.yml
254
+ Found 2 variable(s) used in code
255
+
256
+ ⚠️ Unused variables in serverless.yml:
257
+ 1. DATABASE_URL
258
+
259
+ 🚨 Missing from serverless.yml:
260
+ 1. LOG_LEVEL
261
+ Used in: src/lambda/handler.js
262
+ ```
263
+
264
+ ### Key Features
265
+
266
+ - **No .env required** - serverless.yml is treated as a standalone configuration source
267
+ - **CloudFormation intrinsic functions** - Supports `!Ref`, `!GetAtt`, `!Sub`, `!ImportValue`, and all CF functions
268
+ - **External references** - Detects SSM parameters, Secrets Manager, CloudFormation outputs
269
+ - **Function-level variables** - Scans both provider-level and function-specific environment vars
270
+ - **Smart filtering** - Automatically skips AWS/runtime variables (disable with `--strict`)
271
+ - **CI/CD validation** - Use `envguard check` to enforce serverless config completeness
272
+
273
+ ## Commands
274
+
275
+ - `envguard scan` - Scan for issues and display report
276
+ - `envguard scan --ci` - Scan and exit with error code if issues found
277
+ - `envguard scan --strict` - Report all variables including known runtime variables
278
+ - `envguard fix` - Auto-generate `.env.example`
279
+ - `envguard check` - Alias for `scan --ci`
280
+ - `envguard check --strict` - Check with strict mode enabled
281
+
282
+ ### Strict Mode
283
+
284
+ By default, EnvGuard filters out well-known runtime variables that don't need to be explicitly defined:
285
+
286
+ **AWS Lambda variables**: `AWS_REGION`, `AWS_LAMBDA_FUNCTION_NAME`, etc.
287
+ **Node.js runtime**: `NODE_ENV`, `PATH`, etc.
288
+ **CI/CD environments**: `CI`, `GITHUB_ACTIONS`, etc.
289
+ **Serverless Framework**: `IS_OFFLINE`, `SLS_OFFLINE`, etc.
290
+
291
+ Use `--strict` mode to report ALL variables including these runtime-provided ones:
292
+
293
+ ```bash
294
+ envguard scan --strict
295
+ ```
296
+
297
+ Example output (non-strict):
298
+ ```
299
+ ℹ️ Skipped known runtime variables (use --strict to show):
300
+ Serverless Framework: IS_OFFLINE, SLS_OFFLINE
301
+ CI/CD: CI
302
+ AWS Lambda: AWS_REGION
303
+ ```
304
+
305
+ ## Development
306
+
307
+ ```bash
308
+ # Install dependencies
309
+ npm install
310
+
311
+ # Build
312
+ npm run build
313
+
314
+ # Run locally
315
+ npm start scan
316
+ ```
317
+
318
+ ## License
319
+
320
+ MIT
@@ -0,0 +1,8 @@
1
+ import { ScanResult } from '../types';
2
+ import { EnvEntry } from '../parser/envParser';
3
+ export declare class EnvAnalyzer {
4
+ analyze(usedVars: Map<string, string[]>, definedVars: Map<string, EnvEntry>, exampleVars: Set<string>): ScanResult;
5
+ generateExampleContent(usedVars: Map<string, string[]>, existingEntries: Map<string, EnvEntry>): string;
6
+ private getFormatHint;
7
+ }
8
+ //# sourceMappingURL=envAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envAnalyzer.d.ts","sourceRoot":"","sources":["../../src/analyzer/envAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,UAAU,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,qBAAa,WAAW;IACtB,OAAO,CACL,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC/B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAClC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,UAAU;IA8Cb,sBAAsB,CACpB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC/B,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,GACrC,MAAM;IAyCT,OAAO,CAAC,aAAa;CAkCtB"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EnvAnalyzer = void 0;
4
+ class EnvAnalyzer {
5
+ analyze(usedVars, definedVars, exampleVars) {
6
+ const issues = [];
7
+ // Issue 1: Variables used in code but missing from .env
8
+ for (const [varName, locations] of usedVars.entries()) {
9
+ if (!definedVars.has(varName)) {
10
+ issues.push({
11
+ type: 'missing',
12
+ varName,
13
+ details: `Used in code but not defined in .env`,
14
+ locations,
15
+ });
16
+ }
17
+ }
18
+ // Issue 2: Variables defined in .env but never used
19
+ for (const [varName] of definedVars.entries()) {
20
+ if (!usedVars.has(varName)) {
21
+ issues.push({
22
+ type: 'unused',
23
+ varName,
24
+ details: `Defined in .env but never used in code`,
25
+ });
26
+ }
27
+ }
28
+ // Issue 3: Variables used in code but not in .env.example
29
+ for (const [varName, locations] of usedVars.entries()) {
30
+ if (!exampleVars.has(varName)) {
31
+ issues.push({
32
+ type: 'undocumented',
33
+ varName,
34
+ details: `Used in code but missing from .env.example`,
35
+ locations,
36
+ });
37
+ }
38
+ }
39
+ return {
40
+ issues,
41
+ usedVars,
42
+ definedVars: new Set(definedVars.keys()),
43
+ exampleVars,
44
+ };
45
+ }
46
+ generateExampleContent(usedVars, existingEntries) {
47
+ let content = '# Auto-generated by envguard\n';
48
+ content += '# Do not put actual secrets in this file - use .env instead\n\n';
49
+ const sortedVars = Array.from(usedVars.keys()).sort();
50
+ for (const varName of sortedVars) {
51
+ const locations = usedVars.get(varName);
52
+ const existingEntry = existingEntries.get(varName);
53
+ // Add location comments
54
+ content += `# Used in: ${locations.slice(0, 3).join(', ')}`;
55
+ if (locations.length > 3) {
56
+ content += ` (+${locations.length - 3} more)`;
57
+ }
58
+ content += '\n';
59
+ // Add existing comment if available
60
+ if (existingEntry?.comment) {
61
+ content += `# ${existingEntry.comment}\n`;
62
+ }
63
+ else {
64
+ // Add a format hint based on common patterns
65
+ const hint = this.getFormatHint(varName);
66
+ if (hint) {
67
+ content += `# Format: ${hint}\n`;
68
+ }
69
+ }
70
+ // Add the variable with empty value or existing value
71
+ if (existingEntry) {
72
+ content += `${varName}=${existingEntry.value}\n`;
73
+ }
74
+ else {
75
+ content += `${varName}=\n`;
76
+ }
77
+ content += '\n';
78
+ }
79
+ return content;
80
+ }
81
+ getFormatHint(varName) {
82
+ const patterns = {
83
+ 'DATABASE_URL': 'postgresql://user:pass@host:5432/db',
84
+ 'MONGODB_URI': 'mongodb://localhost:27017/dbname',
85
+ 'REDIS_URL': 'redis://localhost:6379',
86
+ 'PORT': '3000',
87
+ 'NODE_ENV': 'development|production|test',
88
+ 'API_KEY': 'your-api-key-here',
89
+ 'SECRET': 'your-secret-here',
90
+ 'JWT_SECRET': 'your-jwt-secret',
91
+ 'STRIPE_': 'sk_test_...',
92
+ 'AWS_': 'aws-credentials',
93
+ };
94
+ for (const [pattern, hint] of Object.entries(patterns)) {
95
+ if (varName.includes(pattern)) {
96
+ return hint;
97
+ }
98
+ }
99
+ if (varName.endsWith('_URL') || varName.endsWith('_URI')) {
100
+ return 'https://example.com';
101
+ }
102
+ if (varName.endsWith('_PORT')) {
103
+ return '8080';
104
+ }
105
+ if (varName.endsWith('_KEY') || varName.endsWith('_SECRET') || varName.endsWith('_TOKEN')) {
106
+ return 'your-secret-here';
107
+ }
108
+ return null;
109
+ }
110
+ }
111
+ exports.EnvAnalyzer = EnvAnalyzer;
112
+ //# sourceMappingURL=envAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envAnalyzer.js","sourceRoot":"","sources":["../../src/analyzer/envAnalyzer.ts"],"names":[],"mappings":";;;AAGA,MAAa,WAAW;IACtB,OAAO,CACL,QAA+B,EAC/B,WAAkC,EAClC,WAAwB;QAExB,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,wDAAwD;QACxD,KAAK,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;YACtD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,SAAS;oBACf,OAAO;oBACP,OAAO,EAAE,sCAAsC;oBAC/C,SAAS;iBACV,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,KAAK,MAAM,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,OAAO;oBACP,OAAO,EAAE,wCAAwC;iBAClD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,0DAA0D;QAC1D,KAAK,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;YACtD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,cAAc;oBACpB,OAAO;oBACP,OAAO,EAAE,4CAA4C;oBACrD,SAAS;iBACV,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM;YACN,QAAQ;YACR,WAAW,EAAE,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YACxC,WAAW;SACZ,CAAC;IACJ,CAAC;IAED,sBAAsB,CACpB,QAA+B,EAC/B,eAAsC;QAEtC,IAAI,OAAO,GAAG,gCAAgC,CAAC;QAC/C,OAAO,IAAI,iEAAiE,CAAC;QAE7E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtD,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;YACzC,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAEnD,wBAAwB;YACxB,OAAO,IAAI,cAAc,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,MAAM,SAAS,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC;YAChD,CAAC;YACD,OAAO,IAAI,IAAI,CAAC;YAEhB,oCAAoC;YACpC,IAAI,aAAa,EAAE,OAAO,EAAE,CAAC;gBAC3B,OAAO,IAAI,KAAK,aAAa,CAAC,OAAO,IAAI,CAAC;YAC5C,CAAC;iBAAM,CAAC;gBACN,6CAA6C;gBAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBACzC,IAAI,IAAI,EAAE,CAAC;oBACT,OAAO,IAAI,aAAa,IAAI,IAAI,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,sDAAsD;YACtD,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,IAAI,GAAG,OAAO,IAAI,aAAa,CAAC,KAAK,IAAI,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,GAAG,OAAO,KAAK,CAAC;YAC7B,CAAC;YAED,OAAO,IAAI,IAAI,CAAC;QAClB,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,aAAa,CAAC,OAAe;QACnC,MAAM,QAAQ,GAA8B;YAC1C,cAAc,EAAE,qCAAqC;YACrD,aAAa,EAAE,kCAAkC;YACjD,WAAW,EAAE,wBAAwB;YACrC,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,6BAA6B;YACzC,SAAS,EAAE,mBAAmB;YAC9B,QAAQ,EAAE,kBAAkB;YAC5B,YAAY,EAAE,iBAAiB;YAC/B,SAAS,EAAE,aAAa;YACxB,MAAM,EAAE,iBAAiB;SAC1B,CAAC;QAEF,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvD,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9B,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1F,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAjID,kCAiIC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const scan_1 = require("./commands/scan");
6
+ const fix_1 = require("./commands/fix");
7
+ const program = new commander_1.Command();
8
+ program
9
+ .name('envguard')
10
+ .description('Keep your environment variables in sync with your codebase')
11
+ .version('0.1.0');
12
+ program
13
+ .command('scan')
14
+ .description('Scan codebase and compare with .env files')
15
+ .option('--ci', 'Exit with error code if issues found (for CI/CD)')
16
+ .option('--strict', 'Report all variables including known runtime variables (AWS_REGION, NODE_ENV, etc.)')
17
+ .action(async (options) => {
18
+ try {
19
+ await (0, scan_1.scanCommand)(options);
20
+ }
21
+ catch (error) {
22
+ console.error('Error:', error);
23
+ process.exit(1);
24
+ }
25
+ });
26
+ program
27
+ .command('fix')
28
+ .description('Auto-generate .env.example from codebase')
29
+ .action(async () => {
30
+ try {
31
+ await (0, fix_1.fixCommand)();
32
+ }
33
+ catch (error) {
34
+ console.error('Error:', error);
35
+ process.exit(1);
36
+ }
37
+ });
38
+ program
39
+ .command('check')
40
+ .description('Check for issues (alias for scan --ci)')
41
+ .option('--strict', 'Report all variables including known runtime variables (AWS_REGION, NODE_ENV, etc.)')
42
+ .action(async (options) => {
43
+ try {
44
+ await (0, scan_1.scanCommand)({ ci: true, strict: options.strict });
45
+ }
46
+ catch (error) {
47
+ console.error('Error:', error);
48
+ process.exit(1);
49
+ }
50
+ });
51
+ program.parse();
52
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,0CAA8C;AAC9C,wCAA4C;AAG5C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,MAAM,EAAE,kDAAkD,CAAC;KAClE,MAAM,CAAC,UAAU,EAAE,qFAAqF,CAAC;KACzG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,IAAA,kBAAW,EAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,IAAI,CAAC;QACH,MAAM,IAAA,gBAAU,GAAE,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,UAAU,EAAE,qFAAqF,CAAC;KACzG,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,IAAI,CAAC;QACH,MAAM,IAAA,kBAAW,EAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function checkCommand(): Promise<{
2
+ success: boolean;
3
+ issues: import("..").Issue[];
4
+ }>;
5
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY;;;GAGjC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkCommand = checkCommand;
4
+ const scan_1 = require("./scan");
5
+ async function checkCommand() {
6
+ // Check command is the same as scan but with --ci flag
7
+ return (0, scan_1.scanCommand)({ ci: true });
8
+ }
9
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":";;AAEA,oCAGC;AALD,iCAAqC;AAE9B,KAAK,UAAU,YAAY;IAChC,uDAAuD;IACvD,OAAO,IAAA,kBAAW,EAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function fixCommand(): Promise<{
2
+ success: boolean;
3
+ }>;
4
+ //# sourceMappingURL=fix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix.d.ts","sourceRoot":"","sources":["../../src/commands/fix.ts"],"names":[],"mappings":"AAOA,wBAAsB,UAAU;;GAgE/B"}