molex-env 0.2.6 → 0.3.2
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 +83 -49
- package/package.json +4 -2
- package/src/lib/watch.js +35 -1
package/README.md
CHANGED
|
@@ -126,8 +126,8 @@ OPTIONAL_KEY=
|
|
|
126
126
|
|
|
127
127
|
Files are loaded and merged in this order (later files override earlier ones):
|
|
128
128
|
|
|
129
|
-
1. `.menv` - Base configuration
|
|
130
|
-
2. `.menv.local` - Local overrides
|
|
129
|
+
1. `.menv` - Base configuration
|
|
130
|
+
2. `.menv.local` - Local overrides
|
|
131
131
|
3. `.menv.{profile}` - Profile-specific config (e.g., `.menv.prod`)
|
|
132
132
|
4. `.menv.{profile}.local` - Profile + local overrides (e.g., `.menv.prod.local`)
|
|
133
133
|
|
|
@@ -277,23 +277,62 @@ Watch .menv files and reload automatically when they change. Perfect for develop
|
|
|
277
277
|
|
|
278
278
|
**Arguments:**
|
|
279
279
|
|
|
280
|
-
- `options` - Same options as `load()`
|
|
280
|
+
- `options` - Same options as `load()`, including `debug` for automatic change logging
|
|
281
281
|
- `onChange(error, result)` - Callback fired on file changes
|
|
282
282
|
|
|
283
|
-
**
|
|
283
|
+
**Automatic Change Detection:**
|
|
284
|
+
|
|
285
|
+
When `debug: true` is enabled, watch mode automatically logs what values changed on each reload:
|
|
284
286
|
|
|
285
287
|
```javascript
|
|
286
288
|
const { watch } = require('molex-env');
|
|
287
289
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
watch({
|
|
291
|
+
profile: 'dev',
|
|
292
|
+
debug: true, // Automatically logs changes
|
|
293
|
+
schema: {
|
|
294
|
+
PORT: 'number',
|
|
295
|
+
DEBUG: 'boolean',
|
|
296
|
+
SERVICE_URL: 'string'
|
|
297
|
+
}
|
|
298
|
+
}, (err, result) => {
|
|
299
|
+
if (err) {
|
|
300
|
+
console.error('Config reload failed:', err.message);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
console.log('✅ Config successfully reloaded');
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// When you edit .menv files, automatic output:
|
|
307
|
+
// [molex-env] Config reloaded - changes detected:
|
|
308
|
+
// PORT: 3000 → 8080
|
|
309
|
+
// SERVICE_URL: https://api.example.com → https://api.production.com
|
|
310
|
+
// ✅ Config successfully reloaded
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Manual Change Detection:**
|
|
314
|
+
|
|
315
|
+
Without `debug: true`, you can manually detect changes in your callback:
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
let currentConfig;
|
|
319
|
+
|
|
320
|
+
watch({ profile: 'dev' }, (err, result) => {
|
|
290
321
|
if (err) {
|
|
291
322
|
console.error('Config reload failed:', err.message);
|
|
292
323
|
return;
|
|
293
324
|
}
|
|
294
325
|
|
|
295
|
-
|
|
296
|
-
|
|
326
|
+
if (!currentConfig) {
|
|
327
|
+
console.log('Initial config loaded');
|
|
328
|
+
} else {
|
|
329
|
+
// Manually check what changed
|
|
330
|
+
if (currentConfig.PORT !== result.parsed.PORT) {
|
|
331
|
+
console.log(`PORT changed: ${currentConfig.PORT} → ${result.parsed.PORT}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
currentConfig = result.parsed;
|
|
297
336
|
|
|
298
337
|
// Restart your server or update app state here
|
|
299
338
|
if (global.server) {
|
|
@@ -325,10 +364,17 @@ function startServer(config) {
|
|
|
325
364
|
const initial = require('molex-env').load({ profile: 'dev' });
|
|
326
365
|
server = startServer(initial.parsed);
|
|
327
366
|
|
|
328
|
-
// Watch for changes
|
|
329
|
-
watch({
|
|
367
|
+
// Watch for changes with automatic change logging
|
|
368
|
+
watch({
|
|
369
|
+
profile: 'dev',
|
|
370
|
+
debug: true,
|
|
371
|
+
schema: {
|
|
372
|
+
PORT: 'number',
|
|
373
|
+
DEBUG: 'boolean'
|
|
374
|
+
}
|
|
375
|
+
}, (err, result) => {
|
|
330
376
|
if (!err && result.parsed.PORT !== initial.parsed.PORT) {
|
|
331
|
-
console.log('Port changed, restarting...');
|
|
377
|
+
console.log('Port changed, restarting server...');
|
|
332
378
|
server.close(() => {
|
|
333
379
|
server = startServer(result.parsed);
|
|
334
380
|
});
|
|
@@ -657,10 +703,9 @@ console.log(`PORT: ${process.menv.PORT}`);
|
|
|
657
703
|
```javascript
|
|
658
704
|
const { watch } = require('molex-env');
|
|
659
705
|
|
|
660
|
-
let currentConfig;
|
|
661
|
-
|
|
662
706
|
watch({
|
|
663
707
|
profile: 'dev',
|
|
708
|
+
debug: true, // Automatic change detection
|
|
664
709
|
schema: {
|
|
665
710
|
PORT: 'number',
|
|
666
711
|
DEBUG: 'boolean',
|
|
@@ -672,24 +717,15 @@ watch({
|
|
|
672
717
|
return;
|
|
673
718
|
}
|
|
674
719
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
console.log('Initial config loaded');
|
|
678
|
-
} else {
|
|
679
|
-
// Detect what changed
|
|
680
|
-
Object.keys(result.parsed).forEach(key => {
|
|
681
|
-
if (currentConfig[key] !== result.parsed[key]) {
|
|
682
|
-
changed.push(`${key}: ${currentConfig[key]} → ${result.parsed[key]}`);
|
|
683
|
-
}
|
|
684
|
-
});
|
|
685
|
-
|
|
686
|
-
if (changed.length > 0) {
|
|
687
|
-
console.log('Config updated:', changed.join(', '));
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
currentConfig = result.parsed;
|
|
720
|
+
console.log('Config reloaded and ready to use');
|
|
721
|
+
// result.parsed has the new values
|
|
692
722
|
});
|
|
723
|
+
|
|
724
|
+
console.log('Watching for changes...');
|
|
725
|
+
// Output on file change:
|
|
726
|
+
// [molex-env] Config reloaded - changes detected:
|
|
727
|
+
// DEBUG: false → true
|
|
728
|
+
// API_URL: https://api.example.com → https://api.dev.local
|
|
693
729
|
```
|
|
694
730
|
|
|
695
731
|
### Validation and Error Handling
|
|
@@ -730,35 +766,19 @@ try {
|
|
|
730
766
|
|
|
731
767
|
## Best Practices
|
|
732
768
|
|
|
733
|
-
### Git Configuration
|
|
734
|
-
|
|
735
|
-
Add to `.gitignore`:
|
|
736
|
-
```gitignore
|
|
737
|
-
# Keep base configs in git
|
|
738
|
-
# .menv
|
|
739
|
-
# .menv.dev
|
|
740
|
-
# .menv.prod
|
|
741
|
-
|
|
742
|
-
# Ignore local overrides (machine-specific, secrets)
|
|
743
|
-
.menv.local
|
|
744
|
-
.menv.*.local
|
|
745
|
-
```
|
|
746
|
-
|
|
747
769
|
### Environment Strategy
|
|
748
770
|
|
|
749
771
|
```
|
|
750
772
|
Development: .menv + .menv.local
|
|
751
773
|
Staging: .menv + .menv.staging
|
|
752
|
-
Production: .menv + .menv.prod + .menv.prod.local
|
|
774
|
+
Production: .menv + .menv.prod + .menv.prod.local
|
|
753
775
|
```
|
|
754
776
|
|
|
755
777
|
### Security Tips
|
|
756
778
|
|
|
757
|
-
- ✅ **DO** use `.menv.local` for secrets and add to `.gitignore`
|
|
758
779
|
- ✅ **DO** use `strict: true` in production to catch unknown keys and configuration errors
|
|
759
780
|
- ✅ **DO** use `debug: true` during development to understand file precedence
|
|
760
781
|
- ✅ **DO** validate sensitive values (URLs, ports, etc.) after loading
|
|
761
|
-
- ❌ **DON'T** commit production secrets to git
|
|
762
782
|
- ❌ **DON'T** use `exportEnv: true` if you need immutable config
|
|
763
783
|
|
|
764
784
|
### Performance
|
|
@@ -794,11 +814,25 @@ The example demonstrates:
|
|
|
794
814
|
|
|
795
815
|
**Problem:** Getting errors about unknown keys when loading config.
|
|
796
816
|
|
|
797
|
-
**
|
|
817
|
+
**Cause:** You have a key in your `.menv` file that isn't defined in your schema, and `strict: true` is enabled.
|
|
818
|
+
|
|
819
|
+
**Solution:** Either add the key to your schema or disable strict mode:
|
|
798
820
|
```javascript
|
|
799
|
-
|
|
821
|
+
// Option 1: Add missing key to schema
|
|
822
|
+
load({
|
|
823
|
+
strict: true,
|
|
824
|
+
schema: {
|
|
825
|
+
PORT: 'number',
|
|
826
|
+
YOUR_MISSING_KEY: 'string' // Add this
|
|
827
|
+
}
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
// Option 2: Disable strict mode to allow unknown keys
|
|
831
|
+
load({ strict: false });
|
|
800
832
|
```
|
|
801
833
|
|
|
834
|
+
> **Note:** This is different from "required" - unknown keys exist in your file but not in schema. Required keys exist in schema but not in your file.
|
|
835
|
+
|
|
802
836
|
### Values are strings instead of typed
|
|
803
837
|
|
|
804
838
|
**Problem:** `PORT` is `"3000"` (string) instead of `3000` (number).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "molex-env",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Native .menv loader with profiles, typing, and origin tracking.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"README.md"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "node --test"
|
|
12
|
+
"test": "node --test",
|
|
13
|
+
"publish:npm": "npm publish",
|
|
14
|
+
"publish:github": "npm publish --registry=https://npm.pkg.github.com"
|
|
13
15
|
},
|
|
14
16
|
"keywords": [
|
|
15
17
|
"env",
|
package/src/lib/watch.js
CHANGED
|
@@ -27,6 +27,7 @@ function watch(options, onChange, load)
|
|
|
27
27
|
const basenames = new Set(files.map((file) => path.basename(file)));
|
|
28
28
|
const watchers = [];
|
|
29
29
|
let timer = null;
|
|
30
|
+
let previousConfig = null;
|
|
30
31
|
|
|
31
32
|
const trigger = () =>
|
|
32
33
|
{
|
|
@@ -35,7 +36,40 @@ function watch(options, onChange, load)
|
|
|
35
36
|
{
|
|
36
37
|
try
|
|
37
38
|
{
|
|
38
|
-
|
|
39
|
+
// Disable file precedence debug during reload to avoid conflicts with watch change detection
|
|
40
|
+
const reloadOptions = { ...options, debug: false };
|
|
41
|
+
const result = load(reloadOptions);
|
|
42
|
+
|
|
43
|
+
// Auto-detect changes if debug mode was enabled
|
|
44
|
+
if (options.debug && previousConfig)
|
|
45
|
+
{
|
|
46
|
+
const changes = [];
|
|
47
|
+
for (const key in result.parsed)
|
|
48
|
+
{
|
|
49
|
+
const oldValue = previousConfig[key];
|
|
50
|
+
const newValue = result.parsed[key];
|
|
51
|
+
|
|
52
|
+
// Compare values (handle dates and objects)
|
|
53
|
+
const oldStr = oldValue instanceof Date ? oldValue.toISOString() : JSON.stringify(oldValue);
|
|
54
|
+
const newStr = newValue instanceof Date ? newValue.toISOString() : JSON.stringify(newValue);
|
|
55
|
+
|
|
56
|
+
if (oldStr !== newStr)
|
|
57
|
+
{
|
|
58
|
+
changes.push({ key, old: oldValue, new: newValue });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (changes.length > 0)
|
|
63
|
+
{
|
|
64
|
+
console.log('[molex-env] Config reloaded - changes detected:');
|
|
65
|
+
changes.forEach(({ key, old, new: newVal }) =>
|
|
66
|
+
{
|
|
67
|
+
console.log(` ${key}: ${old} → ${newVal}`);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
previousConfig = { ...result.parsed };
|
|
39
73
|
onChange(null, result);
|
|
40
74
|
} catch (err)
|
|
41
75
|
{
|