Enhancing npm Script Tasks with Node.js and JavaScript
Tags: developmentworkflow, npmscripts, automation, javascript
Published: 2023-11-07 13:09:34

---
title: Enhancing npm Script Tasks with Node.js and JavaScript
published: true
date: 2023-11-06 14:24:52 UTC
tags: developmentworkflow,npmscripts,automation,javascript
canonical_url: https://medium.com/@seanhaddock_60973/enhancing-npm-script-tasks-with-node-js-and-javascript-3ed8d174d895
---

![](https://cdn-images-1.medium.com/max/1024/0*H--AyqUH-GOvNvgq)
_Photo by Kelly Sikkema on Unsplash_

Npm script tasks are an integral part of any modern JavaScript project. They allow us to automate mundane tasks and prevent us from having to remember a bunch of different commands.

You can accomplish many things without ever leaving package.json. But sometimes you need to do more than can be done in the single line definition of a script task or with multiple tasks.

If you find yourself in that situation you can offload the work to a JavaScript file and define the script task so that it runs that file with Node.js.

### Running a JavaScript file with Node

Running a JavaScript file with an **npm** script task is as simple as:

```
"my-script-task": "node ./my-script.mjs"
```

When you execute npm run my-script-task in the terminal, **npm** will execute this task, which runs the my-script.mjs file using  **Node**.

Why does the file have an .mjs extension? The .mjs extension stands for “Module JavaScript”. It is used to explicitly tell Node that the file should be run as an ES module, which allows us to use ESM syntax. See this post to learn more about JavaScript [Modules](https://dev.to/seanbh/modules-modules-modules-oh-my-fn8).

### Helpful Modules

I have found that I can accomplish a lot by only importing 3 modules:

```
import { execSync } from 'child_process';
import readline from 'readline';
import chalk from 'chalk';
```

If you are using ESLint, it may complain about the import statement unless you add this to your .eslintrc.json file:

```
{
  "files": ["*.mjs"],
  "parserOptions": {
    "sourceType": "module",
    "ecmaVersion": "latest"
  }
}
```

#### execSync

execSync is built into Node and is the workhorse. It is used to execute shell commands which actually accomplish the work we need to perform. Note that it is surrounded by {} in the import statement because it is a named export rather than the default export.

To use it, you just pass in the command that you would normally run in the terminal. For example, if I want to bump the prerelease version of my package, I can do:

```
execSync(`npm version prerelease --preid=test`);
```

#### readLine

readLine also comes with Node and allows for user interaction. For example, we can make the user confirm what they are about to do:

```
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

// make the user confirm what they are about to do
rl.question('Are you sure? (y/n) ', (answer) => {
  if (answer.toLowerCase() === 'y') {
    // do your work
  } else {
    // abort
    rl.close();
  }
});
```

#### chalk

chalk is a third-party [package](https://github.com/chalk/chalk) we can use to style the terminal, so that we can make questions and messages stand out. To use it, you just wrap the text in a function call:

```
chalk.yellowBright(
   ‘This text will be bright yellow’
);
```

You can use this when passing text to both rl.question and console.log:

```
console.log(
   chalk.redBright(
     ‘This text will be bright red’
   )
);
```

With this combination of tools, I’ve been able to greatly enhance our development workflows.

That’s it! I hope you found this useful.

### Bibliography

- [Child process | Node.js v21.1.0 Documentation (nodejs.org)](https://nodejs.org/api/child_process.html#child_processexecsynccommand-options)
- [Readline | Node.js v21.1.0 Documentation (nodejs.org)](https://nodejs.org/api/readline.html)
- [JavaScript modules · V8](https://v8.dev/features/modules#mjs)
- [scripts | npm Docs (npmjs.com)](https://docs.npmjs.com/cli/v10/using-npm/scripts)
- [GitHub — chalk/chalk: 🖍 Terminal string styling done right](https://github.com/chalk/chalk)