DEV Community

Cover image for Publishing private NPM package for free
Rajan Prasad
Rajan Prasad

Posted on

Publishing private NPM package for free

If you're avid JS developer then You must be using npm daily to daily basis. NPM has become a home for millions of packages. In today's article, we're going to publish a private NPM package to GitHub. If we were to publish private package to NPM directly, we'll have to upgrade to one of the Paid Plans of NPM but GitHub allows us to do the same thing for free.

Prerequisite

I assume you have basic working knowledge of Git and NodeJS and a GitHub Account Of course.

Getting Started

We'll start by creating a folder for our package and initializing npm in the directory. To do so:

mkdir gh-package
cd gh-package
npm init -y
touch index.js
Enter fullscreen mode Exit fullscreen mode

You can rename the directory anything you want, in my case it's a github package so i'm naming it gh-package. Now, you should go to package.json file and edit it as follow:

{
  "name": "@userName/gh-package",
  "version": "1.0.0",
  "description": "Package for trying out GITHUB Package Registry",
  "main": "index.js",
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/@userName"
  },
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Enter fullscreen mode Exit fullscreen mode

You can customize it in anyway you like but make sure to replace the userName with your valid github username. If i've my github username dmr i'll edit it as:

...
"name": "@dmr/gh-package"
...
Enter fullscreen mode Exit fullscreen mode

Also, instead of gh-package, it should be same as your package name.

Writing Sample package code

Now, let's write some code. In order to keep things simple, i'm going to write a very simple function which will take a string as parameter and will return Hello *String*

Replace the index.js with the following code:

const sayHello = (name) => {
  console.log('Hello ' + name + '!');
};

module.exports = {
  sayHello,
};
Enter fullscreen mode Exit fullscreen mode

Creating repo & Setting up GitHub Access Token

Now in order to publish our package we'll need a github repo and have to run GitHub Actions. So head to the GitHub and create a repo and name it as the same name you want to name your package. You can make it public however I suggest to make it private. Now once repo is created you should be able to commit the current code and push it to the repo. I'm not going to guide you through that part.

Now as I already mentioned, we need to run github actions and in order to do so, we need to create Access Token. In order to do so, head over to your github page go to Settings -> Developer Settings -> Personal Access Tokens -> Generate new token

You should tick the following permissions:

  • workflow
  • write: packages
  • delete: packages

Once done, it will provide you with a token. You need to keep the token safe as we will need that token in order to install the package as well since it's going to be private package.

Adding Secret to GitHub Repo

Now, the generated token should be considered as critical entity and should be kept safe. Hence we need to create a secret to our repository. Repository Secrets allows us to use variables without exposing it to the code, just like environment variables in Heroku. So head over to the repo created for this project -> Settings -> Secrets -> New repository secret.

You can name the secret anything but make sure to use it the same name as in our workflow. In my case i'll be naming it MY_GITHUB_TOKEN

Creating GH Actions workflow

We're almost done, the last thing we need to do is add github actions workflow to our repo. In order to do so, we need to create a folder called .github in our root folder and inside that another folder called workflows and lastly a file called action.yml

mkdir .github
mkdir .github/workflows
touch .github/workflows/action.yml
Enter fullscreen mode Exit fullscreen mode

Now add the following code to action.yml file

name: Build and Deploy

on:
  push:
    branches:
      - main

jobs:
  publish-gpr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://npm.pkg.github.com/
          scope: '@userName'
      - run: npm install
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.MY_GITHUB_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

Replace the userName in scope with your own github userName and *MY_GITHUB_TOKEN with the secret you named while adding secret to the repo

Pushing and Publising the package

Now the final step is to commit all the changes and push it to the github. Once we do so, you can go to the package repo -> Actions and see the build process kicking off. Once the build is completed you'll be able to see your package by going to your Profile -> Packages.

Testing the published package

Now we need to see our published package in action, i mean that's the whole point of publishing an package. In order to do so, You have to create a folder let's call it package-test and navigate into that folder and init npm. Now we need to create a file called .npmrc and paste the following code:

@YOUR_USERNAME:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=YOUR_TOKEN
Enter fullscreen mode Exit fullscreen mode

Replace the YOUR_USERNAME and YOUR_TOKEN with your github username and the generated token. Now you can install the package by running:

npm i @YOUR_USERNAME/PACKAGENAME
Enter fullscreen mode Exit fullscreen mode

now create a file called index.js and replace it with following code:

let demoPackage = require('@username/gh-package');

demoPackage.sayHello('World');
Enter fullscreen mode Exit fullscreen mode

And run it, and the package will return Hello World
The package code can be found on my Github Repo

Thanks for Reading.

Oldest comments (2)

Collapse
 
ssontakke profile image
Shaunak Sontakke

This method requires you to put your token in code. Which is not a great design. Any alternative ways to do this?

Collapse