javascriptnpmpackage.jsonnpm-scriptspost-install

How can i edit a package.json with postinstall


I have created a package on npm that create a "scss directory stucture" and I would like to copy/add custom scripts to the package.json file at the root of the project.

MY-PROJECT
├── node_modules
├── scss
└── package.json <--

All I was able to do, is to copy a file name "package.json" to the local directory but if there is already one, it will overwrite it.

Obvisously i do not want to overwrite that file, but only add scripts like "npm run watch". So the user would be able to start working on its project right away without having to write those scripts himself.

Thanks for the help


Solution

  • Utilize the following node.js script:

    post-install.js

    const saveFile = require('fs').writeFileSync;
    
    const pkgJsonPath = require.main.paths[0].split('node_modules')[0] + 'package.json';
    
    const json = require(pkgJsonPath);
    
    if (!json.hasOwnProperty('scripts')) {
      json.scripts = {};
    }
    
    json.scripts['watch'] = '<some_commands_here>';
    
    saveFile(pkgJsonPath, JSON.stringify(json, null, 2));
    

    package.json

    In the scripts section of your package.json define your postinstall script as follows:

    {
      "scripts": {
        "postinstall": "node post-install"
      }
    }
    

    Note: The npm script (above) assumes post-install.js resides in the same directory as your package.json file.


    Explanation:

    1. In the line of code that reads:

      const pkgJsonPath = require.main.paths[0].split('node_modules')[0] + 'package.json'
      

      we obtain the path to the package.json for the project that is consuming your npm package and assign it to the pkgJsonPath variable.

      • require.main.paths returns an Array of pathnames.

      • We obtain the pathname at index 0 and split() it using node_modules as the separator.

      • The resultant array element at index 0 gives us the pathname of the project directory, (i.e. the pathname of the project that is consuming your npm package).

      • Finally the package.json string is concatenated using the plus operator (+).

    2. Next we require the package.json file and assign the parsed JSON to the json variable.

    3. We then check whether the package.json has a scripts key, and if it doesn't we create an a new scripts property/key and assign it an empty object, i.e.

      if (!json.hasOwnProperty('scripts')) {
        json.scripts = {};
      }
      
    4. The following part is where we define the custom npm script to be added to the package.json file - you'll need to change this part as necessary:

      json.scripts['watch'] = '<some_commands_here>';
      
    5. Finally we JSON.stringify() the json object and overwrite the original package.json file with the new data using fs.writeFileSync().