JavaScript Basics: Parse Configuration Text Before Applying It
Reading a dotenv file does not have to change the process environment immediately. util.parseEnv turns dotenv text into an object, leaving a place to validate values before your application uses them. This example keeps all configuration in memory.
Prepare a scratch directory
Tested on Linux with Node.js v24.19.0. You need Node, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. No npm packages or remote services are needed. The .mjs extension selects ES modules.
Keep using the same terminal. Stop if setup fails, before saving the source:
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1Run the example
Save this as parse-settings.mjs:
import assert from 'node:assert/strict';
import { parseEnv } from 'node:util';
const before = process.env.DEMO_PORT;
const values = parseEnv(`
DEMO_PORT=8080
DEMO_DEBUG=false
DEMO_LABEL="release #7"
DEMO_NOTE=ready # ignored comment
`);
assert.equal(process.env.DEMO_PORT, before);
assert.equal(values.DEMO_DEBUG, 'false');
assert.equal(values.DEMO_LABEL, 'release #7');
assert.equal(values.DEMO_NOTE, 'ready');
function portNumber(value) {
if (!/^[0-9]+$/.test(value ?? '')) throw new Error('invalid port');
const port = Number(value);
if (!Number.isInteger(port) || port < 1 || port > 65535) {
throw new Error('invalid port');
}
return port;
}
const settings = {
port: portNumber(values.DEMO_PORT),
debug: values.DEMO_DEBUG === 'true',
label: values.DEMO_LABEL,
};
assert.deepEqual(settings, { port: 8080, debug: false, label: 'release #7' });
assert.throws(() => portNumber('8080junk'), /invalid port/);
assert.throws(() => portNumber('70000'), /invalid port/);
console.log(JSON.stringify(settings));
console.log('Process environment: unchanged');
console.log('Invalid ports: rejected');Run it:
node parse-settings.mjsObserved output:
{"port":8080,"debug":false,"label":"release #7"}
Process environment: unchanged
Invalid ports: rejectedRead the result
The parser returns strings: the text false is still a nonempty string and is truthy in JavaScript. An explicit comparison converts the fixture’s debug setting, while the port validator rejects trailing text and out-of-range values. Quoting keeps the hash inside the label; an unquoted hash starts a comment.
The example accepts only the exact string true as enabling debug; a production configuration validator may instead reject every value other than true and false. Decide that policy explicitly. Parsing is not schema validation, and this example does not load a file or mutate process.env. Keep credentials out of logs; the printed fixture contains only demonstration values.
The official Node.js reference describes the API. The assertions above check the specific fixture and its intended edge case.
Clean up
Remove the source and then the empty practice directory:
rm -- parse-settings.mjs
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirIf the directory is not empty, inspect the remaining files rather than deleting unknown contents.
Acknowledgements
This post was created with assistance from AI.