env-drift-check 0.1.6 → 0.1.9
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 +222 -78
- package/dist/cli.js +52 -5
- package/package.json +1 -1
- package/dist/engine/fixer.d.ts +0 -2
- package/dist/engine/fixer.js +0 -19
package/README.md
CHANGED
|
@@ -1,106 +1,172 @@
|
|
|
1
|
-
# env-drift-check
|
|
1
|
+
# env-drift-check
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://www.npmjs.com/package/env-drift-check)
|
|
5
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
<div align="center">
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
**A combined environment drift detector + schema validator for multi-environment setups.**
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
[](https://npmjs.org/package/env-drift-check)
|
|
8
|
+
[](https://npm-stat.com/charts.html?package=env-drift-check)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](#)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
*Say goodbye to "It works on my machine" and hello to bulletproof environment variables.*
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
[Installation](#installation) • [Features](#features) • [Quick Start](#quick-start) • [Configuration](#configuration) • [Usage](#usage) • [Roadmap](#roadmap)
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
</div>
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
| **Type Safety** | String-only values, no validation | **Rich Validation** (Email, URL, Regex) |
|
|
21
|
-
| **Team Onboarding** | "Copy this file from Slack/Docs" | `npx env-drift-check init` & sync |
|
|
22
|
-
| **Configuration Drift** | Desync between dev/stage/prod | **Real-time Detection** against template |
|
|
18
|
+
<div align="center">
|
|
19
|
+
<img src="https://github.com/shashi089/env-drift-check/raw/main/assets/env-drift-check.png" alt="env-drift-check demo" />
|
|
20
|
+
</div>
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 💡 The Problem It Solves
|
|
25
|
+
|
|
26
|
+
Managing `.env` files across a team of developers or multiple deployment environments (development, staging, production) is notoriously error-prone.
|
|
27
|
+
|
|
28
|
+
- **Missing variables** lead to unexpected runtime crashes.
|
|
29
|
+
- **Incorrect data types** (e.g., passing a string `"false"` instead of a proper boolean) cause silent logical bugs.
|
|
30
|
+
- **Onboarding new developers** often involves insecurely sharing `.env` files over Slack, or fighting with an outdated `.env.example`.
|
|
31
|
+
|
|
32
|
+
**env-drift-check** bridges this gap. It provides real-time drift detection to ensure your local environments match the blueprint, an interactive CLI to fix missing variables instantly, and a robust schema validator to enforce types and formats.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🏗 Architecture & Flow
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
graph TD
|
|
40
|
+
A[Developers / CI] -->|Run env-drift-check| B(Engine)
|
|
41
|
+
|
|
42
|
+
subgraph Validation Process
|
|
43
|
+
B -->|1. Parse| C{.env.example}
|
|
44
|
+
B -->|2. Parse| D[Target .env]
|
|
45
|
+
B -->|3. Load Rules| E[envwise.config.json]
|
|
46
|
+
|
|
47
|
+
C --> F{Drift Detector}
|
|
48
|
+
D --> F
|
|
49
|
+
|
|
50
|
+
F -->|Detect Mismatches| G{Compare Keys & Values}
|
|
51
|
+
E -->|Schema Validation| G
|
|
52
|
+
end
|
|
25
53
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
54
|
+
G -->|Interactive Mode| H[Prompt UI: Auto-fix]
|
|
55
|
+
H -->|Update| D
|
|
56
|
+
|
|
57
|
+
G -->|Strict Mode| I[CI/CD Exit Code 1]
|
|
58
|
+
G -->|Report| J[Terminal Output]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 🚀 Features
|
|
64
|
+
|
|
65
|
+
- 🔍 **Environment Drift Detection**: Compares your local `.env` against the base `.env.example` to find missing or extra keys.
|
|
66
|
+
- 🛡️ **Extensive Schema Validation**: Enforce `string`, `number`, `boolean`, `enum`, `email`, `url`, and custom `regex` validations via `envwise.config.json`.
|
|
67
|
+
- 🪄 **Interactive Auto-fix**: A beautiful CLI wizard that prompts you for missing variables and writes them back to your `.env` file automatically.
|
|
68
|
+
- � **Formatting Preservation**: Inherently preserves your original inline comments, empty lines, bespoke spacing, and absolute key ordering when writing updates to your target `.env` file.
|
|
69
|
+
- �🔄 **Multi-Environment Support**: Validate all `.env*` files in your project with the `--all` flag.
|
|
70
|
+
- 🚦 **CI/CD Ready**: Use `--strict` mode to fail the build if variables are missing or invalid, ensuring safe deployments.
|
|
30
71
|
|
|
31
|
-
|
|
72
|
+
### How Does It Compare?
|
|
73
|
+
|
|
74
|
+
| Feature | `dotenv-safe` | `envalid` | **`env-drift-check`** |
|
|
75
|
+
| :--- | :---: | :---: | :---: |
|
|
76
|
+
| **Missing Keys Detection** | ✅ | ✅ | ✅ |
|
|
77
|
+
| **CLI Interactive Mode** | ❌ | ❌ | ✅ |
|
|
78
|
+
| **Schema Validation (Config)** | ❌ | ✅ (Code) | ✅ (JSON) |
|
|
79
|
+
| **Cross-Env File Check** | ❌ | ❌ | ✅ |
|
|
80
|
+
| **No Code Integration Needed**| ❌ | ❌ | ✅ |
|
|
81
|
+
|
|
82
|
+
*(env-drift-check works purely as a CLI tooling step, meaning you don't need to change your application's actual code to validate environment variables!)*
|
|
83
|
+
|
|
84
|
+
---
|
|
32
85
|
|
|
33
|
-
|
|
34
|
-
- [Configuration](./docs/Configuration.md) - Advanced types and `envwise.config.json` schema.
|
|
35
|
-
- [Programmatic API](./docs/API-Reference.md) - Integrating the validation engine into your code.
|
|
86
|
+
## 📦 Installation
|
|
36
87
|
|
|
37
|
-
|
|
88
|
+
Install `env-drift-check` as a development dependency:
|
|
38
89
|
|
|
39
90
|
```bash
|
|
40
|
-
# Install as a dev dependency (Recommended)
|
|
41
91
|
npm install --save-dev env-drift-check
|
|
42
|
-
|
|
43
|
-
# OR install globally
|
|
44
|
-
npm install -g env-drift-check
|
|
45
92
|
```
|
|
46
93
|
|
|
47
|
-
|
|
94
|
+
Or run it directly using `npx` without installing:
|
|
48
95
|
|
|
49
|
-
### 1. Initialize (New Setup)
|
|
50
|
-
Bootstrap your project by creating a configuration and an example environment file.
|
|
51
96
|
```bash
|
|
52
97
|
npx env-drift-check init
|
|
53
98
|
```
|
|
54
99
|
|
|
55
|
-
|
|
56
|
-
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## ⚡ Quick Start
|
|
103
|
+
|
|
104
|
+
### 1. Initialize the Project
|
|
105
|
+
|
|
106
|
+
Bootstrap your repository with a default configuration and `.env.example`:
|
|
107
|
+
|
|
57
108
|
```bash
|
|
58
|
-
npx env-drift-check
|
|
59
|
-
# Specify a custom reference file
|
|
60
|
-
npx env-drift-check --base .env.production
|
|
109
|
+
npx env-drift-check init
|
|
61
110
|
```
|
|
111
|
+
*Output:*
|
|
112
|
+
```text
|
|
113
|
+
✅ Created envwise.config.json
|
|
114
|
+
✅ Created .env.example
|
|
62
115
|
|
|
63
|
-
|
|
64
|
-
If missing variables are found, launch the interactive wizard to fill them in without leaving your IDE.
|
|
65
|
-
```bash
|
|
66
|
-
npx env-drift-check --interactive
|
|
67
|
-
# OR
|
|
68
|
-
npx env-drift-check -i
|
|
116
|
+
Setup complete! Run 'npx env-drift-check -i' to sync your .env file.
|
|
69
117
|
```
|
|
70
118
|
|
|
71
|
-
###
|
|
72
|
-
|
|
119
|
+
### 2. Run an Interactive Check
|
|
120
|
+
|
|
121
|
+
If you just cloned a repo, check for missing environment variables and fill them in right from the terminal:
|
|
122
|
+
|
|
73
123
|
```bash
|
|
74
|
-
npx env-drift-check
|
|
124
|
+
npx env-drift-check -i
|
|
75
125
|
```
|
|
76
126
|
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
Once completed, your `.env` file is automatically updated!
|
|
130
|
+
|
|
131
|
+

|
|
132
|
+
|
|
77
133
|
---
|
|
78
134
|
|
|
79
|
-
##
|
|
135
|
+
## ⚙️ Configuration (`envwise.config.json`)
|
|
80
136
|
|
|
81
|
-
|
|
137
|
+
To unlock the full power of the schema validator, define rules in an `envwise.config.json` file at the root of your project.
|
|
138
|
+
|
|
139
|
+
### Sample Configuration
|
|
82
140
|
|
|
83
141
|
```json
|
|
84
142
|
{
|
|
85
143
|
"baseEnv": ".env.example",
|
|
86
144
|
"rules": {
|
|
87
|
-
"PORT": {
|
|
88
|
-
"type": "number",
|
|
89
|
-
"min":
|
|
90
|
-
"max":
|
|
91
|
-
"description": "
|
|
145
|
+
"PORT": {
|
|
146
|
+
"type": "number",
|
|
147
|
+
"min": 1024,
|
|
148
|
+
"max": 65535,
|
|
149
|
+
"description": "The port the HTTP server binds to"
|
|
150
|
+
},
|
|
151
|
+
"NODE_ENV": {
|
|
152
|
+
"type": "enum",
|
|
153
|
+
"values": ["development", "production", "test", "staging"]
|
|
92
154
|
},
|
|
93
|
-
"
|
|
155
|
+
"DEBUG_MODE": {
|
|
156
|
+
"type": "boolean",
|
|
157
|
+
"mustBeFalseIn": "production"
|
|
158
|
+
},
|
|
159
|
+
"DATABASE_URL": {
|
|
94
160
|
"type": "url",
|
|
95
|
-
"
|
|
161
|
+
"required": true
|
|
96
162
|
},
|
|
97
163
|
"ADMIN_EMAIL": {
|
|
98
|
-
"type": "email"
|
|
99
|
-
"required": true
|
|
164
|
+
"type": "email"
|
|
100
165
|
},
|
|
101
|
-
"
|
|
102
|
-
"type": "
|
|
103
|
-
"
|
|
166
|
+
"API_KEY": {
|
|
167
|
+
"type": "regex",
|
|
168
|
+
"regex": "^sk_(test|live)_[0-9a-zA-Z]{24}$",
|
|
169
|
+
"description": "Stripe API Key format"
|
|
104
170
|
}
|
|
105
171
|
}
|
|
106
172
|
}
|
|
@@ -108,26 +174,104 @@ Define validation rules in `envwise.config.json` to ensure data integrity across
|
|
|
108
174
|
|
|
109
175
|
### Supported Validation Types
|
|
110
176
|
|
|
111
|
-
| Type |
|
|
112
|
-
|
|
113
|
-
| `string` |
|
|
114
|
-
| `number` |
|
|
115
|
-
| `boolean` |
|
|
116
|
-
| `enum` |
|
|
117
|
-
| `email` |
|
|
118
|
-
| `url` |
|
|
119
|
-
| `regex` |
|
|
177
|
+
| Type | Options | Description |
|
|
178
|
+
|---|---|---|
|
|
179
|
+
| `string` | `min`, `max` | Enforce string length bounds. |
|
|
180
|
+
| `number` | `min`, `max` | Enforce numeric value limits. |
|
|
181
|
+
| `boolean` | `mustBeFalseIn` | Ensure value is "true" or "false". Can conditionally reject "true" in specific environments (e.g. production safety). |
|
|
182
|
+
| `enum` | `values: []` | Restrict the variable to a specific set of allowed strings. |
|
|
183
|
+
| `email` | - | Validates against a standard email regex. |
|
|
184
|
+
| `url` | - | Validates standard URI formats. |
|
|
185
|
+
| `regex` | `regex` | Custom regular expression validation. |
|
|
186
|
+
|
|
187
|
+
*(All variables are `required: true` by default unless explicitly specified as `required: false` in their rule).*
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 💻 CLI Usage Examples
|
|
192
|
+
|
|
193
|
+
### Drift Detection Example
|
|
194
|
+
Check the default `.env` file against the default `.env.example`:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx env-drift-check
|
|
198
|
+
```
|
|
199
|
+
*Output Detail:*
|
|
200
|
+
```text
|
|
201
|
+
🚨 1 Mismatched Keys
|
|
202
|
+
PORT: Expected 3000, got 8080
|
|
203
|
+
|
|
204
|
+
❌ 2 Validation Errors
|
|
205
|
+
DATABASE_URL: DATABASE_URL must be a valid URL
|
|
206
|
+
NODE_ENV: NODE_ENV must be one of: development, production
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Multi-Environment Verification
|
|
210
|
+
Check all `.env.development`, `.env.test`, `.env.production` files in parallel:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npx env-drift-check --all
|
|
214
|
+
```
|
|
120
215
|
|
|
121
|
-
|
|
216
|
+
### CI/CD Pipeline Integration (Strict Mode)
|
|
217
|
+
Run the check in your GitHub Actions, GitLab CI, or pre-commit hook. Using `--strict` ensures the process exits with `code 1` on any error.
|
|
122
218
|
|
|
123
|
-
|
|
219
|
+
```yaml
|
|
220
|
+
# .github/workflows/ci.yml
|
|
221
|
+
name: CI
|
|
222
|
+
on: [push, pull_request]
|
|
223
|
+
|
|
224
|
+
jobs:
|
|
225
|
+
validate-env:
|
|
226
|
+
runs-on: ubuntu-latest
|
|
227
|
+
steps:
|
|
228
|
+
- uses: actions/checkout@v3
|
|
229
|
+
# Assuming you have a .env.test you want to validate
|
|
230
|
+
- run: npx env-drift-check .env.test --strict
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 🌟 Best Practices
|
|
236
|
+
|
|
237
|
+
1. **Never commit `.env` or `.env.*` files!** Ensure they are in your `.gitignore`.
|
|
238
|
+
2. **Always commit `.env.example`** and `envwise.config.json` as the source of truth for your team.
|
|
239
|
+
3. **Use the Interactive Mode** (`-i`) locally during development and onboarding.
|
|
240
|
+
4. **Use Strict Mode** (`--strict`) in your CI/CD pipeline to catch missing production variables early.
|
|
241
|
+
5. **Add it to your `postinstall` or `prepare` script** in `package.json` to auto-prompt new developers:
|
|
242
|
+
```json
|
|
243
|
+
"scripts": {
|
|
244
|
+
"prepare": "env-drift-check -i"
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 🗺 Roadmap
|
|
251
|
+
|
|
252
|
+
- [x] Boolean conditional checks (`mustBeFalseIn`)
|
|
253
|
+
- [x] Interactive CLI prompts
|
|
254
|
+
- [x] Multi-file parsing (`--all`)
|
|
255
|
+
- [ ] **JSON Output Mode**: Provide `--format json` for reporting to integrate with other tooling pipelines.
|
|
256
|
+
- [ ] **Secret Scanning**: Add basic entropy checks to prevent weak local passwords from entering production variables.
|
|
257
|
+
- [ ] **Variable Deprecation**: Support marking keys as deprecated to gracefully remove them across teams.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 🤝 Contributing
|
|
262
|
+
|
|
263
|
+
Contributions are always welcome!
|
|
264
|
+
|
|
265
|
+
1. Fork the project
|
|
266
|
+
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
|
267
|
+
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
|
268
|
+
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
|
269
|
+
5. Open a Pull Request
|
|
270
|
+
|
|
271
|
+
---
|
|
124
272
|
|
|
125
|
-
|
|
126
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`).
|
|
127
|
-
3. Commit your changes (`git commit -m 'Add some amazing feature'`).
|
|
128
|
-
4. Push to the branch (`git push origin feature/amazing-feature`).
|
|
129
|
-
5. Open a Pull Request.
|
|
273
|
+
## 📄 License
|
|
130
274
|
|
|
131
|
-
|
|
275
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
|
132
276
|
|
|
133
|
-
|
|
277
|
+
> Built with ❤️ for better Developer Experience by [Shashidhar Naik](https://github.com/shashi089)
|
package/dist/cli.js
CHANGED
|
@@ -16,7 +16,7 @@ const program = new commander_1.Command();
|
|
|
16
16
|
program
|
|
17
17
|
.name("env-drift-check")
|
|
18
18
|
.description("Interactive .env synchronizer and validator")
|
|
19
|
-
.version("0.1.
|
|
19
|
+
.version("0.1.7");
|
|
20
20
|
program
|
|
21
21
|
.command("check", { isDefault: true })
|
|
22
22
|
.description("Check for environment drift (default command)")
|
|
@@ -46,10 +46,57 @@ program
|
|
|
46
46
|
const newValues = await (0, interactive_1.interactiveSetup)(result.missing, baseEnv, config);
|
|
47
47
|
// Merge new values into targetEnv
|
|
48
48
|
const updatedEnv = { ...targetEnv, ...newValues };
|
|
49
|
-
// Write back to file
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
// Write back to file preserving formatting
|
|
50
|
+
const rawContent = fs_1.default.readFileSync(targetPath, "utf-8");
|
|
51
|
+
const lines = rawContent.split(/\r?\n/);
|
|
52
|
+
const eol = rawContent.includes("\r\n") ? "\r\n" : "\n";
|
|
53
|
+
const updatedLines = [];
|
|
54
|
+
const keysToUpdate = { ...newValues };
|
|
55
|
+
for (const line of lines) {
|
|
56
|
+
const trimmed = line.trim();
|
|
57
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
58
|
+
updatedLines.push(line);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const firstEq = line.indexOf("=");
|
|
62
|
+
if (firstEq !== -1) {
|
|
63
|
+
const key = line.slice(0, firstEq).trim();
|
|
64
|
+
if (key in keysToUpdate) {
|
|
65
|
+
const prefix = line.slice(0, firstEq + 1);
|
|
66
|
+
const rawValue = line.slice(firstEq + 1);
|
|
67
|
+
let suffix = "";
|
|
68
|
+
let inQuote = false;
|
|
69
|
+
let quoteChar = "";
|
|
70
|
+
for (let i = 0; i < rawValue.length; i++) {
|
|
71
|
+
const c = rawValue[i];
|
|
72
|
+
if ((c === '"' || c === "'") && !inQuote) {
|
|
73
|
+
inQuote = true;
|
|
74
|
+
quoteChar = c;
|
|
75
|
+
}
|
|
76
|
+
else if (c === quoteChar && inQuote) {
|
|
77
|
+
inQuote = false;
|
|
78
|
+
}
|
|
79
|
+
else if (c === '#' && !inQuote) {
|
|
80
|
+
// Keep spacing before the comment if possible
|
|
81
|
+
const spaceMatch = rawValue.slice(0, i).match(/\s+$/);
|
|
82
|
+
const spaces = spaceMatch ? spaceMatch[0] : " ";
|
|
83
|
+
suffix = spaces + rawValue.slice(i);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
updatedLines.push(`${prefix}${keysToUpdate[key]}${suffix}`);
|
|
88
|
+
delete keysToUpdate[key];
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
updatedLines.push(line);
|
|
93
|
+
}
|
|
94
|
+
if (Object.keys(keysToUpdate).length > 0) {
|
|
95
|
+
for (const [k, v] of Object.entries(keysToUpdate)) {
|
|
96
|
+
updatedLines.push(`${k}=${v}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const newContent = updatedLines.join(eol);
|
|
53
100
|
fs_1.default.writeFileSync(targetPath, newContent);
|
|
54
101
|
console.log(`\n ✅ Updated ${path_1.default.basename(targetPath)} with new values.`);
|
|
55
102
|
// Re-check drift
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "env-drift-check",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Interactive .env synchronizer and validator. Detect environment drift, sync missing variables, and enforce schema validation for seamless developer onboarding.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"env",
|
package/dist/engine/fixer.d.ts
DELETED
package/dist/engine/fixer.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.applyFixes = applyFixes;
|
|
4
|
-
function applyFixes(base, target, result) {
|
|
5
|
-
const fixedEnv = { ...target };
|
|
6
|
-
// Add missing keys
|
|
7
|
-
for (const key of result.missing) {
|
|
8
|
-
if (base[key]) {
|
|
9
|
-
fixedEnv[key] = base[key];
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
// Fix mismatched values (base → target)
|
|
13
|
-
for (const mismatch of result.mismatches) {
|
|
14
|
-
if (mismatch.expected) {
|
|
15
|
-
fixedEnv[mismatch.key] = mismatch.expected;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return fixedEnv;
|
|
19
|
-
}
|