Publishing your first Typescript npm package using Github actions
Tags: typescript, node, github, npm
Published: 2022-04-14 20:06:10

As Javascript/Typescript developer, have you ever dreamed to publish an npm package? If yes, then I'll walk you through the steps I've done to publish my first npm package.

## Things we're going to use/tackle

- Github actions
- Npm

## What you need to know
- Git
- Git tags
- Nodejs
- Typescript
- Github
- Github Secrets

![Getting Started](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4fjt7fzspqh3f2phsubr.png)

## First thing to do
You have to create your github repository.![Create github repo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jkebdhzrnpg6p1lj1805.png) and then clone it and initialize your node application using
```bash
npm init
```
After setting up your project, you have to take a look at these `package.json` properties:

```typescript
{
  "name": "<@org_name>/<pkg_name>", // you can simply just add the package name and omit `"<@org_name>/` if you don't want to publish it into a certain organization
  "version": "1.1.2", // update this if you want to release a new version of you package
  "main": "lib/index.js", // entry point of your package
  "repository": {
    "type": "git",
    "url": "git+https://github.com/<username>/<repo_name>.git"
  },
  "keywords": ["node"],
  "author": "<your_name>",
  "bugs": {
    "url": "https://github.com/<username>/<repo_name>/issues"
  },// add these for devs/collaborators to submit an issue on your repository
  "homepage": "https://github.com/<username>/<repo_name>#readme", // add these to show the homepage of your package
  "typings": "./lib/index.d.ts" // add this to have a typescript badge in your package, this shows that your package has built in types
}
```

## Configure your typescript application
Add the following dev dependencies:
```bash
# using yarn
yarn add -D typescript @types/node nodemon ts-node
```
Then we have to create `tsconfig.json`:
```json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6",
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "outDir": "lib",
    "moduleResolution": "Node",
    "rootDir": "./src",
    "allowSyntheticDefaultImports": true,
    "declaration": true,
    "types": ["node"],
    "esModuleInterop": true
  },
  "compileOnSave": true,
  "exclude": [
    "node_modules/**/*",
    ".webpack/**/*",
    "_warmup/**/*",
    ".github/**/*",
    ".vscode/**/*"
  ],
  "include": ["src/*.ts"],
  "buildOptions": {
    "assumeChangesOnlyAffectDirectDependencies": false
  }
}
```
> This configuration outputs the transpiled code from `src/*` folder to `lib` directory.

## Excluding files from git
We also have to exclude some files/folders in our repository. To exclude them, we have to create `.gitignore`, in my case these are the following files I have to ignore:
```bash
# .gitignore
node_modules # these are the packages installed in our application
lib          # these are the transpiled output files
```

## Create the application
Now, we have to create files inside the `src` directory.

```bash
└── src
    ├── index.ts # entry point of our application
    └── types.ts # optional
```
Inside `src/index.ts`, we can just write anything beyond this point. (We can create a package to check if a number is odd 😏 like this one)
![is-odd](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2w00ttkkg6zfsholqeo.png)
 Well just as an example, we can do it! 💪🏽
```typescript
// src/index.ts
const isOdd = (number: number): boolean => number % 2 !== 0;

export { isOdd };
```

## Create scripts for your package
- You have to run your app locally before publishing it. We can create `dev` script inside the `scripts` property in your `package.json`.
- You should also add a build script so you can transpile your code into javascript.
```typescript
"scripts": {
  "dev": "nodemon --watch \"src/**\" --ext \"ts,json\" --ignore \"src/**/*.spec.ts\" --exec \"ts-node src/index.ts\"", // dev script
  "build": "tsc -p .", // build script
}
```
## Publishing our package
We're now ready publishing our first package but first things first.
- We have to get our npm access token which you can get in your [npm profile](https://www.npmjs.com/settings/<your_username>/tokens)
- You can generate token by selecting either of these scopes:
![npm token scopes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71w0ukuh7nrut1p7yrbe.png)

> Note: You can use automation if you wanted to bypass 2-factor authentication. It is highly recommended to use in your ci/cd

- After getting the access token, you can now put it in Github secrets.

> Tip: You can find it here. `https://github.com/<username>/<repo_name>/settings/secrets/actions`

- Now we can use github actions to publish our npm package. You can use this [yaml](https://raw.githubusercontent.com/nljms/ph-mobile-networks/main/.github/workflows/publish_pkg.yml) file for our publish action.

> Note: In the yml file, we're going to publish a new version once there is a [tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) pushed into our repository

> Additional note: In order to create a tag, you have to commit all the changes first in your repository. Then you have to create a tag using this command:
```bash
git tag -a <version> -m '<message>' # the tag version should match the package version which can be seen on `package.json` 
```

Once everything is settled, you can push the tag using

```bash
git push --tags
```

![yahoo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t5stmr96y6ek07ebzaqe.png)
 
 You just have to wait and check if the ci/cd succeeds.

> Note: If anything breaks in your development, you can reference my project here https://github.com/nljms/ph-mobile-networks

I hope this helps you in your journey building your first npm package! 😄