π» JSON Config Sanity Checker Script
Detect contradictory settings and deprecated keys in your package.json automatically
const fs = require('fs');
const path = require('path');
class JSONConfigSanityChecker {
constructor(configPath) {
this.configPath = configPath;
this.config = null;
this.issues = [];
this.deprecatedKeys = ['engineStrict', 'preferGlobal', 'scripts.test'];
}
loadConfig() {
try {
const rawData = fs.readFileSync(this.configPath, 'utf8');
this.config = JSON.parse(rawData);
return true;
} catch (error) {
this.issues.push(`Failed to load config: ${error.message}`);
return false;
}
}
checkDeprecatedKeys() {
this.deprecatedKeys.forEach(key => {
if (this.getValueByPath(key) !== undefined) {
this.issues.push(`Deprecated key found: ${key}`);
}
});
}
checkTimeoutValues() {
const timeoutProps = ['timeout', 'requestTimeout', 'timeoutMs'];
const timeouts = [];
timeoutProps.forEach(prop => {
const value = this.config[prop];
if (value !== undefined) {
timeouts.push({ prop, value });
// Flag absurdly large timeouts
if (value > 300000) { // 5 minutes
this.issues.push(`Absurd timeout value: ${prop}=${value}ms (${Math.round(value/60000)} minutes)`);
}
}
});
// Check for contradictory timeout values
if (timeouts.length > 1) {
const uniqueValues = [...new Set(timeouts.map(t => t.value))];
if (uniqueValues.length > 1) {
this.issues.push(`Contradictory timeout values: ${timeouts.map(t => `${t.prop}=${t.value}`).join(', ')}`);
}
}
}
getValueByPath(path) {
return path.split('.').reduce((obj, key) => obj && obj[key], this.config);
}
run() {
if (!this.loadConfig()) return this.issues;
this.checkDeprecatedKeys();
this.checkTimeoutValues();
return this.issues;
}
}
// Usage:
// const checker = new JSONConfigSanityChecker('./package.json');
// const issues = checker.run();
// console.log(issues.length > 0 ? issues : 'Config looks sane!');
The Problem: You're Not a Developer, You're a JSON Janitor
Remember when programming was about, you know, programming? Those halcyon days when you'd write algorithms, solve problems, and maybeβjust maybeβget something to work? Those days are gone, my friend. You've been promoted. You are now a Professional Configuration Manager, a JSON Whisperer, a YAML Yodeler. Your primary skill is no longer logic or architecture; it's remembering whether the property is called timeout, requestTimeout, timeoutMs, or pleaseJustWorkAlready in this particular file.
Modern development stacks are like Russian nesting dolls of configuration. You start with a package.json. Then you need a tsconfig.json because TypeScript. Then an .eslintrc.json because your code is ugly. Then a docker-compose.json (or is it .yml? Who knows!). Then a CI config, a linter config for your linter config, and a meta-config to manage the sheer emotional weight of all the other configs. Each file is a tiny kingdom with its own laws, and they're all at war. Your tsconfig.json says "module: commonjs" while your bundler config screams "module: esnext." Your linter demands double quotes but your formatter is a single-quote purist. It's civil war, and your terminal is Gettysburg.
The worst part? The bugs are silent, patient, and smug. They don't show up as clear error messages. No, they manifest as "works on my machine," or "the tests passed but production is on fire," or that classic: "it was working yesterday." You'll lose an afternoon because "port": 0 actually means "pick a random port," not "use port zero." You'll waste a morning because someone, somewhere, set a "timeout": 9999999 years ago as a "temporary fix" and now your API calls hang until the heat death of the universe. The configs are winning. They're in your walls.
The Solution: An Intervention for Your Config Files
I got tired of the madness. I was done being a marriage counselor for my package.json and my webpack.config.js. So I built the JSON Config Sanity Checker. It's not another tool to configure. It's the tool that tells your other tools to get their act together.
At its core, it's brutally simple. You point it at your project directory. It finds all the JSON (and JSON-like) config files. It reads them. And then it performs a group therapy session, highlighting where they disagree, where they're using outdated language, and where they've just plain lost the plot. It's the friend who looks at your "scripts": { "start": "node --inspect --experimental-modules server.js" } and gently asks, "Are you okay?"
This isn't magic. It's just a script that applies common sense and known patterns. It knows that certain keys are deprecated in certain tools. It knows that a port should probably be between 1 and 65535. It knows that if one config says "target: es5" and another says "target: es2022," someone's going to have a bad time. It does the boring, tedious cross-referencing so you don't have to. The humor is just a coping mechanism.
How to Use It: Your Path to Config Nirvana
Using the sanity checker is easier than explaining to your PM why the sprint is blocked by a comma in a JSON file.
Step 1: Install it. It's an npm package, because of course it is. We're not animals.
npm install -g json-config-sanity-checker
# or
npx json-config-sanity-checker@latest ./your-project-pathStep 2: Run it. Navigate to your project's root and unleash the truth.
sanity-check-configsThat's it. It will crawl your project, print a report, and give your configs a grade. An "A" means you might actually be a functional adult. A "D" means your project is held together by hope and stale coffee.
Here's a tiny peek at the kind of logic in the engine, from the main source file:
// A snippet of the absurdity detector
function detectAbsurdValues(obj, filePath) {
const warnings = [];
if (obj.port === 0) {
warnings.push(`π¨ ${filePath}: 'port' is 0. This means 'random port', not 'port zero'.`);
}
if (obj.timeout > 86400000) { // > 1 day in ms
warnings.push(`π€ ${filePath}: 'timeout' is ${obj.timeout}ms. Planning to wait for the next ice age?`);
}
if (obj.host === 'localhost' && obj.port === 443) {
warnings.push(`π ${filePath}: Using HTTPS port (443) with localhost. That's... optimistic.`);
}
return warnings;
}Check out the full source code on GitHub to see how it handles contradictions and deprecations.
Key Features: What This Digital Therapist Does
- Detects Contradictory Settings: Finds conflicts across your config empire. If your TypeScript config targets ES5 but your bundler expects ESM modules, it will call a family meeting.
- Flags Deprecated or Obsolete Keys: Spots those old
"engineStrict"or"experimentalDecorators"(that are now just"decorators") settings you forgot about from a tutorial you read in 2017. - Warns About Absurd Values: Questions your life choices when it sees
timeout: 9999999,port: 0, ormaxBufferSize: "infinite". It's the voice of reason you muted in Slack. - Project Health Score: Gives you a simple grade (A-F) so you can feel shame or pride, like in school. Motivation through guilt is still motivation.
Conclusion: Take Back Control (Or At Least Understand Why You Lost It)
The JSON Config Sanity Checker won't write your code for you. It won't fix your bugs. But it will shine a light into the dark, cobweb-filled corners of your project where configuration gremlins live. It turns hours of tedious cross-checking and Stack Overflow archaeology into a single command. It gives you back the most precious resource in development: time you can spend actually developing, instead of just preparing to develop.
So give it a shot. Run it on your current project. I promise you'll find something. Maybe it's a harmless typo. Maybe it's the reason your staging environment has been subtly broken for six months. Either way, knowledge is power. And slightly less swearing is a nice bonus.
Try it out and restore a fragment of your sanity: https://github.com/BoopyCode/json-config-sanity-checker
Now if you'll excuse me, I need to go configure my linter to ignore the line length in my config files for my config file linter. The work is never done.
Quick Summary
- What: A CLI tool that scans your project's JSON config files for contradictions, deprecated keys, and absurd values before they ruin your day.
π¬ Discussion
Add a Comment