Skip to content

karmaniverous/npm-package-template-ts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

179 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TypeScript NPM Package Template

👇 Some of these badges only activate when you publish your package!

npm version Node Current docs changelog license

Writing great TypeScript is only half the battle! You also need to instrument it, format it, lint it, test it, bundle it, document it, and publish it!

Getting all of these pieces to work gracefully together is not trivial.

This template puts those pieces together in a way that just WORKS, right out of the box, so you can focus on your code. It includes fully-configured support for:

Code authoring with TypeScript.
Inline documentation with TSDoc.
CLI generation with Commander.
Code formatting with Prettier.
Linting with ESLint.
Unit testing with Vitest.
Package pruning with Knip.
Bundling with Rollup (pure ESM).
Publishing with ReleaseIt.
Git hooks with Lefthook.
API documentation generated by TypeDoc.
✅ Recommended extensions & settings wherever appropriate.

Getting Started

Create a new repo using this template! When you clone it locally, be sure to run:

npm i                 # install dependencies
npx lefthook install  # install Git hooks

Also, type @recommended into the VSCode Extensions sidebar and install the recommended extensions!

Change all repository & personal references in package.json & typedoc.json to reflect your own info.

Before your first commit, be sure to reset your project's version number (e.g. to 0.0.0) in package.json.

To streamline the release process from your desktop, set up a GitHub Personal Access Token and follow the instructions in .env.local.template.

Code Authoring

You want to write straight TS code without having to jump through weird hoops like adding a .js extension to your TS imports. (Click here to dive into that hole. 🙄)

Long story short: you can. Just write your code in the src directory and import it as you would any other module. The bundling process will take care of the rest.

Inline Documentation

This template uses TSDoc for inline documentation. TSDoc is similar to JSDoc, but is way less verbose as it can take advantage of TypeScript's type system. It also has better support for documenting generics and other TypeScript-specific features.

TSdoc comments are automatically included in your bundled code, so you can use them to document your code for IntelliSense in JavaScript as well as TypeScript.

The template also includes linting support for your TSDoc comments to keep you out of trouble. Just run npm run lint to check your comments along with the rest of your code, and be sure to check out the great TSDoc documentation for more details!

Also note that this template generates API Documentation with TypeDoc. The TypeDoc spec includes a few tags that TSDoc doesn't support. tsdoc.json specifies these extra tags and ensures you can use them in your code without generating ESLint warnings!

CLI Generation

This template uses Commander to generate a CLI for your package.

Given that your underlying library is solid, wrapping it into a CLI is fairly straightforward. Just follow these steps:

  1. All of your CLI-specific code should live in the src/cli directory, but can import code from across your package as required. Each subdirectory here is the root of a CLI command. You can have as many as you want, but this template includes a single example called mycli.

  2. The index.ts file in each named CLI subdirectory will be picked up by the bundler and compiled into a CLI command. So src/cli/mycli/index.ts will be compiled into dist/cli/mycli/index.js.

  3. The bin field in package.json must specifically reference each of these compiled CLI commands. On installation, you can then execute your CLI command like this:

> npx mycli      # if installed locally

> mycli          # if installed globally

# this is what you get...

Usage: mycli [options] [command]

My CLI tool

Options:
  -h, --help      display help for command

Commands:
  foo [options]   Foos your bar.
  help [command]  display help for command

Providing a detailed tutorial on Commander is really out of scope for this README, but this repo demonstrates a simple example with a single subcommand abstracted into a separate dependency.

You can build on this example to create a MUCH more complex CLI! See the Commander documentation for more details.

If your project requires an extensive, config-driven CLI, you might want to use my get-dotenv-child template instead!

Formatting

Code formatting is provided by Prettier.

Just run npm run lint to lint & format your code, or npm run lint:fix to resolve any issues automatically if possible.

The Prettier extension is included in the template's VSCode workspace recommendations, and the template contains related workspace settings, so be sure to install recommended extensions when prompted!

Linting

Linting services are provided by ESLint.

Just run npm run lint to lint your code, or npm run lint:fix to resolve any issues automatically if possible. These commands also run Prettier to identify & fix formatting issues.

The ESLint extension is included in the template's VSCode workspace recommendations, and the template contains related workspace settings, so be sure to install recommended extensions when prompted!

Unit Testing

Unit test support is provided by Vitest.

Any file containing .test. in its name (e.g. foo.test.ts) will be treated as a test file and executed by Vitest. See vitest.config.ts for configuration details.

Just run npm run test to execute your tests.

Test coverage reporting is provided by Vitest and runs every time you execute your tests. If you execute your tests from the command line, you will see a coverage report at the bottom of the run. You can also see a prettier version of this report by opening coverage/lcov-report/index.html in your browser.

The Vitest extension is a great way to execute & debug your Vitest tests! It's included in the template's VSCode workspace recommendations, and the template contains related workspace settings, so be sure to install recommended extensions when prompted!

Package Pruning

Knip is a great command-line tool that finds unused files, dependencies and exports in your TypeScript project. Less code and dependencies lead to improved performance, less maintenance and easier refactorings!

This template integrates Knip into your build process so you can prune your package at every release. Edit the config file to add any new cutouts, and run npm run knip to prune your package on demand!

Bundling

This template uses Rollup to bundle your code into pure ESM output. See the References section for more detailed notes. It creates:

  • ESM library output, for import into TS/JS code.
  • Type definition files to support TypeScript imports and power IntelliSense in JavaScript.
  • CLI commands for execution from your command line. See the CLI Generation section for details. Don't forget to update the bin field in package.json!

Type declarations are properly bundled and should be available no matter how your package is imported.

Just run npm run build to bundle your code, and the output will be in the dist directory.

See rollup.config.ts for details.

Incremental Build Warning

Incremental builds are turned on in this template. This will save you some build time, but @rollup/plugin-typescript will emit the following warning at build time:

(!) [plugin typescript] @rollup/plugin-typescript: outputToFilesystem option is defaulting to true.

This is a known issue and should have no negative effect on your build. If you can figure out how to suppress this warning, please submit a PR!

External Dependencies

rollup.config.ts is configured to treat all non-dev and peer dependencies listed in package.json as external dependencies. This means these dependencies will not be bundled into your package, but should be installed as a matter of course when you run npm install.

It is possible for external dependencies to creep into your build. For example, let's say you have a dev dependency that you referenced in runtime code, but is actually included as a runtime dependency by some other package. In this case the dependency would not be listed as an external dependency by rollup.config.ts, which could shift your distribution file locations and break your package.

To prevent this, simply list the dependency as a regular dependency in your package.json file... which is exactly where it belongs anyway!

Publishing

This template uses ReleaseIt to create a release on GitHub and publish your package to NPM.

Just run npm run release and the following will happen:

  • ESLint will lint your code.
  • Vitest will execute your tests and assess code coverage. Open coverage/lcov-report/index.html to see the results.
  • Rollup will bundle your code.
  • TypeDoc will generate & commit your API documentation.
  • ReleaseIt will create a release on GitHub and publish your package to NPM.

To preserve Git Flow integrity, npm run release will only run on the main branch. It is often useful, though, to create a pre-release version from a feature branch. To do this, run npm run release:pre on any branch.

See the release-it section in package.json for details.

Validating Your Package

Use this awesome utility to validate that the types in your package are actually accessible in key target development environments.

Git Hooks

This template assumes you will be using something like Git Flow with a strong Git branch naming convention.

The template uses Lefthook to perform two services:

  • It will prevent you from committing to a branch with an invalid name. See the branch-naming-policy script for details.

  • If your branch name begins with a standard-format issue number (e.g. GH-1) it will prefix your commit message with the issue number. This is a great way to keep your commits organized and linked to the issues they address! See the add-issue script for details.

To activate this functionality, be sure to run npx lefthook install after cloning the repository & installing dependencies!

API Documentation

If you've been careful to document your code according to TSDoc conventions, then when you run npm run docs, TypeDoc will generate API documentation, wrap it up with your README file, and publish it in browsable form.

The docs are deployed automatically to GitHub Pages via the included docs workflow on every push to main.

You can alter the outcome by editing typedoc.json. See the TypeDoc options documentation for more info.

For example, see https://docs.karmanivero.us/npm-package-template-ts.

Note that this README file contains a link in the header to this documentation site that does NOT appear in the copy of the README on the documentation site's home page.

This is accomplished with the typedoc-plugin-replace-text TypeDoc plugin. It's already installed & configured in this template, and using it is really simple. Just enclose any Markdown you'd like to exclude from the documentation site in a pair of special Markdown comment tags like this:

<!-- TYPEDOC_EXCLUDE -->

> [API Documentation](https://karmaniverous.github.io/npm-package-template-ts)!

<!-- /TYPEDOC_EXCLUDE -->

Anything between these tags (as well as the tags themselves) will be excluded from the documentation site. Note that you can also use these tags to exclude content from your inline Typescript documentation!

Some tips:

  • When TypeDoc finds a relative link in your README to an asset in your repo, it will copy that asset to the media directory of the documentation site. This is fine for images, but you probably want source code links to continue to point to the source code file in its original location. To accomplish this, just use the full URL to the file instead of a relative link.

  • The organization of your documentation site mostly reflects the organization of your code. So make full use of the tags supported by TypeDoc!

  • I added convenient links in typedoc.json to the project GitHub repository and my GitHub profile. You'll want to change these to reflect your own info.

References


Built for you with ❤️ on Bali! Find more great tools & templates on my GitHub Profile.

About

A feature-rich NPM package template for TypeScript projects.

Topics

Resources

License

Stars

Watchers

Forks

Contributors