admin管理员组

文章数量:1316540

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

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

Share Improve this question edited May 6, 2020 at 12:27 RobC 25k21 gold badges84 silver badges85 bronze badges asked May 5, 2020 at 16:53 MaxMax 2061 gold badge6 silver badges14 bronze badges 1
  • Worth mentioning that dependencies can't easily be updated during postinstall as npm will override your changes. Though it is possible to do in spawned detached child process which would wait some time for npm install to finish before updating package.json – Pavel Gurecki Commented Jun 7, 2024 at 15:57
Add a ment  | 

3 Answers 3

Reset to default 4

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_mands_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_mands_here>';
    
  5. Finally we JSON.stringify() the json object and overwrite the original package.json file with the new data using fs.writeFileSync().

You can write small script and add mand in scripts or modify package.json

script.js

const json = require("./package.json")
json.scripts["run:watch"] = "npm run watch"
require("fs").writeFileSync(process.cwd() + "/package.json", JSON.stringify(json, null, 2))

package.json

{
"scripts": {
    "postinstall": "node script.js"
  }
}

You can also write sample script inline string, and run using node -e

{
"scripts": {
    "postinstall": "node -e 'const json = require(\"./package.json\"); json.scripts[\"run:watch\"] = \"npm run watch\";require(\"fs\").writeFileSync(process.cwd() + \"/package.json\", JSON.stringify(json, null, 2))'"
  },
}

I had a similar problem. If you need to edit root package.json while your module with "postinstall" script is installed as an npm dependency in some consumer project, then you need to lookup in parent directories as long as no package.json resolved

const fs = require('fs');
const path = require('path');

let rootPath = '../';
while (!fs.existsSync(path.resolve(rootPath, 'package.json'))){
  rootPath += '../';
}
const pkgJsonPath = path.resolve(rootPath, 'package.json');

本文标签: javascriptHow can i edit a packagejson with postinstallStack Overflow