How to test an `npm publish` result, without actually publishing to NPM? - node.js

One common problem I have, is that sometimes my .npmignore file is too aggressive, and I ignore files that I actually will to include in the NPM tarball.
My question is - is there a way to test the results of NPM publish, without actually publishing to NPM?
I am thinking something like this. Assuming I have a local NPM package with package name "foo"
set -e;
local proj="bar";
local path_to_foo="."
mkdir -p "$HOME/.local.npm"
npm --tarball -o "$HOME/.local.npm" # made up command, but you get the idea
(
cd "$HOME/.temp_projects"
rm -rf "$proj"
mkdir "$proj"
cd "$proj"
npm init -f
npm install "$path_to_foo"
)
copy_test_stuff -o "$HOME/.temp_projects/bar"
cd "$HOME/.temp_projects/bar"
npm test
I don't think this will work. Because whatever we include in the NPM publish tarball, might not have enough to do the full test. But maybe if we copy all the test files (including fixtures, etc) when we do copy_test_stuff, it might work?

Simply run
npm publish --dry-run
or, with tarball generation in the current directory
npm pack
In npm 6 and up, these will display what files are going to be uploaded.

I'll elaborate my comment I posted earler, (thanks Alexander Mills).
I'm a verdaccio contributor, so, I closely follow whom are implementing and how to verdaccio. I'll describe couples or examples (e2e mostly) that I've found and might be interesting or as a valid answer.
create-react-app
By far, the most popular integration. Let me give you some context, they are using lerna and have multiple packages that need to test before to publish on main registry aka (npmjs). I'll quote here Dan Abramov explaining their reasons to use a custon registry.
The script is self-explanatory but let me highlight some parts.
+nohup npx verdaccio#2.7.2 &>$tmp_registry_log &
+# Wait for `verdaccio` to boot
+grep -q 'http address' <(tail -f $tmp_registry_log)
+
+# Set registry to local registry
+npm set registry http://localhost:4873
+yarn config set registry http://localhost:4873
+
+# Login so we can publish packages
+npx npm-cli-login#0.0.10 -u user -p password -e user#example.com -r http://localhost:4873 --quotes
# Test local start command
yarn start --smoke-test
+./tasks/release.sh --yes --force-publish=* --skip-git --cd-version=prerelease --exact --npm-tag=latest
As you see, they are running verdaccio and instead a custom config file they have decided to use npm-cli-login and then they run the tests against verdaccio. When all is ready, they publish on verdaccio. As last step, later in the same file, they fetch packages with their own app.
pnpm
They have created a project called pnpm-registry-mock which is an abstraction that allows them to run verdaccio before running the tests.
"pretest:e2e": "rimraf ../.tmp/ && rimraf node_modules/.bin/pnpm && pnpm-registry-mock prepare",
"test:e2e": "preview --skip-prepublishOnly && npm-run-all -p -r pnpm-registry-mock test:tap",
"test": "npm run lint && npm run tsc && npm run test:e2e",
Basically, using npm scripts they prepare verdaccio and run the test as last step. I cannot go too much into details, since I've only saw it shallowly. But I know what it does.
Mozilla Neutrino
This is work in progress, but, it's also interesting to mention here.
+if [ "$PROJECT" == "all" ]; then
+ yarn link:all;
+ yarn validate:eslintrc;
+ yarn lint;
+ yarn build;
+ yarn test;
+else
+ yarn verdaccio --config verdaccio.yml & sleep 10;
+ yarn config set registry "http://localhost:4873";
+ npm config set registry "http://localhost:4873";
+ .scripts/npm-adduser.js;
+ yarn lerna publish \
+ --force-publish=* \
+ --skip-git \
+ --skip-npm \
+ --registry http://localhost:4873/ \
+ --yes \
+ --repo-version $(node_modules/.bin/semver -i patch $(npm view neutrino version));
+ yarn lerna exec npm publish --registry http://localhost:4873/;
+ PROJECT="$PROJECT" TEST_RUNNER="$TEST_RUNNER" LINTER="$LINTER" yarn test:create-project;
+fi
Again, the same approach, project is being built and then verdaccio is being executed and they publish all packages.
Babel.js
I know Babel.js has been experimenting with a smoke-testing for Babel 6 and have plans to integrate a registry with Babel 7. I quote Henry Zhu early this year talking about babel-smoke-tests in the same thread of create-react-app.
The experiment is called babel-smoke-tests and babel-smoke-tests/scripts/test.sh is the key file for you.
Here I see the same pattern than other projects. They are launching verdaccio and then they do their stuff.
START=$(cd scripts; pwd)/section-start.sh
END=$(cd scripts; pwd)/section-end.sh
$START 'Setting up local npm registry' setup.npm.registry
node_modules/.bin/verdaccio -l localhost:4873 -c verdaccio.yml &
export NPM_CONFIG_REGISTRY=http://localhost:4873/
NPM_LOGIN=$(pwd)/scripts/npm-login.sh
$NPM_LOGIN
$END 'Done setting up local npm registry' setup.npm.registry
scripts/bootstrap.sh
export THEM=$(cd them; pwd)
if [[ $SPECIFIC_TEST ]]; then
scripts/tests/$SPECIFIC_TEST.sh
else
scripts/tests/jquery.sh
scripts/tests/react.sh
fi
Wrap up
First of all, I hope my small research give you new ideas how to address your issue. I think npm pack solve some issues, but mocking a registry using verdaccio which is quite light and straightforward to use might be a real option for you. Some big projects are being (or getting started) using it and they follow more or less the same approach. So, Why don't try? :)
https://www.verdaccio.org/

I had the exact same problem, so I created a package called package-preview. What package-preview does is:
packs your package (it is what npm does before publish)
installs your package in a temp location
links the package to your project's node_modules
This allows you to basically require the package as a dependency in your tests. So in tests of "awesome-pkg", intead of require('../lib') you write require('awesome-pkg')
I use this package in all the pnpm repos for several months and it works really well. I also posted an article about this package that explains all the different errors that it can catch: Never ever forget to install a dependency

Referring to npm docs:
[--dry-run] As of npm#6, does everything publish would do except
actually publishing to the registry. Reports the details of what would
have been published.
Similar to --dry-run see npm pack, which figures out the files to be included and packs them into a tarball to be uploaded to the registry.
https://docs.npmjs.com/cli/v6/commands/npm-publish#description

I see too many complicated answers, but according to documentation, you just need to install your local package globally (because it will be installed on different directory)
Go to your module root directory and do
npm install . -g

Related

thrift npm instalation fails

I am trying to install the NPM package thirft in my angular project. I added to mi package.json:
"#types/thrift": "^0.10.9",
"thrift": "^0.13.0",
"node-int64": "^0.4.0",
Then I run npm Install All seems to go smooth.
As stated in the npm package webpage I have to grunt the package to finish its instalaltion.
Following the steps I got to the package and execute:
npm install
npx grunt
And then I get this error
Running "shell:ThriftGen" (shell) task
>> /bin/sh: 1: ../../compiler/cpp/thrift: not found
Warning: Done, with errors: command "mkdir -p test/gen-js && ../../compiler/cpp/thrift -gen js --out test/gen-js ../../test/ThriftTest.thrift && ../../compiler/cpp/thrift -gen js --out test/gen-js ../../test/JsDeepConstructorTest.thrift && mkdir -p test/gen-js-jquery && ../../compiler/cpp/thrift -gen js:jquery --out test/gen-js-jquery ../../test/ThriftTest.thrift && mkdir -p test/gen-nodejs && ../../compiler/cpp/thrift -gen js:node --out test/gen-nodejs ../../test/ThriftTest.thrift && mkdir -p test/gen-js-es6 && ../../compiler/cpp/thrift -gen js:es6 --out test/gen-js-es6 ../../test/ThriftTest.thrift && mkdir -p test/gen-nodejs-es6 && ../../compiler/cpp/thrift -gen js:node,es6 --out ./test/gen-nodejs-es6 ../../test/ThriftTest.thrift" (target "ThriftGen") exited with code 127. Use --force to continue.
Aborted due to warnings.
It fell that using force will not correct the underlying problem but ignore it and end in a erroneous installation.
Edit from Feb. 23, 2021:
Since a few days, Apache thrift 0.14.0 has been released. This should solve the aforementioned issues. Please give it a try and open a new question if you experience any problems. See https://www.npmjs.com/package/thrift
Original Answer:
As of now (thrift 0.13.0) there are multiple issues with the Node.js package. The issues are documented here:
https://issues.apache.org/jira/browse/THRIFT-5170
https://issues.apache.org/jira/browse/THRIFT-5029
https://issues.apache.org/jira/browse/THRIFT-5039
All of these issues have been fixed in upstream master branch at https://github.com/apache/thrift. But the fixes have not been released to npm yet.
If you urgently need a working thrift, I recommend building it yourself from the sources. This will require a bit of fiddling, but its not impossible. Generally for this kind of request its best if you ask at the users mailing list at https://thrift.apache.org/mailing. But I'll try to outline the relevant steps here.
You will need to create a local Node.js package that you can use in place of the usual npm install command. See the Node.js package documentation for more details. This Node.js package does not include the thrift compiler, so it is not sufficient to generate new Thrift bindings from an IDL file. If you need the compiler too, it may be easiest to install it from binary distributors (like your Linux distribution, if you have that). Apache Thrift itself does not provide ready-made binaries.
Here are the required steps to generate the Node.js bundle:
Clone the Thrift master branch from https://github.com/apache/thrift
Open a terminal and go to the root folder of the checkout
Call npm install to install build dependencies
Package a local Node.js bundle of Thrift with npm pack
This will (as of now) create a local bundle thrift-0.14.0.tgz with the latest Node.js sources for Thrift.
Copy this to your Angular project, then install it using npm --save "file:thrift-0.14.0.tar.gz"

Running multiple nodeJS Applications

Is it possible to run for example 3 or more nodeJS Apps with a command via a shell script?
The idea is i have a shell script and navigate into app directories and type the npm command.
npm package concurrently is not an option.
#!/bin/sh
cd ./firstApp && npm start ...
cd ./seconndApp && npm run dev ...
cd ./thirdApp && npm run dev ...
I would also have suggested concurrently, you didn't give a reason for not using that.
Another possible solution might be Lerna
https://github.com/lerna/lerna
Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.
Lerna can also reduce the time and space requirements for numerous copies of packages in development and build environments - normally a downside of dividing a project into many separate NPM packages.
One of things lerna can do is run all packages at the same time. Read the doco and decide if it fits your use case.

Google App Engine Standard Node JS how to run build script?

Does GAE standard for Node support a way to have build scripts? I tried using postinstall within package.json but that did not work.
My codebase has subdirectories with package.json within the subdirectories. In my root package.json there is
scripts: {
postinstall: cd vendor && npm install
....
}
However I'm not seeing any vendor packages installed so I'm inclined to believe the postinstall does not get triggered on GAE Node standard.
Is there any way for me to install subdirectory dependencies without having to copy and paste all my vendor/package.json dependencies to the root?
Note: I've also tried putting an "install" within the package.json scripts but that didn't seem to get triggered either.
In GAE standard, installation of dependencies are automatically managed. You should add them in your package.json.
As Google documentation mentioned :
When you deploy your app, the Node.js runtime automatically installs all dependencies declared in your package.json file using the npm install command.
{
"dependencies": {
"lodash": "^4.0.1"
}
}
Installation will be done during app deployment via :
gcloud app deploy
To add a build step, run the following:
gcloud beta app gen-config --custom
This will generate the default dockerfile and config that is run. In your .dockerfile, add your build step:
RUN npm run build --unsafe-perm || \
((if [ -f npm-debug.log ]; then \
cat npm-debug.log; \
fi) && false)
"prestart": "if [ ! -d build ]; then npm run build; fi",
" -d build" here is the build process generated folder, replace it to whatever you actually use.
Not sure if this will work for your case, but seems like GAE standard has added the ability to run a custom build step.
However it does state:
After executing your custom build step, App Engine removes and regenerates the node_modules folder by only installing the production dependencies declared in the dependencies field of your package.json file.
Maybe since the node_modules are in your vendor/ directory, GAE may not detect and remove them, thus accomplishing your goal. This is a pre-install step, unlike postinstall specified in your script. Not sure if it matters.

CircleCI not caching my globally installed node module?

I am trying to cache a command line tool needed for my build process. The tool is made out of NodeJS. The build succeeds, but I need it to run faster.
The relevant parts of my circle.yml look like this :
dependencies:
post:
- npm -g list
- if [ $(npm -g list | grep -c starrynight) -lt 1 ]; then npm install -g starrynight; else echo "StarryNight seems to be cached"; fi
test:
override:
- npm -g list
- starrynight run-tests --framework nightwatch
The second npm -g list shows starrynight available for use, but the first one shows that it is not being cached.
echo $(npm prefix -g)
. . . gets me . . .
/home/ubuntu/nvm/v0.10.33
. . . so I am assuming CircleCI doesn't cache anything installed globally into nvm.
Nothing I have tried gets me my message, "StarryNight seems to be cached".
How can I cache starrynight?
Ok, I figured this out. Thanks to Hirokuni Kim of CircleCI for pointing me in the right direction.
The relevant bits of the new circle.yml looks like this :
machine:
node:
version: 0.10.33
dependencies:
cache_directories:
- ~/nvm/v0.10.33/lib/node_modules/starrynight
- ~/nvm/v0.10.33/bin/starrynight
pre:
- if [ ! -e ~/nvm/v0.10.33/bin/starrynight ]; then npm install -g starrynight; else echo "Starrynight seems to be cached"; fi;
Hirokuni suggested caching ~/nvm but cache retrieval took as long as the build, since it restores every available version of nodejs.
I had tried previously to cache just ~/nvm/v0.10.33/lib/node_modules/starrynight on its own, without realizing that the sister 'directory' bin/starrynight is actually an essential symlink to the entry point of the module.
My working assumption is that NodeJS modules run from the command line through a series of symbolic references, probably as follows. . .
npm install -g starrynight creates two new artifacts:
an environment alias for npm named starrynight
a symlink in the ${prefix}/bin directory, which points to the entry point file, starrynight.js specified with the bin key in package.json.
When the user types starrynight as a CLI command the shell interprets it as an alias for npm and executes it. npm examines $0, gets starrynight, and starts up nodejs with the symlink ${prefix}/bin/starrynight as the module to execute. That symlink refers to ~/nvm/v0.10.33/lib/node_modules/starrynight where the real action takes place.
In short, it is necessary to cache both ${prefix}/lib/node_modules/xxx and ${prefix}/bin/xxx
The path in the accepted answer doesn't seem to work anymore. I've checked on the build instance that now global npm packages are in
/opt/circleci/nodejs/<version>
so I've added to the circle.yml the following:
- "/opt/circleci/nodejs/v4.3.2/lib/node_modules"
- "/opt/circleci/nodejs/v4.3.2/bin"

Run npm install --production on OpenShift

When I push my code to OpenShift, it looks like it's installing my devDependencies which takes forever. I would really love to set it up so it will only install the dependencies (by running with the --production flag). Is there any way to do this?
You can tell npm to install using the --production flag by setting the NPM_CONFIG_PRODUCTION environment variable to "true".
Here is an example that should work for existing applications:
rhc env set NPM_CONFIG_PRODUCTION="true"
Or, you can set this variable as a part of your initial app-create step:
rhc app create myapplication nodejs-0.10 NPM_CONFIG_PRODUCTION="true"
Found a way to specify it in source instead of during app creation.
The benefit (for me) over an env var is that it applies to all ways to launch the app, including a "Launch on OpenShift" button.
Create an .openshift/action_hooks/pre_build file:
#!/bin/bash
# This makes npm not install devDependencies.
echo 'Enabling npm production'
echo 'production = true' >> $OPENSHIFT_REPO_DIR/.npmrc
That's it! I've tested and it does affect npm for this build, and the .npmrc disappears if you remove this hook in the future.
(Obviously I could also achieve this by simply adding an .npmrc to my repo, but do not want to affect people checking out the source and running npm install, only how it works on OpenShift.)
It looks like the only solution is to update the cartridge itself. The npm install command is located in the cartridge's bin/control folder. Meanwhile, it's been fixed in the originating github repo at wshearn/openshift-origin-cartridge-nodejs so you can just install from github rather than using the Quickstart.
Create a .npmrc file where the node_modules folder is located.
Open it with your text-editor and add this to it:
production = true
P.S. no semicolons or any other characters
This will ensure that devDependencies are not installed on the OPENSHIFT server

Resources