@anhuijie/envguard 1.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 EnvGuard Contributors
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,444 @@
1
+ <div align="center">
2
+
3
+ # 🛡️ EnvGuard
4
+
5
+ **Environment Variable Validation, Security Scanning & Documentation Generator**
6
+
7
+ [![CI](https://github.com/AnhuiJie/envguard/actions/workflows/ci.yml/badge.svg)](https://github.com/AnhuiJie/envguard/actions/workflows/ci.yml)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ [![Node.js >=18](https://img.shields.io/badge/node-%3E%3D18-green.svg)](https://nodejs.org/)
10
+
11
+ [English](#english) · [中文](#中文) · [日本語](#日本語)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ <a id="english"></a>
18
+
19
+ ## 🇬🇧 English
20
+
21
+ ### Why EnvGuard?
22
+
23
+ Misconfigured environment variables are a leading cause of production incidents. EnvGuard provides a **single tool** to validate, secure, and document your project's configuration — catching errors before they reach production.
24
+
25
+ ### Features
26
+
27
+ - **Schema Validation** — Define types, required fields, enums, ranges, and patterns for every variable
28
+ - **Security Scanning** — Detect accidentally committed secrets (AWS keys, GitHub tokens, private keys, etc.)
29
+ - **Auto Documentation** — Generate `.env.example` and markdown docs from your schema
30
+ - **Environment Diff** — Compare `.env` files across dev/staging/prod to find drift
31
+ - **CI/CD Ready** — Exit codes and GitHub Action integration for automated checks
32
+ - **Zero Dependencies** — Pure Node.js, no external packages required
33
+ - **Multi-format Support** — Works with `.env`, `.env.local`, `.env.production`, and more
34
+
35
+ ### Quick Start
36
+
37
+ ```bash
38
+ # Install
39
+ npm install -g envguard
40
+
41
+ # Create config
42
+ envguard init
43
+
44
+ # Validate environment variables
45
+ envguard validate
46
+
47
+ # Scan for secrets
48
+ envguard check
49
+
50
+ # Generate documentation
51
+ envguard docs
52
+
53
+ # Compare environments
54
+ envguard diff .env.development .env.production
55
+ ```
56
+
57
+ ### Configuration
58
+
59
+ Create `envguard.config.js` in your project root:
60
+
61
+ ```js
62
+ module.exports = {
63
+ schema: {
64
+ NODE_ENV: {
65
+ required: true,
66
+ type: 'string',
67
+ enum: ['development', 'staging', 'production', 'test'],
68
+ description: 'Application environment',
69
+ },
70
+ PORT: {
71
+ required: false,
72
+ type: 'port',
73
+ default: '3000',
74
+ description: 'Server port',
75
+ },
76
+ DATABASE_URL: {
77
+ required: true,
78
+ type: 'url',
79
+ description: 'Database connection string',
80
+ },
81
+ JWT_SECRET: {
82
+ required: true,
83
+ type: 'string',
84
+ description: 'Secret key for JWT signing',
85
+ },
86
+ },
87
+ security: {
88
+ minSeverity: 'medium',
89
+ ignoreKeys: [],
90
+ },
91
+ };
92
+ ```
93
+
94
+ ### Supported Types
95
+
96
+ | Type | Description | Example |
97
+ |------|-------------|---------|
98
+ | `string` | Any string value | `any text` |
99
+ | `number` | Numeric value with optional min/max | `42` |
100
+ | `boolean` | true/false, 1/0, yes/no | `true` |
101
+ | `url` | Valid URL | `https://example.com` |
102
+ | `email` | Valid email address | `user@example.com` |
103
+ | `port` | Valid port number (0-65535) | `3000` |
104
+ | `json` | Valid JSON string | `'{"key":"value"}'` |
105
+ | `regex` | Valid regex pattern | `^\\d+$` |
106
+
107
+ ### Rule Options
108
+
109
+ | Option | Type | Description |
110
+ |--------|------|-------------|
111
+ | `required` | boolean | Variable must be set |
112
+ | `type` | string | Value type validation |
113
+ | `default` | any | Default value if not set |
114
+ | `enum` | array | Allowed values |
115
+ | `min` / `max` | number | Range constraints (for `number` type) |
116
+ | `pattern` | string | Regex pattern the value must match |
117
+ | `deprecated` | boolean | Mark as deprecated |
118
+ | `replacement` | string | Suggested replacement for deprecated vars |
119
+ | `description` | string | Human-readable description |
120
+
121
+ ### Security Scanning
122
+
123
+ EnvGuard detects these secret types:
124
+
125
+ - AWS Access Keys & Secret Keys
126
+ - GitHub / GitLab Tokens
127
+ - Slack Tokens
128
+ - Stripe Live Keys
129
+ - Private Keys (RSA, EC, DSA)
130
+ - JWT Secrets
131
+ - Database URLs with embedded passwords
132
+ - Generic API Keys, Passwords, and Secrets
133
+
134
+ ### CI/CD Integration
135
+
136
+ **GitHub Actions:**
137
+
138
+ ```yaml
139
+ - name: Validate env config
140
+ run: npx envguard validate
141
+
142
+ - name: Security check
143
+ run: npx envguard check
144
+ ```
145
+
146
+ The command exits with code `1` on validation errors or critical security findings, failing the build.
147
+
148
+ ### Programmatic API
149
+
150
+ ```js
151
+ const { validateEnv, scanForSecrets, generateEnvExample } = require('envguard');
152
+
153
+ const schema = { PORT: { required: true, type: 'port' } };
154
+ const result = validateEnv(process.env, schema);
155
+ // { valid: true, errors: [], warnings: [], checked: 1 }
156
+
157
+ const secrets = scanForSecrets(process.env);
158
+ // { findings: [], hasCritical: false, total: 0 }
159
+
160
+ const example = generateEnvExample(schema);
161
+ // "# Server port\n# type: port\nPORT=\n"
162
+ ```
163
+
164
+ ### License
165
+
166
+ [MIT](LICENSE)
167
+
168
+ ---
169
+
170
+ <a id="中文"></a>
171
+
172
+ ## 🇨🇳 中文
173
+
174
+ ### 为什么需要 EnvGuard?
175
+
176
+ 环境变量配置错误是生产事故的主要原因之一。EnvGuard 提供**一站式工具**来验证、保护和文档化项目配置——在错误到达生产环境之前就将其捕获。
177
+
178
+ ### 功能特性
179
+
180
+ - **Schema 验证** — 为每个变量定义类型、必填、枚举、范围和正则模式
181
+ - **安全扫描** — 检测意外提交的密钥(AWS 密钥、GitHub Token、私钥等)
182
+ - **自动文档** — 从 Schema 生成 `.env.example` 和 Markdown 文档
183
+ - **环境对比** — 比较 dev/staging/prod 的 `.env` 文件差异
184
+ - **CI/CD 就绪** — 退出码和 GitHub Action 集成,支持自动化检查
185
+ - **零依赖** — 纯 Node.js 实现,无需外部包
186
+ - **多格式支持** — 支持 `.env`、`.env.local`、`.env.production` 等
187
+
188
+ ### 快速开始
189
+
190
+ ```bash
191
+ # 安装
192
+ npm install -g envguard
193
+
194
+ # 创建配置
195
+ envguard init
196
+
197
+ # 验证环境变量
198
+ envguard validate
199
+
200
+ # 扫描敏感信息
201
+ envguard check
202
+
203
+ # 生成文档
204
+ envguard docs
205
+
206
+ # 对比环境差异
207
+ envguard diff .env.development .env.production
208
+ ```
209
+
210
+ ### 配置
211
+
212
+ 在项目根目录创建 `envguard.config.js`:
213
+
214
+ ```js
215
+ module.exports = {
216
+ schema: {
217
+ NODE_ENV: {
218
+ required: true,
219
+ type: 'string',
220
+ enum: ['development', 'staging', 'production', 'test'],
221
+ description: '应用运行环境',
222
+ },
223
+ PORT: {
224
+ required: false,
225
+ type: 'port',
226
+ default: '3000',
227
+ description: '服务端口',
228
+ },
229
+ DATABASE_URL: {
230
+ required: true,
231
+ type: 'url',
232
+ description: '数据库连接字符串',
233
+ },
234
+ JWT_SECRET: {
235
+ required: true,
236
+ type: 'string',
237
+ description: 'JWT 签名密钥',
238
+ },
239
+ },
240
+ security: {
241
+ minSeverity: 'medium',
242
+ ignoreKeys: [],
243
+ },
244
+ };
245
+ ```
246
+
247
+ ### 支持的类型
248
+
249
+ | 类型 | 说明 | 示例 |
250
+ |------|------|------|
251
+ | `string` | 任意字符串 | `任意文本` |
252
+ | `number` | 数值,支持 min/max | `42` |
253
+ | `boolean` | true/false、1/0、yes/no | `true` |
254
+ | `url` | 合法 URL | `https://example.com` |
255
+ | `email` | 合法邮箱 | `user@example.com` |
256
+ | `port` | 合法端口号 (0-65535) | `3000` |
257
+ | `json` | 合法 JSON 字符串 | `'{"key":"value"}'` |
258
+ | `regex` | 合法正则表达式 | `^\\d+$` |
259
+
260
+ ### 安全扫描
261
+
262
+ EnvGuard 可检测以下密钥类型:
263
+
264
+ - AWS 访问密钥和密钥
265
+ - GitHub / GitLab Token
266
+ - Slack Token
267
+ - Stripe Live Key
268
+ - 私钥(RSA、EC、DSA)
269
+ - JWT 密钥
270
+ - 包含密码的数据库连接 URL
271
+ - 通用 API Key、密码和密钥
272
+
273
+ ### CI/CD 集成
274
+
275
+ **GitHub Actions:**
276
+
277
+ ```yaml
278
+ - name: 验证环境配置
279
+ run: npx envguard validate
280
+
281
+ - name: 安全检查
282
+ run: npx envguard check
283
+ ```
284
+
285
+ 验证失败或发现严重安全问题时,命令以退出码 `1` 退出,使构建失败。
286
+
287
+ ### 编程式 API
288
+
289
+ ```js
290
+ const { validateEnv, scanForSecrets, generateEnvExample } = require('envguard');
291
+
292
+ const schema = { PORT: { required: true, type: 'port' } };
293
+ const result = validateEnv(process.env, schema);
294
+ // { valid: true, errors: [], warnings: [], checked: 1 }
295
+
296
+ const secrets = scanForSecrets(process.env);
297
+ // { findings: [], hasCritical: false, total: 0 }
298
+
299
+ const example = generateEnvExample(schema);
300
+ // "# Server port\n# type: port\nPORT=\n"
301
+ ```
302
+
303
+ ### 许可证
304
+
305
+ [MIT](LICENSE)
306
+
307
+ ---
308
+
309
+ <a id="日本語"></a>
310
+
311
+ ## 🇯🇵 日本語
312
+
313
+ ### なぜ EnvGuard が必要か?
314
+
315
+ 環境変数の設定ミスは本番障害の主要な原因の一つです。EnvGuard は、プロジェクトの設定を検証・保護・文書化する**オールインワンツール**を提供し、エラーが本番環境に到達する前に検出します。
316
+
317
+ ### 機能
318
+
319
+ - **スキーマ検証** — 各変数の型、必須、列挙、範囲、正規表現パターンを定義
320
+ - **セキュリティスキャン** — 誤ってコミットされたシークレットの検出(AWS キー、GitHub トークン、秘密鍵など)
321
+ - **自動ドキュメント生成** — スキーマから `.env.example` と Markdown ドキュメントを生成
322
+ - **環境比較** — dev/staging/prod の `.env` ファイルの差分を検出
323
+ - **CI/CD 対応** — 終了コードと GitHub Action 統合による自動チェック
324
+ - **ゼロ依存** — 外部パッケージ不要のピュア Node.js 実装
325
+ - **マルチフォーマット対応** — `.env`、`.env.local`、`.env.production` などに対応
326
+
327
+ ### クイックスタート
328
+
329
+ ```bash
330
+ # インストール
331
+ npm install -g envguard
332
+
333
+ # 設定ファイルの作成
334
+ envguard init
335
+
336
+ # 環境変数の検証
337
+ envguard validate
338
+
339
+ # セキュリティスキャン
340
+ envguard check
341
+
342
+ # ドキュメント生成
343
+ envguard docs
344
+
345
+ # 環境の比較
346
+ envguard diff .env.development .env.production
347
+ ```
348
+
349
+ ### 設定
350
+
351
+ プロジェクトルートに `envguard.config.js` を作成:
352
+
353
+ ```js
354
+ module.exports = {
355
+ schema: {
356
+ NODE_ENV: {
357
+ required: true,
358
+ type: 'string',
359
+ enum: ['development', 'staging', 'production', 'test'],
360
+ description: 'アプリケーション環境',
361
+ },
362
+ PORT: {
363
+ required: false,
364
+ type: 'port',
365
+ default: '3000',
366
+ description: 'サーバーポート',
367
+ },
368
+ DATABASE_URL: {
369
+ required: true,
370
+ type: 'url',
371
+ description: 'データベース接続文字列',
372
+ },
373
+ JWT_SECRET: {
374
+ required: true,
375
+ type: 'string',
376
+ description: 'JWT 署名用シークレットキー',
377
+ },
378
+ },
379
+ security: {
380
+ minSeverity: 'medium',
381
+ ignoreKeys: [],
382
+ },
383
+ };
384
+ ```
385
+
386
+ ### サポート型
387
+
388
+ | 型 | 説明 | 例 |
389
+ |----|------|-----|
390
+ | `string` | 任意の文字列 | `任意のテキスト` |
391
+ | `number` | 数値(min/max 対応) | `42` |
392
+ | `boolean` | true/false、1/0、yes/no | `true` |
393
+ | `url` | 有効な URL | `https://example.com` |
394
+ | `email` | 有効なメールアドレス | `user@example.com` |
395
+ | `port` | 有効なポート番号 (0-65535) | `3000` |
396
+ | `json` | 有効な JSON 文字列 | `'{"key":"value"}'` |
397
+ | `regex` | 有効な正規表現パターン | `^\\d+$` |
398
+
399
+ ### セキュリティスキャン
400
+
401
+ EnvGuard は以下のシークレットタイプを検出します:
402
+
403
+ - AWS アクセスキー・シークレットキー
404
+ - GitHub / GitLab トークン
405
+ - Slack トークン
406
+ - Stripe ライブキー
407
+ - 秘密鍵(RSA、EC、DSA)
408
+ - JWT シークレット
409
+ - パスワード埋め込みデータベース URL
410
+ - 汎用 API キー、パスワード、シークレット
411
+
412
+ ### CI/CD 統合
413
+
414
+ **GitHub Actions:**
415
+
416
+ ```yaml
417
+ - name: 環境設定の検証
418
+ run: npx envguard validate
419
+
420
+ - name: セキュリティチェック
421
+ run: npx envguard check
422
+ ```
423
+
424
+ 検証エラーや重大なセキュリティ問題が見つかった場合、コマンドは終了コード `1` で終了し、ビルドを失敗させます。
425
+
426
+ ### プログラマティック API
427
+
428
+ ```js
429
+ const { validateEnv, scanForSecrets, generateEnvExample } = require('envguard');
430
+
431
+ const schema = { PORT: { required: true, type: 'port' } };
432
+ const result = validateEnv(process.env, schema);
433
+ // { valid: true, errors: [], warnings: [], checked: 1 }
434
+
435
+ const secrets = scanForSecrets(process.env);
436
+ // { findings: [], hasCritical: false, total: 0 }
437
+
438
+ const example = generateEnvExample(schema);
439
+ // "# Server port\n# type: port\nPORT=\n"
440
+ ```
441
+
442
+ ### ライセンス
443
+
444
+ [MIT](LICENSE)
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@anhuijie/envguard",
3
+ "version": "1.0.0",
4
+ "description": "Environment variable & config validation, security scanning, and documentation generator for modern projects",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "envguard": "./src/cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node src/cli.js",
11
+ "test": "node --test test/**/*.test.js",
12
+ "lint": "eslint src/"
13
+ },
14
+ "keywords": [
15
+ "env",
16
+ "environment-variables",
17
+ "config",
18
+ "validation",
19
+ "security",
20
+ "dotenv",
21
+ "schema",
22
+ "documentation",
23
+ "ci-cd"
24
+ ],
25
+ "author": "AnhuiJie <anhuijie@example.com>",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/AnhuiJie/envguard"
30
+ },
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "files": [
35
+ "src/",
36
+ "README.md",
37
+ "LICENSE"
38
+ ]
39
+ }
package/src/cli.js ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * EnvGuard CLI — Environment variable & config validation, security scanning, and documentation generator
5
+ */
6
+
7
+ const { runInit } = require('./commands/init');
8
+ const { runValidate } = require('./commands/validate');
9
+ const { runCheck } = require('./commands/check');
10
+ const { runDocs } = require('./commands/docs');
11
+ const { runDiff } = require('./commands/diff');
12
+
13
+ const VERSION = '1.0.0';
14
+
15
+ function parseArgs(argv) {
16
+ const args = argv.slice(2);
17
+ const command = args[0];
18
+ const options = {};
19
+ const positional = [];
20
+
21
+ for (let i = 1; i < args.length; i++) {
22
+ if (args[i].startsWith('--')) {
23
+ const key = args[i].slice(2);
24
+ const next = args[i + 1];
25
+ if (next && !next.startsWith('--')) {
26
+ options[key] = next;
27
+ i++;
28
+ } else {
29
+ options[key] = true;
30
+ }
31
+ } else {
32
+ positional.push(args[i]);
33
+ }
34
+ }
35
+
36
+ // Map positional args to command-specific options
37
+ if (command === 'diff' && positional.length >= 2) {
38
+ options.fileA = positional[0];
39
+ options.fileB = positional[1];
40
+ }
41
+
42
+ return { command, options };
43
+ }
44
+
45
+ function printHelp() {
46
+ console.log(`
47
+ EnvGuard v${VERSION} — Environment variable & config validation, security scanning, and documentation generator
48
+
49
+ Usage:
50
+ envguard <command> [options]
51
+
52
+ Commands:
53
+ init Create envguard.config.js template
54
+ validate Validate environment variables against schema
55
+ check Scan .env files for sensitive information
56
+ docs Generate .env.example and documentation
57
+ diff Compare two .env files
58
+
59
+ Options:
60
+ --config <path> Path to config file
61
+ --env-file <path> Path to .env file
62
+ --output <dir> Output directory for docs
63
+ --severity <level> Minimum severity for security check (low|medium|high|critical)
64
+ --recursive Scan subdirectories for .env files
65
+ --force Overwrite existing files
66
+ --allow-failure Exit with code 0 even on errors
67
+ --help Show this help message
68
+ --version Show version number
69
+
70
+ Examples:
71
+ envguard init
72
+ envguard validate
73
+ envguard validate --env-file .env.production
74
+ envguard check --recursive
75
+ envguard docs --output ./docs
76
+ envguard diff .env.development .env.production
77
+ `);
78
+ }
79
+
80
+ function main() {
81
+ const { command, options } = parseArgs(process.argv);
82
+
83
+ if (options.help) {
84
+ printHelp();
85
+ return;
86
+ }
87
+
88
+ if (options.version) {
89
+ console.log(`EnvGuard v${VERSION}`);
90
+ return;
91
+ }
92
+
93
+ switch (command) {
94
+ case 'init':
95
+ runInit({ ...options, cwd: process.cwd() });
96
+ break;
97
+ case 'validate':
98
+ runValidate({ ...options, cwd: process.cwd() });
99
+ break;
100
+ case 'check':
101
+ runCheck({ ...options, cwd: process.cwd() });
102
+ break;
103
+ case 'docs':
104
+ runDocs({ ...options, cwd: process.cwd() });
105
+ break;
106
+ case 'diff':
107
+ runDiff({ ...options, cwd: process.cwd() });
108
+ break;
109
+ default:
110
+ printHelp();
111
+ if (command) {
112
+ console.log(`Unknown command: ${command}`);
113
+ }
114
+ break;
115
+ }
116
+ }
117
+
118
+ main();
@@ -0,0 +1,63 @@
1
+ /**
2
+ * envguard check — scan for sensitive information in .env files
3
+ */
4
+
5
+ const { scanForSecrets } = require('../core/security');
6
+ const { formatFinding, printHeader, colorize } = require('../utils/format');
7
+ const { findEnvFiles, loadEnvFile } = require('../utils/file');
8
+
9
+ function runCheck(options = {}) {
10
+ const cwd = options.cwd || process.cwd();
11
+
12
+ printHeader('EnvGuard — Security Check');
13
+
14
+ // Find .env files
15
+ const envFiles = findEnvFiles(cwd, { recursive: options.recursive });
16
+
17
+ if (envFiles.length === 0) {
18
+ console.log(colorize('No .env files found.', 'yellow'));
19
+ return { findings: [], total: 0 };
20
+ }
21
+
22
+ console.log(`Scanning ${envFiles.length} file(s)...\n`);
23
+
24
+ let allFindings = [];
25
+
26
+ for (const filePath of envFiles) {
27
+ const envObj = loadEnvFile(filePath);
28
+ const result = scanForSecrets(envObj, {
29
+ ignoreKeys: options.ignoreKeys,
30
+ minSeverity: options.severity || 'medium',
31
+ });
32
+
33
+ if (result.findings.length > 0) {
34
+ console.log(colorize(`📄 ${filePath}`, 'bold'));
35
+ for (const finding of result.findings) {
36
+ console.log(` ${formatFinding(finding)}`);
37
+ }
38
+ console.log('');
39
+ allFindings = allFindings.concat(
40
+ result.findings.map((f) => ({ ...f, file: filePath }))
41
+ );
42
+ }
43
+ }
44
+
45
+ if (allFindings.length === 0) {
46
+ console.log(colorize('✓ No sensitive information detected!', 'green'));
47
+ } else {
48
+ console.log(colorize(`Found ${allFindings.length} potential issue(s)`, 'yellow'));
49
+ if (allFindings.some((f) => f.severity === 'critical')) {
50
+ console.log(colorize(' Critical issues found! Do not commit these files.', 'red'));
51
+ }
52
+ }
53
+
54
+ console.log('');
55
+
56
+ if (allFindings.some((f) => f.severity === 'critical') && !options.allowFailure) {
57
+ process.exit(1);
58
+ }
59
+
60
+ return { findings: allFindings, total: allFindings.length };
61
+ }
62
+
63
+ module.exports = { runCheck };