Today we will discuss how I've written a npm package and published it to npmjs.
You can checkout the codebase from here
This is a simple package which just generates random quotes from Phil Dunphy, the lovable and hilarious character from the TV show Modern Family. I have chosen Phil Dunphy as I love Mordern Family and he is one of my favorite caracter from the show.
The target of this package was not to create something unique and useful for everyone (though if you are a fan of Phill Dunphy you may love this idea 😉), but it was to learn how we can use these technologies to build packages in a simple and efficient manner.
Technology Used
- Typescript for writing the business logic and have used tsup for compiling to javascript files.
- ESlint for linting the typescript code
- Also have used Github Actions for linting the code whenever a new pull request is being created.
Setting up local environment for creating packages
For setting up a local environment, we can start like a basic node js project.
mkdir my_project
cd my_prject
npm init
After that we need to add the main entry point of our package as well as a bin file.
{
"name": "phil-s-osophy",
"version": "1.0.1",
"description": "Phil Dunphy's amazing life lessons from Mordern Family.",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
...
"bin": {
"phil-o-osophy": "./dist/index.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/MitraKumar/phil-s-osophy.git"
},
"author": "MitraKumar",
"license": "MIT",
"bugs": {
"url": "https://github.com/MitraKumar/phil-s-osophy/issues"
},
"homepage": "https://github.com/MitraKumar/phil-s-osophy#readme",
...
}
In my scenario since it I am compiling the javascript with tsup I've added the files in here.
And in the typescript file we need to add shebang in front of the file
#! /usr/bin/env node
After updating all this we can simply run npm install -g .
from the project directory to use the package.
Project Setup with Typescript
The main business logic for the package is written in typescript and the logic is very simple, it's just accessing a random element from a list of quotes and printing it out. Again the project was not to create anything unique, it is just fun enough for me to learn these things.
For compiling typescript file I have used tsup as a dev dependency, which is very useful and intuitive for compiling to javascript files. To make this process seamless I've added a npm script to build the project.
For the configuration of tsup we need to create a tsup.config.ts
file.
import { defineConfig } from 'tsup'
export default defineConfig({
target: 'es2020',
format: ['cjs', 'esm'],
splitting: false,
sourcemap: true,
clean: true,
dts: true
})
Then after adding this I added the build command in npm scripts and voila it all worked seamlessly.
{
"name": "phil-s-osophy",
...
"scripts": {
...
"build": "tsup ./src"
},
...
}
This is really helpful as we get the power of types and the seamless process of compiling to javascript files.
Linting with ESLint
Linting is must in a project, this is a small simple enough project but for a live project with many contributors linting is must otherwise without following a proper coding standard it will be difficult over time to maintain a project.
I have used ESlint for checking the linting of the project. Setting up ESLint is simple enough but we have to add few dependencies to help us out here...
in the package.json we need to add few of the dev dependencies such as
{
...
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^6.6.0",
"eslint": "^8.48.0",
...
}
}
We can install this dependencies by running
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
After that we need to add a .eslintrc
file, with some basic rulesets.
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"@typescript-eslint/no-explicit-any": "error",
"indent": ["error", 2],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double"],
"semi": ["error", "always"]
}
}
And all the configurations are done, now we can simply add a npm script eslint ./src --ext .ts
to lint our files.
But this will cause an issue as ESLint will not trigger any typescript error, for that we can simply check it with tsc --noEmit ./src/index.ts
. So for linting we can simply add a script like this tsc --noEmit ./src/index.ts; eslint ./src --ext .ts
to run both of them sequentially.
Also we can add a script to fix the linting errors with ESlint.
{
...
"scripts": {
"lint": "tsc --noEmit ./src/index.ts; eslint ./src --ext .ts",
"fix": "eslint ./src --ext .ts --fix",
...
},
...
}
And voila, linting is also setup in our project.
Setting up Github Actions for checking coding standards
In a real world we probably cannot expect everyone to properly lint code and the Pushing it. So we need to setup a Github Action to generate a check for linting errors if any whenever a PR is being generated.
Setting up such action is pretty easy, we just need create a yml file in the directory .github/workflows
like I've created a file .github/workflows/linter.yml
name: Code Checker
on:
pull_request:
branches:
- main
jobs:
linting:
runs-on: ubuntu-latest
name: Checking coding standards & type checking.
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup node environment
uses: actions/setup-node@v3
with:
node-version: 'latest'
- name: Install dependencies
run: npm clean-install
- name: Run linting & type checking
run: npm run lint
This workflow file is mainly divided into three sections
- name - Name of the workflow
- Event - On which event the workflow will trigger, like in this scenario it will trigger on creating a Pull request against the branch
main
- Jobs - What jobs will run in this workflow.
Jobs also have several aspects to understand, the main thing being steps
Steps basically mentions what the a job will do in a sequential order, like here it is mentioned that the job will first checkout the repo, then setup node environment then install all dependencies and then run our lint script from above.
And that's it, now creating a PR will automatically run this jobs and will show a green check mark ✅
Conclusion
So in conclusion I will say, this was a fun simple enough project which helped me learn a lot of things. And if any of you have any idea of improving the project, even if it's a change in README file, you are more than welcome to submit a Pull Request and I will be happy to merge it.
Top comments (0)