How to make a forked dependency in package.json run its prepare script during npm install? - npm

I forked a NPM module and modified it in my fork. In my fork, the command gulp needs to be run to compile the module. Running this command will output the file ical-expander-dist.js into the dist folder. This file should become part of the fork package.
The adjusted package.json in my fork looks like this:
{
"name": "ical-expander",
"version": "1.1.1",
"description": "ICS / iCal / iCalendar parser / expander",
"main": "dist/ical-expander-dist.js", // adjusted path
"scripts": {
"prepare": "gulp" // added script
},
// [SNIP] - excluded irrelevant lines
"files": [
"dist/ical-expander-dist.js" // adjusted path
]
}
Now I want to make my fork a dependency of another project.
{
"name": "otherproject",
"title": "Other Project",
// [SNIP] - excluded irrelevant lines
"dependencies": {
"ical-expander": "github:haukepribnow/ical-expander"
}
// [SNIP] - excluded irrelevant lines
}
After executing npm install in otherproject's root folder, the path ./node_modules/ical-expander will contain the files LICENSE, README.md and package.json. It will however not contain dist/ical-expander-dist.js.
It looks like the prepare script of my ical-expander fork is not being run during npm install in otherproject.
So my question boils down to: How can I make sure that preparation scripts for compiling my fork are being run when executing npm install in a project that has my fork as one of its dependencies?

Sometimes it's very simple: Make sure to use npm version 5.0.0 or higher.
According to the npm changelog, npm install will run dependencies' prepare scripts correctly from 5.0.0 on.

Related

lerna publish and npm pack failing to package all the files in "dist" folder

I am trying to build my first Angular Component package using lerna and it was working pretty well until I realized I had to add "ng-packagr" to get all of the HTML bundled inline with the rest of the code. After adding that support and getting it to work now all of a sudden my files are not getting published into the tarball.
Here is my package.json
{
"name": "#custom/core",
"version": "0.0.7",
"description": "Test",
"main": "./dist/bundles/custom-core.umd.min.js",
"module": "./dist/esm2015/custom-core.js",
"typings": "./dist/index.d.ts",
"$schema": "./node_modules/ng-packagr/package.schema.json",
"ngPackage": {
"lib": {
"entryFile": "./src/index.ts"
},
"whitelistedNonPeerDependencies": [
"."
]
},
"scripts": {
"build": "ng-packagr -p package.json"
},
"files": [
"dist"
],
...
My dist folder contains all kinds of folders like this:
But then when I run a lerna publish or npm pack this is what happens:
As you can see only 1 file gets added to the tarball...
Does anyone know why this is happening all of a sudden? I've tried playing around with my .gitignore thinking maybe it was forcing the packaging to ignore these other files but it wasn't that.
UPDATE
Ok so I found that the culprit is ng-packagr. When I run my npm run build which uses ng-packagr -p package.json to build the different module packages, that CLI is also generating a package.json that goes inside of my dist folder. When the npm pack or lerna publish attempt to package everything using a package.json they must be looking at the generated on in dist rather than the one in the folder above it.
I'm not sure how I should be fixing this.
My solution was to abandon my plan to use the files key in the package.json file and to instead use a .npmignore file. Here is a copy of mine:
# Node generated files
node_modules
npm-debug.log
assets
package-lock.json
# aot files
aot
# OS generated files
Thumbs.db
.DS_Store
# Ignored files
*.ts
!*.d.ts
tsconfig.json
tsconfig-aot.json
tslint.json
*.tgz
config
src

npm install dependencies of local modules

I'm having trouble using npm with a local module. My project's structure looks like:
package.json
local_module/
- package.json
- gulpfile.json
gulpfile.js
The main project's package.json is essentially:
{
"dependencies": {
"local_module": "file:local_module"
},
"devDependencies": {
"gulp": "..."
}
}
The local module's package.json is essentially:
{
"scripts": {
"prepublish": "gulp release"
},
"devDependencies": {
"gulp": "..."
}
}
My intention is keep my project modular by keeping local_module as its own package that is used as a dependency for the main project. I want to run npm install in the main project and use local_module from node_modules. However, local_module needs gulp installed to run the prepublish step, and when running npm install from the main project, it does not install the dependencies for local_module, and so gulp isn't installed, so it can't do the prepublish step.
Several questions like this have been asked, like NPM doesn't install module dependencies, but many are old and there are so many versions of npm that I can't get a clear solution.
How can I get npm to install local_module's dependencies before the prepublish step? I tried adding a preinstall step for the main project, e.g.
"preinstall": "cd local_module && npm install"
But it seems npm tries to run the prepublish step of local_module before running the preinstall for the main project. I want a solution that will do this in one npm install step rather than having a separate step before this to do npm install in the local module.
I have found a solution that will work for me in the immediate future. I changed local_module's package.json to:
{
"scripts": {
"prepublish": "npm install --ignore-scripts && gulp release"
},
"devDependencies": {
"gulp": "..."
}
}
When npm install is run from the main project, the prepublish step is run first in local_module, so I force prepublish to also do an install so that gulp is available to do the actual prepublish step. This is hardly ideal however.

Install NPM dependancies for sub package which is nested within my main project?

I have a main package.json for my project. I also have a component within my project which I'm publishing to NPM, so that requires its own package.json.
package.json
index.html
-folder
--component-folder
---package.json
Both package.json files define dependancies. At the moment I have to run npm install from both my project root and from component-folder. Is there a way of making it install dependancies for both when its only run from the project root?
Try using subpackage:
{
"name": "my-awesome-project",
"version": "2.5.1",
"subPackages": [
"packages/sub-package-1",
"packages/sub-package-2"
]
}
https://www.npmjs.com/package/subpackage

“No readme data” with package.json not in root folder

I have a directory structure with a Build and a Source Folder.
Alls things Grunt, npm, bower and composer live in the Build Folder, All sources live in the Source Folder and all Things Project (i.e. README.md) live in the root of the project.
- myProject
+ Build
Gruntfile.js
bower.json
package.json
...
+ Source
+ vendor
+ src
...
README.md
composer.json
So now if i run npm install in the build Folder, npm claims my Project is missing a README, which is not true.
Also i am simply using the package.json to install npm dependencies for grunt. My project is not a npm project.
Can i somehow tell npm that it is not run in the root of the project?
Or can i tell npm that my project is not a npm project?
You have two options here:
If you have no intention to publish this package to npm then you can set private to true as described here
You can set the location of readme with the readme property as seen below:
{
"name": "app_name",
"version": "0.0.1",
"author": "your name here",
"description": "A descriptive description",
"license": "MIT",
"readme": "../README.md"
}
As far as I can tell, there's no validation on the readme property but it will squelch the warning.

Install only one package from package.json?

Suppose that somewhere in my package.json I have:
"dependencies": {
"bower": "1.0.0",
// zillion other dependencies
}
Is there a way to make npm install only bower#1.0.0 from my package.json? Like so: npm install --only bower.
My goal is to make npm install and bower install run simultaneously.
As a workaround you may use something like:
$ node -pe "require('./package').dependencies.bower"
// → 1.0.0
$ npm install bower#$(node -pe "require('./package').dependencies.bower")
// npm install bower#1.0.0
// or with jq
$ npm install bower#$(< package.json jq -r '.dependencies.bower')
Where -e/--eval flag evaluates passed string and -p/--print prints result of eval.
💡 Please consider other answers as well since this one may be outdated.
As #atalantus noted in comment, the accepted answer doesn't work on newer version of NPM. Working solution for newer versions (verified on NPM 6.13.4) is:
npm install --no-package-lock --no-save bower#1.0.0
This will install bower and all its dependencies, but prevents installation of anything else you might have in package.json. It also doesn't create or modify existing package-lock.json.
From npm documentation:
The --no-package-lock argument will prevent npm from creating a package-lock.json file. When running with package-lock's disabled npm will not automatically prune your node modules when installing.
--no-save: Prevents saving to dependencies.
Combining this with Anton Rudeshko's approach to find out version in package.json, the final solution is:
VERSION_BOWER=`node -p -e "require('./package.json').dependencies.bower"`
npm install --no-package-lock --no-save bower#"$VERSION_BOWER"
Update 2023
Alternative solution I've just used is to temporarily modify package.json to only keep the dependency you need. That can be done quite easily with help of jq
Given package.json
{
"name": "sample",
"main": "src/index.js",
"dependencies": {
"bower": "1.0.0",
"foo": "^1.2.3",
"bar": "^4.5.6",
},
"devDependencies": {
"baz": "^10.20.30",
}
}
Let's first modify it with jq to only keep bower
cat package.json| jq 'del(.devDependencies) | .dependencies |= {bower:.bower}'
Gives us
{
"name": "sample",
"main": "src/index.js",
"dependencies": {
"bower": "1.0.0"
}
}
by deleting devDependencies completely and leaving only bower in dependencies.
Next up you would want to overwrite package.json with this new, version, but you can't do it directly like this
cat package.json | jq 'del(.devDependencies) | .dependencies |= {bower:.bower}' > package.json
because the file gets overwritten before it's fully read. Instead you need to buffer the output stream of jq command, simplest solution just storing it in variable, and then overwriting the original file
updated=`cat package.json | jq 'del(.devDependencies) | .dependencies |= {bower:.bower}'`
echo $updated > package.json
And package.json now reads:
cat package.json
{
"name": "sample",
"main": "src/index.js",
"dependencies": {
"bower": "1.0.0"
}
}
Run npm install now and you only install bower#1.0.0.
Obviously not always we can afford to modify the file, but you could also back-up the original file, etc. Main point is here how to easily modify json file thanks to jq rather than playing magic tricks with sed :-)
Seeing as with newer versions of NPM the previous solutions don't work anymore, I came up with this:
npm i -g --prefix=$(pwd) bower # $(pwd) = current directory, UNIX only
node bin/bower
Installing a package globally allows you to specify a "prefix" - a directory where the package will be installed. Here I just put the current directory as the folder I want the package to appear in. In CI, this will probably be your repo root.
Keep in mind this will ignore your package.json version and just download the latest one. If you need a specific version, just use bower#someversion instead.
An alternative solution is just rm package.json && npm i bower, or mv package.json _package.json && npm i bower if you want to restore it later