3

I have a NPM package with a small user base, yesterday I created a new version and wanted to release it. I thought that I might as well make use of the new GitHub Packages and so I setup everything as GitHub suggested and released!

Now the problem is that I still have the old NPM page running on version 2.0.2 while everyone currently uses this as their dependency while the new GitHub package is on 2.0.4, Is there a way to 'synchronize' these two. Of course the GitHub Packages uses the <USER>/<PACKAGE> labeling while NPM just uses <NAME>.

Is the only thing I can do to publish on GitHub Packages and on NPM and just try to move users away from the NPM page?

Schotsl
  • 187
  • 1
  • 8
  • 29

3 Answers3

3

If your publishing a public package, your better off just publishing it on NPM, as that is what most developers are used to.

I use GitHub Packages at work and the only advantage is that is effective free for hosting internal packages, as we are already paying for GitHub anyway. If it wasn’t for the zero price we wouldn’t be using it.

If you really want to force all your users to migrate to GitHub packages, and have to set up npm to work with it you could mark you old version npm deprecated and use that to point people to the new version.

https://docs.npmjs.com/cli/v6/commands/npm-deprecate

David Bradshaw
  • 11,859
  • 3
  • 41
  • 70
0

Here is another solution, but there is a catch.

Change your registry.npmjs.org package content to

index.js

export * from '@schotsl/my-package';

Now your registry.npmjs.org package is (almost) pointing to your npm.pkg.github.com package.

Only almost because any development directory for a project downstream of registry.npmjs.org/my-package, must configure the scope-to-server mapping for @schotsl/my-package to npm.pkg.github.com in a package manager config file.

In the case of package managers 'npm' and 'yarn' (v1) that can be done in an .npmrc file at the same level as package.json.

The required .npmrc content is

@schotsl:registry=https://npm.pkg.github.com
# Github PAT token, packages:read authorization only ok 
//npm.pkg.github.co/:_authToken="ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

The first line is the scope to server mapping.

The second line is a Github personal authorization token (PAT) with at least package:read permission. It is actually pretty liberal. A PAT with package:read issued from any github account will allow read access to every github accounts packages.

For the 'yarn' v2 package, the .npmrc file does not work, and instead a couple of keys need to be set in .yarnrc.yml.

Unfortunately there is no way to set the scope-to-server mapping and the token inside the registry.npmjs.org/my-package package itself. Putting the .npmrc file in there doesn't work, it is ignored. And that wouldn't be a good solution anyway, because not all package managers read .npmrc files.

That is the 'catch' - using npm.pkg.github.com packages requires package manager specific config settings to be made by every downstream developer.

In addition, what if two different upstream packages have colliding scope names, each mapping to a different server? The current config methodology fails in that case.

Feature Proposal not current behavior

Ideally, there would be a common interface agreed upon by all package managers inside package.json - and the scope-to-server mapping would be defined in the package that directly references the scope. For example, in the package.json of my-package on registry.npmjs.org

{
  dependencies:{
    "@schotsl/my-package":"1.0.0"
  },
  registries:{
    "@schotsl/my-package":"https://npm.pkg.github.com",
  },
  auths:{
    "https://npm.pkg.github.com":"ghp_XXXXXXXXXXXXXXXX",
  },
}

Then downstream users would not need to config for each scope, and predictable (and risky) problems with scope name or package name collisions would not occur.

But that is not the way it is. Therefore Github Packages (npm.pkg.github.com) doesn't really seem to be a feasible way to provide public packages which may become dependencies of other public packages. No problem for private packages though.

Craig Hicks
  • 2,199
  • 20
  • 35
0

Since we’re using a private package (and it's scoped already), we have control over the consumers of our package. These are the steps we took to migrate to Github Packages:

  1. Download from current npm.js NPM_TOKEN=npm_XXXXXXXX npm pack @scope/your-package
  2. Change .npmrc file to contain the GitHub Packages registry: @sccope:registry=https://npm.pkg.github.com //npm.pkg.github.co/:_authToken="${NPM_TOKEN}"
  3. Publish to GitHub Packages: NPM_TOKEN=ghp_XXXXXXX npm publish your-package-m.m.v.tgz --tag latest --access restricted
  4. On consuming project run npm install @scope/your-package:m.m.p to refresh the package-lock.json
  5. Have everyone update their branches and get their Github classic token as NPM_TOKEN environment variable.
  6. npm i should work and pull from Github Packages (make sure everybody have access to Packages not just the repository).

If you need to support all versions you have on npm.js, of course you'll need to download all and publish to Github. I did it with a simple bash loop. Something along (you'll need to manually change the major and minor or nest more loops):

for i in {0..n}; do
  NPM_TOKEN=npm_XXXXX npm pack @scope/your-package@m.m.$i
done

for i in {0..n}; do
  NPM_TOKEN=ghp_XXXXX npm publish @scope/your-package-m.m.$i.tgz --access restricted
done
Moshisho
  • 2,781
  • 1
  • 23
  • 39