DEV Community

Cover image for One package.json to rule them all
Promise Tochi
Promise Tochi

Posted on

One package.json to rule them all

I am going to start this article with a disclaimer: the title is a clickbait, or maybe not - depends on how you look at it.

Haven gotten that out of the way, let's get to the meat of the matter: creating a useful default package.json.

What you need to know (WYNTK)

If you have gone through the official npm docs, you might know that you can create a default package.json configuration; thereby skipping the CLI questionnaire that follows whenever you run the npm init command.
In fact, you can skip the CLI questionnaire by: opening a terminal somewhere on your PC right now; running npm init -y; if you do not have a .npm-init.js file in your home directory, npm will create a package.json in the folder your terminal is pointing to, the created package.json file will contain this default content:

{
  "name": "",
  "version": ""
}
Enter fullscreen mode Exit fullscreen mode

These are the only required properties for a npm package. However, the thoughtful guys at npm allow us, devs, to change the default configuration or CLI questionnaire. Here's how.

As you might have guessed, to create a default package.json configuration, you need to create a .npm-init.js file in the home directory of your PC.

Creating the .npm-init.js file

Open a terminal(preferably git-bash on windows)anywhere on your PC , and run cd ~ this will point the terminal to your home directory.
Next, run echo "const path = require('path')" >.npm-init.js. This will create a .npm-init.js file in the home directory.
In the same terminal window, type start ".npm-init.js" and hit enter. This will open the npm-init file in your default application for opening Javascript files.

Note that some of these commands might not work on versions of Windows prior to Windows 10

Configuring .npm-init.js

To configure npm's default package.json configuration, we need to expose an object to module.exports from the .npm-init.js file in your home directory. Presently, here's what our npm-init file contains:

const path = require('path')
Enter fullscreen mode Exit fullscreen mode

Edit it, so that it looks like so:

const path = require('path')

module.exports = {
}
Enter fullscreen mode Exit fullscreen mode

Add a default author property

The email and website details are optional in the author property.

const path = require('path')

module.exports = {
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
}
Enter fullscreen mode Exit fullscreen mode

Add a default version property

const path = require('path')

module.exports = {
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1'
}
Enter fullscreen mode Exit fullscreen mode

Add a default description property

const path = require('path')

module.exports = {
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1',
  'description': 'My awesome new project'
}
Enter fullscreen mode Exit fullscreen mode

Add a default license property

const path = require('path')

module.exports = {
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1',
  'description': 'My awesome new project',
  'license': 'MIT'
}
Enter fullscreen mode Exit fullscreen mode

Add a default name property

const path = require('path')

module.exports = {
  'name': 'my_new_project',
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1',
  'description': 'My awesome new project',
  'license': 'MIT'
}
Enter fullscreen mode Exit fullscreen mode

You might be thinking why we have to go through all these trouble and end up with a static default name; "why are you wasting my time man?!"

The good thing is we can improve on this by using the name of the folder where you are running npm init from. We can change the contents of the npm-init file to:

const path = require('path')

module.exports = {
  'name': path.basename(process.cwd()),
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1',
  'description': 'My awesome new project',
  'license': 'MIT'
}
Enter fullscreen mode Exit fullscreen mode

If you are wondering:

process.cwd() method returns the path to the current working directory of the Node.js process

path.basename() methods returns the last portion of a path

We can improve this a little because npm requires that package names be URL friendly, that is, they shouldn't contain spaces or any special charaters. So let's change our .npm-init.js to:

const path = require('path')
const projectName = slugify(path.basename(process.cwd()))

module.exports = {
  'name': projectName,
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1',
  'description': 'My awesome new project',
  'license': 'MIT'
}

function slugify(text) {
  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '')             // Trim - from end of text
}
Enter fullscreen mode Exit fullscreen mode

Adding in some more properties

Next we'll add in default repository, bugs and homepage properties.

Here, I'm assuming that you use git and github for version control. If you are, you can guarantee that your project repository will be at https://github.com/{user or organization name}/{project name}. This leads us to:

const path = require('path')
const projectName = slugify(path.basename(process.cwd()))
const projectUrl = `https://github.com/{your github user name}/${projectName}`

module.exports = {
  'name': projectName,
  'author': 'Promise Tochi <your email@domain.com> (https://your-website.com)',
  'version': '0.0.1',
  'description': 'My awesome new project',
  'license': 'MIT',
  'repository': {
    'type': 'git',
    'url': projectUrl
  },
  'bugs': {
    'url': `${projectUrl}/issues`
  },
  'homepage': projectUrl,
}

function slugify(text) {
  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '')             // Trim - from end of text
}
Enter fullscreen mode Exit fullscreen mode

Trying out our default package.json configuration

Create a new folder on your PC and point your terminal at the folder. In the terminal, run npm init, you should get a CLI prompt similar to this:

npm prompt after running npm init

To use the default configuration, type yes in the terminal and hit the Enter key.

Hopefully, that should save you a few minutes when creating a new npm package in the future, if not I hope you learnt something new. Thanks for reading all the way, happy coding.

This is my first article in 2019 and I hope to write a lot more.

Cover Photo by William Krause on Unsplash
William Krause

Top comments (1)

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Nice but take it one step further, package.json supports variables.