molex-env 0.1.0 → 0.2.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/README.md +136 -28
- package/package.json +5 -2
- package/src/index.js +20 -13
- package/src/lib/core.js +15 -1
package/README.md
CHANGED
|
@@ -1,24 +1,35 @@
|
|
|
1
|
-
molex-env
|
|
1
|
+
# molex-env
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/molex-env)
|
|
4
|
+
[](https://www.npmjs.com/package/molex-env)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](package.json)
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
- Deterministic profile merging
|
|
7
|
-
- Typed parsing (boolean, number, json, date)
|
|
8
|
-
- Strict mode for unknown or duplicate keys
|
|
9
|
-
- Origin tracking (file + line)
|
|
10
|
-
- Immutable config objects
|
|
11
|
-
- Optional file watching for reload
|
|
8
|
+
> Native .menv loader with profiles, typing, origin tracking, and optional reload.
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
-
|
|
10
|
+
## Features
|
|
11
|
+
- Deterministic profile merging - Predictable resolution across base and profile files
|
|
12
|
+
- Typed parsing - Booleans, numbers, JSON, and dates with optional casting control
|
|
13
|
+
- Strict mode - Reject unknown keys, duplicates, and invalid lines
|
|
14
|
+
- Origin tracking - See the file and line for every value
|
|
15
|
+
- Immutable config - Optional deep-freeze for safety
|
|
16
|
+
- Live reload - Watch files and reload on change
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
## Install
|
|
19
|
+
```bash
|
|
20
|
+
npm install molex-env
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
```js
|
|
25
|
+
// simplest usage
|
|
26
|
+
require('molex-env').load();
|
|
27
|
+
|
|
28
|
+
// more detailed usage
|
|
17
29
|
const { load } = require('molex-env');
|
|
18
30
|
|
|
19
31
|
const result = load({
|
|
20
32
|
profile: 'prod',
|
|
21
|
-
export: true,
|
|
22
33
|
strict: true,
|
|
23
34
|
schema: {
|
|
24
35
|
PORT: 'number',
|
|
@@ -29,47 +40,144 @@ const result = load({
|
|
|
29
40
|
|
|
30
41
|
console.log(result.parsed.PORT);
|
|
31
42
|
console.log(result.origins.SERVICE_URL);
|
|
43
|
+
console.log(process.menv.PORT);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Setup
|
|
47
|
+
1) Add one or more .menv files in your project root.
|
|
48
|
+
2) Call `load()` during startup.
|
|
49
|
+
3) Optionally enable profile-specific files (e.g. `prod`).
|
|
32
50
|
|
|
33
|
-
File
|
|
51
|
+
## File format
|
|
52
|
+
```env
|
|
53
|
+
# Comments start with #
|
|
54
|
+
PORT=3000
|
|
55
|
+
DEBUG=true
|
|
56
|
+
SERVICE_URL="https://api.example.com"
|
|
57
|
+
METADATA={"region":"us-east-1"}
|
|
58
|
+
START_DATE=2026-02-02
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## File precedence
|
|
34
62
|
1) .menv
|
|
35
63
|
2) .menv.local
|
|
36
64
|
3) .menv.{profile}
|
|
37
65
|
4) .menv.{profile}.local
|
|
38
66
|
|
|
39
|
-
API
|
|
40
|
-
|
|
67
|
+
## API
|
|
68
|
+
|
|
69
|
+
## load(options)
|
|
70
|
+
Load, merge, parse, and validate .menv files.
|
|
71
|
+
|
|
72
|
+
## Options
|
|
41
73
|
- cwd: base directory (default: process.cwd())
|
|
42
74
|
- profile: profile name for .menv.{profile}
|
|
43
75
|
- files: custom file list (absolute or relative to cwd)
|
|
44
76
|
- schema: allowed keys, types, defaults, required
|
|
45
77
|
- strict: reject unknown keys, duplicates, and invalid lines
|
|
46
78
|
- cast: true | false | { boolean, number, json, date }
|
|
47
|
-
-
|
|
79
|
+
- exportEnv: write values to process.env
|
|
48
80
|
- override: override existing process.env values
|
|
81
|
+
- attach: attach parsed values to process.menv (default true)
|
|
49
82
|
- freeze: deep-freeze parsed config (default true)
|
|
50
83
|
- onWarning: function(info) for non-strict duplicates
|
|
51
84
|
|
|
52
|
-
|
|
53
|
-
|
|
85
|
+
## Returns
|
|
86
|
+
```js
|
|
87
|
+
{
|
|
88
|
+
parsed, // typed values
|
|
89
|
+
raw, // raw strings
|
|
90
|
+
origins, // { KEY: { file, line } }
|
|
91
|
+
files // list of resolved files
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## parse(text, options)
|
|
96
|
+
Parse a string of .menv content using the same typing rules as `load()`.
|
|
97
|
+
|
|
98
|
+
## Options
|
|
99
|
+
- schema
|
|
100
|
+
- strict
|
|
101
|
+
- cast
|
|
102
|
+
- freeze
|
|
103
|
+
|
|
104
|
+
## watch(options, onChange)
|
|
105
|
+
Watch resolved files and reload on change.
|
|
106
|
+
|
|
107
|
+
## Arguments
|
|
108
|
+
- options: same as `load()`
|
|
109
|
+
- onChange: function(err, result)
|
|
54
110
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- onChange(err, result)
|
|
111
|
+
## Schema
|
|
112
|
+
You can define simple types or richer objects per key.
|
|
58
113
|
|
|
59
|
-
|
|
114
|
+
```js
|
|
60
115
|
const schema = {
|
|
61
116
|
PORT: { type: 'number', default: 3000 },
|
|
62
117
|
DEBUG: { type: 'boolean', default: false },
|
|
63
118
|
METADATA: { type: 'json' },
|
|
64
|
-
START_DATE: { type: 'date' }
|
|
119
|
+
START_DATE: { type: 'date' },
|
|
120
|
+
SERVICE_URL: { type: 'string', required: true }
|
|
65
121
|
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Schema options per key
|
|
125
|
+
- type: string | boolean | number | json | date
|
|
126
|
+
- default: value used when key is missing
|
|
127
|
+
- required: true | false
|
|
128
|
+
|
|
129
|
+
## Typing rules
|
|
130
|
+
- boolean: true/false (case-insensitive)
|
|
131
|
+
- number: integer or float
|
|
132
|
+
- json: JSON.parse on the value
|
|
133
|
+
- date: Date.parse on the value
|
|
134
|
+
|
|
135
|
+
## Strict mode
|
|
136
|
+
When `strict` is true, the loader rejects:
|
|
137
|
+
- unknown keys not in `schema`
|
|
138
|
+
- duplicate keys across files
|
|
139
|
+
- invalid lines or parse errors
|
|
140
|
+
|
|
141
|
+
## Non-strict mode
|
|
142
|
+
Duplicates are allowed and `onWarning(info)` is called with:
|
|
143
|
+
```js
|
|
144
|
+
{
|
|
145
|
+
key,
|
|
146
|
+
previous: { file, line },
|
|
147
|
+
next: { file, line }
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Examples
|
|
152
|
+
|
|
153
|
+
## Custom files
|
|
154
|
+
```js
|
|
155
|
+
load({
|
|
156
|
+
files: ['config/.menv', 'config/.menv.local'],
|
|
157
|
+
schema: { PORT: 'number' }
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Disable casting
|
|
162
|
+
```js
|
|
163
|
+
load({ cast: false });
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Freeze control
|
|
167
|
+
```js
|
|
168
|
+
load({ freeze: false });
|
|
169
|
+
```
|
|
66
170
|
|
|
67
|
-
Notes
|
|
171
|
+
## Notes
|
|
68
172
|
- Use .menv.local for machine-specific values
|
|
69
173
|
- Use strict mode to detect surprises early
|
|
174
|
+
- Parsed values are attached to process.menv by default (disable with attach: false)
|
|
70
175
|
|
|
71
|
-
Example project
|
|
176
|
+
## Example project
|
|
72
177
|
An example app is included in examples/basic.
|
|
73
178
|
Run it with:
|
|
74
|
-
|
|
75
|
-
|
|
179
|
+
```bash
|
|
180
|
+
cd examples/basic
|
|
181
|
+
npm install
|
|
182
|
+
npm start
|
|
183
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "molex-env",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Native .menv loader with profiles, typing, and origin tracking.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -28,5 +28,8 @@
|
|
|
28
28
|
"bugs": {
|
|
29
29
|
"url": "https://github.com/tonywied17/molex-env/issues"
|
|
30
30
|
},
|
|
31
|
-
"homepage": "https://github.com/tonywied17/molex-env#readme"
|
|
31
|
+
"homepage": "https://github.com/tonywied17/molex-env#readme",
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
32
35
|
}
|
package/src/index.js
CHANGED
|
@@ -3,17 +3,24 @@
|
|
|
3
3
|
const { load, parse } = require('./lib/core');
|
|
4
4
|
const { watch } = require('./lib/watch');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
function loadEntry(options)
|
|
7
|
+
{
|
|
8
|
+
return load(options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Watch resolved .menv files and reload on change.
|
|
13
|
+
* @param {object} options
|
|
14
|
+
* @param {(err: Error|null, result?: {parsed: object, origins: object, files: string[]}) => void} onChange
|
|
15
|
+
* @returns {{close: () => void}}
|
|
16
|
+
*/
|
|
17
|
+
function watchEntry(options, onChange)
|
|
18
|
+
{
|
|
19
|
+
return watch(options, onChange, loadEntry);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = Object.assign(loadEntry, {
|
|
23
|
+
load: loadEntry,
|
|
8
24
|
parse,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @param {object} options
|
|
12
|
-
* @param {(err: Error|null, result?: {parsed: object, origins: object, files: string[]}) => void} onChange
|
|
13
|
-
* @returns {{close: () => void}}
|
|
14
|
-
*/
|
|
15
|
-
watch(options, onChange)
|
|
16
|
-
{
|
|
17
|
-
return watch(options, onChange, load);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
25
|
+
watch: watchEntry
|
|
26
|
+
});
|
package/src/lib/core.js
CHANGED
|
@@ -30,7 +30,7 @@ function buildState()
|
|
|
30
30
|
*/
|
|
31
31
|
function exportToEnv(values, options)
|
|
32
32
|
{
|
|
33
|
-
|
|
33
|
+
if (!options.exportEnv) return;
|
|
34
34
|
for (const [key, value] of Object.entries(values))
|
|
35
35
|
{
|
|
36
36
|
if (!options.override && Object.prototype.hasOwnProperty.call(process.env, key))
|
|
@@ -41,6 +41,18 @@ function exportToEnv(values, options)
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Attach parsed values to process.menv unless disabled.
|
|
46
|
+
* @param {object} values
|
|
47
|
+
* @param {object} options
|
|
48
|
+
* @returns {void}
|
|
49
|
+
*/
|
|
50
|
+
function attachToProcess(values, options)
|
|
51
|
+
{
|
|
52
|
+
if (options.attach === false) return;
|
|
53
|
+
process.menv = values;
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
/**
|
|
45
57
|
* Load .menv files and return parsed values with origins.
|
|
46
58
|
* @param {object} options
|
|
@@ -81,6 +93,8 @@ function load(options = {})
|
|
|
81
93
|
deepFreeze(state.values);
|
|
82
94
|
}
|
|
83
95
|
|
|
96
|
+
attachToProcess(state.values, options);
|
|
97
|
+
|
|
84
98
|
return {
|
|
85
99
|
parsed: state.values,
|
|
86
100
|
origins: state.origins,
|