Publishing private NPM package for free
Tags: npm, node, github
Published: 2020-12-27 05:26:56

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](https://www.npmjs.com/products) 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
```

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"
}
```
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"
...
```
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,
};
```

> 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](https://github.com/)  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
```
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}}
```

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
```
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
```
now create a file called *index.js* and replace it with following code:
```
let demoPackage = require('@username/gh-package');

demoPackage.sayHello('World');
```
And run it, and the package will return *Hello World*
The package code can be found on my  [Github Repo](https://github.com/rajandmr/gh-package) 

> Thanks for Reading.