npm ci crashes with local packages - node.js

I'm using nodejs 10 and npm 6.9.
I wanted to create two projects. One dependant from the other.
So I created these folders
-myapps
---parentproj
---childproj
then I did these steps:
go into parentproj folder
execute "npm create"
execute "npm install fs-extra" (for adding a third party reference)
go into childproj folder
execute "npm create"
execute "npm install ..\parentproj"
now the childproj folder contains both the package.json and package-lock.json file.
If I run "npm ci" I get this error
"npm ERR! fs-extra not accessible from parentproj"
Moreover, if I run "npm ls" from childproj folder I get this message
`-- UNMET DEPENDENCY fs-extra#^7.0.1
Am I doing something wrong?
Which is the correct way for working with local packages without publishing them?
regards.

Related

NPM 7 workspaces - how to install new package in workspace?

If I have a NPM 7 workspace like this:
root
- submodule0
- submodule1
- submodule2
and I navigate to the submodule0 directory and run npm i somepackage it seems to "break" the workspace by creating a new package-lock.json in the submodule0 directory and installing all the dependencies there. In other words, it just does the old behavior that existed before I created the workspace.
I was hoping for a command similar to lerna where I can install a new package in submodule0 from the root. Something like:
npm i somepackage --scope submodule0
So far, the only workaround I can find is to edit the submodule0 package.json and add the somepackage manually. Then run npm i from the root. Obviously this is not ideal because I need to look up the #latest version, navigate to the subdirectory, open the package.json, etc. etc. as opposed to just typing one line in the root.
Workspace support for npm install and npm uninstall was added in npm v7.14.0. You can now just do:
npm i somepackage --workspace=submodule0
Uninstalling modules has been the biggest pain, so this is really exciting. The npm team seems to be slowly adding support to commands one by one. Follow updates here: https://github.com/npm/cli/blob/latest/CHANGELOG.md.
I'm also baffled with why npm workspaces has been released without this functionality.
My current workaround uses the add-dependencies package, which adds dependencies to a declared package.json file, whilst skipping the installation process.
npm i add-dependencies -g
Then, from top level of the monorepo, you can run:
npx add-dependencies ./submodule0/package.json somepackage && npm i
Hopefully a --workspace argument will be added to npm i soon to avoid this faff.
Please refer to the answer of mattwad above if you have NPM v7.14.0 or above
Original answer
I wasn't quite happy with the suggestions, but combined all of them to use it in a npm script without any dependencies:
{
"add": "npm install --package-lock-only --no-package-lock --prefix",
"postadd": "npm install"
}
This can be used like following: npm run add -- submodule0 somepackage
Add only into package.json
U can use this to install package only into package.json ( you don't need external dependencies )
npm i --prefix packages/test --save --package-lock-only --no-package-lock express
followed by npm i to install specified dependency into mono repository root node_modules
Lerna
Also can use lerna to use workspace name to install dependency into
package.json
{
"name": "mono",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"wsi": "function workspaceinstall() { ( scope=$1; shift; lerna exec --scope \"$scope\" -- npm install --package-lock-only --no-package-lock \"$#\") }; workspaceinstall"
},
"author": "",
"license": "ISC",
"workspaces": {
"packages": [
"packages/**"
]
}
}
lerna.json
{
"version": "1.0.0",
"npmClient": "npm",
"packages": ["packages/**"]
}
npm run wsi [workspace name] [dependency name to install]
npm run wsi #workspace/test express
npm run wsi #workspace/test express --save-prod
npm run wsi #workspace/test #types/express --save-dev
wsi script only modify package.json for provided workspace name, to actually install dependencies u have to run npm i
In my case, which is similar to yours, I deleted all dependencies from all the inner projects, deleted also the package-lock.json, and installed everything in the root.
/
node_modules
package.json >> all dependencies
package-lock.json >> the only lock file that exists in the repo
/packages
/A
package.json >> no dependencies
-- no package-lock.json
/B
package.json >> no dependencies
-- no package-lock.json
/C
package.json >> no dependencies
-- no package-lock.json
This way, the node_modules folder ONLY resides on the root, and also the package-lock.json file is in the root.
If I allowed to have each project it's own package-lock.json I started seeing installation and runtime errors (because each project could have its own node_modules and its own version of a dependency).
This is the best way I see it works.
After trying to use the npm install with the --prefix --save --package-lock-only --no-package-lock options, npm always give the the error E404 - Not Found for my own packages of the monorepo that are not yet published to a registry. So even when trying to install external packages it fails because of my current dependencies in the package.json.
To workaround this issue I ended up with a mix of the previous suggestions:
"scripts": {
"add": "add-dependencies $npm_config_scope/package.json",
"postadd": "npm i",
},
"devDependencies": {
"add-dependencies": "^1.1.0"
},
Then I can do:
npm run add --scope=packages/app express
npm run add --scope=packages/core eslint jest -D
This works fine for installing external packages. To install my own packages that lives inside the monorepo, I still have to manually edit the package.json, otherwise I get the package not found error.

Package.json for server and client

I want to install package.json for client side from my server side package.json as the server side is using node and client side is using angular 2
directory structure
server-app
--bin
--node_modules
--package.json
--client-app
--app
--node_modules
--package.json
now the problem is:
I have to run this command npm install from server app folder and also from server-app/client-app folder separately this will create deployment issues
what I want is to run only one time npm install from i.e server-app and it will automatically install the server-app package.json and client-side-app
package.json too.
Any help will be highly appreciated
I think what you need is a npm module called concurrently.
With concurrently installed in your root folder you can run multiple custom npm scripts.
For example: you can create 2 separate scripts that are installing the dependencies (client-install and server-install) and then create install-all-deps script that will run both scripts one after another and install all deps in both directories.
{
"scripts": {
"client-install" : "cd client && npm install",
"server-install" : "cd server && npm install",
"install-all-deps": "concurrently \"npm run server-install\" \"npm run client-install\""
}
}
Here is the npm module https://www.npmjs.com/package/concurrently. Quoting doc:
Run multiple commands concurrently. Like npm run watch-js & npm run
watch-less but better.
Hope this helps.
Structure your application in the following way,
app
--server-app
--client-app
--node_modules
--package.json
This way you can have single package.json file

Prepublish not working as expected

I am testing on npm scripts to build my project dependency.
My idea comes from https://github.com/ParsePlatform/parse-server which impressed me by code in repository doesn't mean code in node_modules after npm install.
Below is my testmodule structure
src/index.js
package.json
and this is my package.json content
{
"name": "testmodule",
"version": "1.0.0",
"description": "",
"main": "lib/index.js",
"scripts": {
"build": "babel src/ -d lib/",
"prepublish": "npm run build"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-core": "^6.18.2"
}
}
and this is structure I expect after run npm install testmodule
node_modules/testmodule/lib/index.js
node_modules/testmodule/package.json
which is src folder should not be here.
But after I run npm install, it is exactly the same as when I push to my git repository.
Please take note that I am using GitLab in my own server.
So my questions are:
Is there anything that i'm missing to make prepublish run?
Which part of parse-server code makes the src folder and other files not there after install?
How are you running npm install?
According to the documentation on npm scripts, the prepublish script is run "BEFORE the package is published. (Also run on local npm install without any arguments.)". It seems clear that the prepublish script is only run on npm publish or npm install <local directory>.
If you are trying to install directly from your local gitlab server via a URL, this will not work - the script will not be run. The solution would be to install locally unless you're willing to open source your package & push it to the npm repository or pay for a private npm repository. This is what I have done during development of packages before they're ready to be made public.

grunt build nodejs - multiple projects

I'am searching for a good way for building a multi project application.
At the moment I have this structure:
Every app is a nodejs application
- parent folder (git root)
|- app1
|-- app1-backend
|-- app1-frontend
|- app2
|- app3
at the moment i need to install every app by hand with the following steps:
install npm modules with npm install
install typings with typings install
compile app with tsc
every app folder contains the following: (app1-backend, app1-frontend, app2, app3)
tsconfig.json, package.json, typings.json
should i automate that with grunt?
Should I use a own grunt file for each project?
greets
Since it's already 3 self contained commands, you can probably get by with just adding a script in the package.json of each project that handles all it's building commands, ie:
{
"name": "project-name",
...
"scripts": {
"build": "npm install && typings install && tsc"
}
}
Which will allow you to just run npm run build to run all 3 commands for any given project.
Then you can just run
(cd /path/to/project1 && npm run build) & (cd /path/to/project2 && npm run build) & (cd /path/to/project3 && npm run build)
Which will build all 3 simultaneously.
Note: I'm assuming npm will handle multiple processes, but you may have to run sequentially
It is possible to use grunt to run whatever shell commands such as using grunt-shell; however for me personally, it doesn't make sense to have a build process in one project that will cause another project to build.

Run npm scripts using local deps

Currently I run npm scripts using local deps this way:
package.json:
"scripts": {
"test": "node ./node_modules/karma/bin/karma start",
"node-test": "node ./node_modules/jasmine/bin/jasmine",
"build": "node ./node_modules/gulp/bin/gulp build"
},
I don't want to use global deps, since I can forgot to add deps to the package.json. This way when a local dep is missing, then I got an error message and I don't have problems because some deps are not installed globally, e.g. karma plugins.
Is there a better (shorter) way to define npm scripts using the local libs? Is this travis compatible?
edit:
If it wasn't obvious I have the same libs installed globally, but I want to use the local installs by these projects. That means when I start karma with karma start then the globally installed version will start the karma server, which means that if I don't have all of the karma plugins globally installed, then I got error.
Another problem that I have windows, so the solutions described here: How to use package installed locally in node_modules? do not work. Windows does not recognize the #!/bin/sh and the #!/usr/bin/env node head sections and there is no sh command as far as I can tell. At least not in webstorm terminal. Git bash has the sh command, but I want to run these npm scripts from webstorm terminal.
One possible solution could be to fix somehow webstorm so it could use sh from terminal. After that I could use $(npm bin) I assume. But that's just a guess. I am not sure whether this can be done.
npm automatically puts prepends the path ./node_modules/.bin to your PATH env before it executes commands run by using npm run (including the two "magic" shortcuts npm start and npm test)
npm scripts docs
You can just set this up with:
"scripts": {
"test": "karma start",
"node-test": "jasmine",
"build": "gulp build"
}
Assuming that you have karma, jasmine and gulp-cli listed in either your devDependencies or dependencies (so that they're install when doing npm install)
And yes, it is travis-compatible. Here is an example of a package that is tested on travis using tap which is installed locally as a module:
https://github.com/scriptoLLC/couchdown/

Resources