Create your own NPM package using TypeScript, Prettier, Eslint and Jest
Tags: npm, typescript, jest, tutorial
Published: 2023-09-03 13:51:24


In this article, we're diving deep into the world of creating your own NPM packages using a potent combination of TypeScript, Prettier, ESLint, and Jest. By the end, you'll not only have a clear understanding of how to set up your development environment but also the knowledge to package your code for easy sharing with the developer community. 

Before you begin, ensure that you have Node.js and NPM (Node Package Manager) installed on your machine by running this in your terminal: 

```bash
node -v
npm -v
```

#### Step 1: Decide on a package name and check its availability. 

Taking into consideration [official package name guideline](https://docs.npmjs.com/package-name-guidelines) pick the right name for your package and check if it is available [here](https://www.npmjs.com/). 

#### Step 2: Create a new directory for your project

```bash
mkdir <project-name>
cd <project-name>
```

Create the `src` directory, this will be the main directory for all our TypeScript source files. Inside the `src` directory, create a file named `index.ts`.

```bash
mkdir src && touch src/index.ts
```

#### Step 3: Init the package

Run the following command for package initialization, answer all the questions in the command line questionnaire and press enter.

```bash
npm init
```

You can skip all of them (you can easily update it later) or simply run `npm init --yes` to receive a list of default values. Open the folder using your IDE. 

#### Step 4: Install all the necessary dependencies - create configuration and ignore files

###### Typescript

In your project directory, install TypeScript as a development dependency:

```bash
npm install --save-dev typescript
```

Then run: 

```bash
tsc --init
```

This command will generate a *tsconfig.json* file in your project directory that contains default compiler options for your TypeScript project.

Replace the default config for these settings below, feel free to add anything you want.

```json
{
  "compilerOptions": {
	"target": "es6",
	"module": "commonjs",
	"declaration": true,
	"outDir": "./dist",
	"strict": true
},

  "include": ["src"],
  "exclude": ["node_modules", "src/**.test.ts"]
}
```

Let's break down what each part of this configuration does:

1. `"compilerOptions"`: This section defines the compiler options for TypeScript.
2. `"include"`: This array specifies which files and directories TypeScript should include in the compilation process. In this configuration, it's set to include the "src" directory, which contains your TypeScript source code.
3. `"exclude"`: This array specifies which files and directories TypeScript should exclude from the compilation process. Here, it's excluding two things: `"node_modules"` - you don't need to compile these since they are already in JavaScript and `"src/**.test.ts"` - this is a common convention for test files, ensuring that they are not compiled as part of your regular code.

###### Eslint

Install ESLint core library along with TypeScript support - parser that allows ESLint to understand TypeScript code and plugin with a set of recommended TypeScript rules as a development dependency:

```bash
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
```

Create `.eslintrc.json` with a set of rules for eslint. 

```bash
touch .eslintrc.json
```

You can add [more rules](https://eslint.org/docs/latest/rules/) to make code more consistent and avoid bugs. 

```json
{
    "root": true,
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": { "project": ["./tsconfig.json"] },
    "plugins": [
        "@typescript-eslint"
    ],
    "rules": {},
    "ignorePatterns": ["src/**/*.test.ts"]
}
```

###### Prettier

Install Prettier as a development dependency:

```bash
npm install --save-dev prettier
```

Create a configuration file in the project root for Prettier configuration. These settings define how your code should be formatted when using the tool.

```bash
touch .prettierrc
```

For example:

```json
{
  "trailingComma": "all",
  "tabWidth": 2,
  "singleQuote": false,
  "printWidth": 120
}
```

This is the most basic config adding trailing commas wherever possible, specifying the number of spaces to be used for each level of indentation, sticking to double quotes for string literals, and defying the maximum line width before code lines are automatically wrapped or formatted

Prettier and ESLint may generate issues when common rules overlap. The best solution here is to use eslint-config-prettier to disable all ESLint rules that are irrelevant to code formatting, as Prettier is already good at it.

```bash
npm install --save-dev eslint-config-prettier
```

To make it work you need to go to the .eslintrc file and add it to Prettier at the end of your extends list to disable any other previous rules from other plugins.

```json
{
    "root": true,
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "prettier"
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": { "project": ["./tsconfig.json"] },
    "plugins": [
        "@typescript-eslint"
    ],
    "rules": {},
    "ignorePatterns": ["src/**/*.test.ts"]
}
```

###### Jest

Finally, install Jest for unit tests and ts-jest preset (a Jest transformer with source map support that lets you use Jest to test projects written in TypeScript).

```bash
npm install --save-dev jest ts-jest @types/jest
```

You don't need to create a configuration file, the basic configuration can be stored in `package.json`:

```json
  "jest": {
    "verbose": true,
    "preset": "ts-jest"
  }
```

The verbose option instructs Jest to display detailed information during test execution and `"preset"` specifies a configuration preset to use for running Jest tests. In this case, it's set to `"ts-jest"`. The `"ts-jest"` preset is designed for projects that use TypeScript for their source code. It configures Jest to work seamlessly with TypeScript, allowing you to write and run tests for TypeScript code. 

#### Step 5: Update scripts in `package.json`

After installing all the dependencies update your scripts in `package.json`:

```json
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc",
    "lint": "eslint ./src",
    "format": "prettier ./src --write",
    "test": "jest"
  }
```

You can also add [magic scripts](https://docs.npmjs.com/cli/v9/using-npm/scripts) that can automate the whole process!

#### Step 6: Init git repository and add `.gitignore` file

The last configuration thing, I swear 😁

```bash
git init
echo "node_modules" >> .gitignore
echo "# <project-name>" >> README.md
git add . && git commit -m "initial commit"
```

Create a remote repository and add it to the project:

```bash
git remote add origin git@github.com:<gh-account>/<project-name>.git
git branch -M main
git push -u origin main
```

#### Step 7: And finally write the code!

Open the index.ts file and implement your functionality.

#### Step 8: Test it using Jest.

Add some unit tests for your code.

**Remember to update package.json if you didn't answer the questions**.

#### Step 9: Test it locally using npm link.

Once you have your NPM package stored locally on your machine, you can test it before publishing. 

Within the original NPM package directory, execute the `npm link` command in your terminal. This command enables us to mimic the installation of the NPM package without actually publishing it to the NPM registry.

Following that, it's necessary to establish a link to this package from within your test directory. Create any test file and run `npm link <project-name>`. From now on you can use your package to test it.   

#### Step 10: Package publishing

First of all, specify which files you want to publish and add them to `.package.json` file. 

```json
  "files": [
    "dist/**/*"
  ]
```

Only the dist folder will be included in the published package! (README.md and package.json are added by default).

If you already have an account, run `npm login` to log in to your NPM account. In case you don't have any you can run the command: `npm adduser`or sign up [here](https://www.npmjs.com/signup).

Then run: 

```bash
npm publish
```

Now browse your package on npmjs. 

The URL is `https://npmjs.com/package/<project-name>`.

#### Updating your NPM package

After you have made some changes you can easily update your npm package using the following command: 

```bash
npm version patch
```

Find more information about bumping a new package version [here](https://docs.npmjs.com/cli/v9/commands/npm-version).

Then run:

```bash
npm publish
```

#### Best practices

- **Readme:** Create a comprehensive `README.md` file for your package. Explain what the package does, how to install and use it, and provide examples.

- **Documentation:** Consider generating documentation for your package, so it will be easier for users to understand and utilize your package.

- **Versioning:** Follow semantic versioning guidelines to ensure that users can understand the impact of updates before they install them.

- **Continuous Integration:** Set up a CI/CD pipeline that automatically runs tests, linters, and builds before publishing. This ensures that only quality code is released.

- **License:** Choose an appropriate open-source license for your package. Include a `LICENSE` file in your project directory.

#### Conclusion

Publishing an NPM package involves more than just code — it's about sharing your expertise and solutions with the development community. By integrating TypeScript, Prettier, ESLint, and Jest, you've already set a strong foundation for your package's quality. With the steps outlined in this article, you can confidently publish packages and updates to them, knowing that you're providing valuable tools for fellow developers. Happy publishing!

![Done](https://media.giphy.com/media/l0Iyl55kTeh71nTXy/giphy.gif)