Programmatically Edit Any File in NodeJS
NodeJS is useful for way more than just installing packages or running servers. For instance, using the npx
package and Node’s filesystem methods, you can create complex logic for interacting with files as if they were plain-ol’ Javascript objects. No BASH required.
This little piece documents a way to programmatically modify package.json
. In this example I append JSON output to my existing test script and add a new script into package.json
Using this pattern and these methods, you can do basically anything you want inside your repo.
Install NPX
npm i -g npx
Create a File for your NPX Script
touch fs-demo.js
Load package.json as an object
const fs = require('fs');
const pkgJson = require('./package.json’);
CRUD your key/value pairs like any object
const { test: testScript } = packageJson.scripts;
if(testScript.includes('--outputFile')){
console.log('No changes needed in test script')
} else{
packageJson.scripts.test = testScript + ' --json --outputFile=jest-test-results.json';
console.log('Updating test script');
}
packageJson.scripts.foo = 'bar';
Write the updated ‘package.json’ to fs
fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2));
console.log('Package saved');
NOTE: the additional arguments to JSON.stringify()
are there to pretty-print the result. Otherwise you’ll wind up with an unreadable JSON string for the next engineer to prettify. Please practice good coding etiquette ;)
Finally: Run the NPX Script
npx ./fs-demo.js
Here’s the Whole Shebang
const fs = require('fs');
const packageJson = require('./package.json');
const { test: testScript } = packageJson.scripts;
if(testScript.includes('--outputFile')){
console.log('No changes needed in test script')
} else{
packageJson.scripts.test = testScript + ' --json --outputFile=jest-test-results.json';
console.log('Updating test script');
}
packageJson.scripts.foo = 'bar';
fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2));
console.log('Package saved');
Gotcha: Working with Arbitrary File Types
Working with other file types (say, .gitignore
) can be a problem because require
doesn’t know what to do with them. It only thinks in terms of Javascript.
To get around this, you can fs.read
files into memory and interact with them like strings:
const gitIgnore = fs.readFileSync('./.gitignore', 'utf-8');
You can then chop up your string however you want. For instance in the example below, you can split it on the new-line.
let myGitIgnore = gitIgnore.split(/\n/);
At this point all you’re doing is transforming string data. When you’re done, you reassemble it like above and simply fs.write
back to your target file.