NPM equivalent for "npm:#user/package-name" version in package.json? - npm

I saw this in a package.json file:
"react-native-wheel-picker": "npm:#gregfrench/react-native-wheel-picker",
That doesn't match the tarball, http, or git dependency formats documented in the NPM docs. Looks like it's a yarn convention, because running yarn installed that dependency without complaints from the start script (which otherwise would complain warn Package react-native-wheel-picker has been ignored because it contains invalid configuration. Reason: Cannot find module 'react-native-wheel-picker/package.json').
What does that "version" string mean, why not use "#gregfrench/react-native-wheel-picker" directly, and what would be the package.json equivalent that would allow npm to function correctly?

The npm compatible dependency specification would look like following:
"#gregfrench/react-native-wheel-picker": "<version>"
As I see on npmjs.com the latest version for #gregfrench/react-native-wheel-picker is 1.2.3 so if the latest version is needed than following should be in the package.json:
"#gregfrench/react-native-wheel-picker": "1.2.3"
If you don't want to have an exact version there are some possibilities like using ^,~, >=.. characters with the version string. These possibilities are documented here.

Related

Using nvm to switch between npm versions and dealing with init.author.name needs to be init-author-name

I was on npm version 6 and when I moved to npm version 8.19.3, I got the warnings below whenever I issued any command:
npm --version
npm WARN config init.author.name Use `--init-author-name` instead.
npm WARN config init.author.email Use `--init-author-email` instead.
npm WARN config init.author.url Use `--init-author-url` instead.
npm WARN config init.license Use `--init-license` instead.
npm WARN config init.version Use `--init-version` instead.
8.19.3
I searched and found another user asked how to fix this warning, see this question, so I updated my $HOME/.npmrc file to use the new format (see this answer) and it worked.
However, because I use nvm to switch between different versions of npm, I would like to have a solution that works for both the old and new versions of npm.
I tried to include syntax's for both the old and new config names as shown next:
# For npm 8.? and higher
init-author-name=Example name
init-author-email=name#example.com
init-author-url=https://www.example.com
init-license=MIT
init-version=1.0.0
# For npm < 8.?
init.author.name=Example name
init.author.email=name#example.com
init.author.url=https://www.example.com
init.license=MIT
init.version=1.0.0
But the above didn't work. I was forced to delete the older syntax names to get rid of the warning messages.
So my question is:
(Q) Is there a syntax that I can use that works for both the older versions of npm and the newer versions of npm? Basically, I'd like not to have to manually edit my .npmrc file when I switch between older and newer versions when I use commands like:
nvm use 12.13.1
# Now I need the old config names (like init.author.name)
nvm use 8.19.3
# Now I need the new config names (like init-author-name)
As I said, I tried including both the old config names and the new names, but it didn't work. I was forced to remove the old names to get rid of the warnings. IMO, this is a bug.
Is there a solution to this problem?
Searching for a solution
I sited the question that I found on this topic:
https://stackoverflow.com/a/72113809/3281336

How to have `pnpm install` install everything exactly to the specs of the pnpm-lock file?

If you connect a github project to a product like cloudflare pages or Vercel, commits to the remote repo trigger new builds. These builds will run the appropriate install and build commands. I haven't updated a site in months, but major changes have come to dependencies being used and it's causing me so many headaches to try and go through one-by-one and address each and every issue that has surfaced. I'm using pnpm, is there anyway I can have pnpm install look at the existing pnpm-lock.yaml so I can eventually build a project that is entirely the same as a previous build I had 6 months ago? I just want to edit some text on my site and not have to make all these updates. I tried "freezing" the versions of all my dependencies and dev dependencies in package.json by removing instances of ^ to match what I see in my lock file, but that didn't work.
Package Management with PNPM
See also why-does-npm-install-rewrite-package-lock-json
Semver
The semver specification explains how to use semantic versioning though you can probably skip to the npm docs.
As you probably know the numbers are in the form major.minor.patch. If you don't mind which patch release you have as long as it is the specified major and minor version you can use the ~ prefix. Similarly, to allow any minor version use ^.
Walkthrough
Inital Setup
pnpm init
pnpm add express
The package.json will contain (at time of writing):
"express": `"^4.18.2"`
A pnpm-lock.yaml is also created:
specifiers:
express: ^4.18.2
dependencies:
express: 4.18.2
express -> '.pnpm/express#4.18.2/node_modules/express'/
Using pnpm install
Giving it a first run without changing anything produces:
$ pnpm install
Lockfile is up to date, resolution step is skipped
Already up to date
Done in 653ms
Now if I change package.json to be exactly v4.16.0 we shall see an update to pnpm-lock.yaml
specifiers:
express: 4.16.0
dependencies:
express: 4.16.0
Adding the patch wildcard ~4.16.0 and running pnpm install again gives:
specifiers:
express: ~4.16.0
dependencies:
express: 4.16.0
Note that the install version did not change. If I delete the node_modules/ directory and reinstall, still no change.
Ok, now try updating the minor version in package.json to ~4.17.0.
specifiers:
express: ~4.17.0
dependencies:
express: 4.17.3
This time it did update the dependency and installed the latest patch version but did install the exact major and minor version. If you think about what the ~ means then this is expected.
The specifiers section in the lock file is just what we specify as the dependency in the package.json file. The dependencies section in the lock file should reflect the version that is installed, or will be installed.
If I delete the node_modules/ folder and pnpm install again then we still have 4.17.3.
Explanation
What confuses a lot of people about pnpm install/npm install is how the lock-file works with the semver specifier:
The installed version listed as a dependency in the lockfile must be compatible with the version specified in the package file.
If it is compatible, no changes will be made.
If it is incompatible, then the latest compatible version will be installed.
Perhaps because sometimes it seems to install the latest version, and not othertimes, the behaviour is not clear. To state this again, changes will only be made when there is an incompatibility between the packge version and lockfile version. The lockfile dependency never has the ~ or ^ wildcards because only one version is actually installed and that's what the lockfile is supposed to track.
Using --frozen-lockfile in a CI environment
The docs for pnpm install describe how the install will fail if the lockfile is out of sync or needs updating.
Changing the package.json back to ~4.16.0 and then doing the install:
$ pnpm install --frozen-lockfile
Lockfile is up to date, resolution step is skipped
 ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not up to date with package.json
Note that in CI environments this setting is true by default. If you still need to run install in such cases, use "pnpm install --no-frozen-lockfile"
In fact, even if I specify the installed version exactly 4.17.3, because it differs to the specifier ~4.17.0, then it will err. The package.json and pnpm-lock.yaml are out of sync even though the version are compatible.
Finally I will make our package compatible with the latest version that was installed with the first pnpm add express command. To do this I use the minor version wildcard ^4.0.0 and unfreeze the lockfile with pnpm install --no-frozen-lockfile.
specifiers:
express: ^4.0.0
dependencies:
express: 4.17.3
While the specifier is updated to match the package file, the version is not chaged; it is compatible.
Running pnpm install --frozen-lockfile will work again, but not update the installed version.
Conclusion
In a normal environment the lockfile will determine the exact version installed unless it is not compatible with the package file, in which case it will install the lastest version specified by the package file.
In a CI environment the lockfile will not by default be updated and will need to be compatible with the package file for installs to occur.
If you want the latest version specified pnpm update will do the update to the lastest compatible version given in the package file.
Disclaimer
I've tested out everything here but it is complex and I have limited experience using pnpm in a real CI environment.
before deploying your project delete pnpm-lock.yaml

URI of binary packages on npmjs.com?

I need to specify a binary package URI, not a npm cache or something. How to figure out what's actual URI npm uses to download it?
Utilize the npm view command with the following syntax:
npm view <pkg_name> dist.tarball
Note: The <pkg_name> part should be substituted with the actual name of the package that you want to find the tarball's URI for.
For instance, running:
npm view eslint dist.tarball
prints:
https://registry.npmjs.org/eslint/-/eslint-6.7.0.tgz
This shows the URI of the tarball (.tgz) for the latest version of eslint in the NPM Registry.
This is essentially the same URI that npm utilizes via a GET request when you run npm install <package_name>.
Specific package versions:
The syntax for specific versions is:
npm view <pkg_name>#<version> dist.tarball
Note: Same as previously mentioned; the <pkg_name> part should be substituted with the actual name of the package that you want to find. The <version> part that follows the # symbol should be replaced with the specific version.
For instance, running:
npm view eslint#4.19.0 dist.tarball
prints:
https://registry.npmjs.org/eslint/-/eslint-4.19.0.tgz
Also URI could be find in resolved field in package-lock.json.

Tags may not have any characters that encodeURIComponent encodes

I'm migrating from bower to yarn, and in my bower.json file I have this dependency:
Snap.svg": "snap.svg#^0.4.1
When I tried to do the same in the yarn dependencies file, I got this error :
npm ERR! code EINVALIDTAGNAME
npm ERR! Invalid tag name "snap.svg#^0.4.1": Tags may not have any characters that encodeURIComponent encodes.
How can I solve this ?
Two things:
First, the npm package name -- which yarn uses since it uses package.json -- is snapsvg whereas snap.svg (with a dot) is only used for Bower. See the snapsvg npm page. The error you see is in reference to that dot in the package name.
Second, when I test installed it with yarn 1.2.1, I noticed that it complained that 0.4.1 was not available:
Couldn't find any versions for "snapsvg" that matches "^0.4.1"
? Please choose a version of "snapsvg" from this list: (Use arrow keys)
> 0.5.1
0.5.0
0.4.0
0.3.0
0.1.0
The resulting package.json entry should look like:
"dependencies": {
"snapsvg": "^0.4.0"
}
and yarn.lock:
snapsvg#^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/snapsvg/-/snapsvg-0.4.0.tgz#e0767014167825957de7e125c29b0fa89796ea03"
dependencies:
eve "~0.4.2"
Generally, when something weird like this happens, use yarn add with the package name manually and see what it does.
I was able to fix it by simply using below command
npm i --legacy-peer-deps

How Does npm --save Decide Which Version and SemVer Options?

If I type the following into my computer
$ echo '{}' > package.json
$ npm install pug --save
and then look at my package.json, I'll see that npm added a dependency for me.
#File: package.json
{
"dependencies": {
"pug": "^2.0.0-rc.1"
}
}
Sweet! However -- how does npm decide to grab version 2.0.0-rc.1? And how does npm decide to use the ^ SemVer version modifier?
As a user of npm can I configure or tell it to use a different SemVer modifier and/or download a different version? (both a specific version and/or something like "latest stable")
As an npm package maintainer, can I specify that npm's default behavior should be something other than "grab the latest version and slap a ^ on there"?
npm takes the latest tag publicly available and ^ is the default, you can use save-prefix to change it locally.
To a get specific version use #version after package name i.e. npm install pug#0.1.0.
Something like composer's minimum-stability doesn't exist in npm world.
As a maintainer, you can't do anything, except keeping SemVer and writeing good code :)
But at all package.json is just a JSON, you can simply modify them, without using any CLI commands and define whatever you need.