{"id":20986840,"url":"https://github.com/karmaniverous/npm-package-template-ts","last_synced_at":"2025-06-30T17:36:37.915Z","repository":{"id":232973583,"uuid":"785688143","full_name":"karmaniverous/npm-package-template-ts","owner":"karmaniverous","description":"A feature-rich NPM package template for TypeScript projects.","archived":false,"fork":false,"pushed_at":"2025-03-22T03:09:12.000Z","size":1774,"stargazers_count":13,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-10T17:56:56.385Z","etag":null,"topics":["chai","eslint","lefthook","mocha","npm","nyc","prettier","rollup","template","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karmaniverous.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["karmaniverous"]}},"created_at":"2024-04-12T12:11:47.000Z","updated_at":"2025-03-22T03:09:17.000Z","dependencies_parsed_at":"2025-01-07T13:38:55.335Z","dependency_job_id":"4ac5f51d-59b7-42b4-9e55-d54b0e92f52b","html_url":"https://github.com/karmaniverous/npm-package-template-ts","commit_stats":{"total_commits":134,"total_committers":1,"mean_commits":134.0,"dds":0.0,"last_synced_commit":"533099d0d9862d68c7737375fbf9eb65fb26ebe7"},"previous_names":["karmaniverous/npm-package-template-ts"],"tags_count":37,"template":true,"template_full_name":null,"purl":"pkg:github/karmaniverous/npm-package-template-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karmaniverous%2Fnpm-package-template-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karmaniverous%2Fnpm-package-template-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karmaniverous%2Fnpm-package-template-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karmaniverous%2Fnpm-package-template-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karmaniverous","download_url":"https://codeload.github.com/karmaniverous/npm-package-template-ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karmaniverous%2Fnpm-package-template-ts/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260696537,"owners_count":23048192,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chai","eslint","lefthook","mocha","npm","nyc","prettier","rollup","template","typescript"],"created_at":"2024-11-19T06:15:02.938Z","updated_at":"2025-06-30T17:36:37.888Z","avatar_url":"https://github.com/karmaniverous.png","language":"TypeScript","funding_links":["https://github.com/sponsors/karmaniverous"],"categories":[],"sub_categories":[],"readme":"\u003c!-- TYPEDOC_EXCLUDE --\u003e\n\n\u003e [API Documentation](https://karmaniverous.github.io/npm-package-template-ts) • [CHANGELOG](https://github.com/karmaniverous/npm-package-template-ts/tree/main/CHANGELOG.md)\n\n\u003c!-- /TYPEDOC_EXCLUDE --\u003e\n\n# TypeScript NPM Package Template\n\n**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!\n\nGetting all of these pieces to work gracefully together is not trivial.\n\nThis 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:\n\n✅ [Code authoring](#code-authoring) with [TypeScript](https://www.typescriptlang.org/).\u003cbr\u003e\n✅ [Inline documentation](#inline-documentation) with [TSDoc](https://tsdoc.org/).\u003cbr\u003e\n✅ [CLI generation](#cli-generation) with [Commander](https://www.npmjs.com/package/commander).\u003cbr\u003e\n✅ [Code formatting](#formatting) with [Prettier](https://prettier.io/).\u003cbr\u003e\n✅ [Linting](#linting) with [ESLint](https://eslint.org/).\u003cbr\u003e\n✅ [Unit testing](#unit-testing) with [Mocha](https://mochajs.org/) \u0026 [Chai](https://www.chaijs.com/).\u003cbr\u003e\n✅ [Package pruning](#package-pruning) with [Knip](https://github.com/webpro-nl/knip).\u003cbr\u003e\n✅ [Bundling](#bundling) with [Rollup](https://rollupjs.org/).\u003cbr\u003e\n✅ [Publishing](#publishing) with [ReleaseIt](https://github.com/release-it/release-it).\u003cbr\u003e\n✅ [Git hooks](#git-hooks) with [Lefthook](https://github.com/evilmartians/lefthook).\u003cbr\u003e\n✅ [API documentation](#api-documentation) generated by [TypeDoc].\u003cbr\u003e\n✅ Recommended extensions \u0026 settings wherever appropriate.\u003cbr\u003e\n\n## Getting Started\n\nCreate a new repo using this template! When you clone it locally, be sure to run:\n\n```bash\nnpm i                 # install dependencies\nnpx lefthook install  # install Git hooks\n```\n\nAlso, type `@recommended` into the VSCode Extensions sidebar and install the recommended extensions!\n\nChange all repository \u0026 personal references in [`package.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/package.json) \u0026 [`typedoc.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/typedoc.json) to reflect your own info.\n\nBefore your first commit, be sure to reset your project's version number (e.g. to `0.0.0`) in `package.json`.\n\nTo streamline the release process from your desktop, set up a GitHub [Personal Access Token](https://github.com/settings/tokens) and follow the instructions in [`.env.local.template`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.env.local.template).\n\n## Code Authoring\n\nYou want to write straight TS code without having to jump through weird hoops like adding a `.js` extension to your TS imports. ([Click here](https://stackoverflow.com/questions/75807785/why-do-i-need-to-include-js-extension-in-typescript-import-for-custom-module) to dive into that hole. 🙄)\n\nLong story short: you can. Just write your code in the `src` directory and import it as you would any other module. The [bundling process](#bundling) will take care of the rest.\n\n## Inline Documentation\n\nThis template uses [TSDoc](https://tsdoc.org/) 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.\n\nTSdoc 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.\n\nThe 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](https://tsdoc.org/) for more details!\n\nAlso note that this template generates [API Documentation](#api-documentation) with [TypeDoc](https://typedoc.org/). The TypeDoc spec includes a few tags that TSDoc doesn't support. [`tsdoc.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/tsdoc.json) specifies these extra tags and ensures you can use them in your code without generating ESLint warnings!\n\n## CLI Generation\n\nThis template uses [Commander](https://www.npmjs.com/package/commander) to generate a CLI for your package.\n\nGiven that your underlying library is solid, wrapping it into a CLI is fairly straightforward. Just follow these steps:\n\n1. All of your CLI-specific code should live in the [`src/cli`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/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`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/src/cli/mycli/).\n\n1. The `index.ts` file in each named CLI subdirectory will be picked up by the [bundler](#bundling) and compiled into a CLI command with the same name as the subdirectory. So `src/cli/mycli/index.ts` will be compiled into `dist/mycli.cli.mjs`.\n\n1. The `bin` field in [`package.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/package.json) must specifically reference each of these compiled CLI commands. On installation, you can then execute your CLI command like this:\n\n```bash\n\u003e npx mycli      # if installed localy\n\n\u003e mycli          # if installed globally\n\n# this is what you get...\n\nUsage: mycli [options] [command]\n\nMy CLI tool\n\nOptions:\n  -h, --help      display help for command\n\nCommands:\n  foo [options]   Foos your bar.\n  help [command]  display help for command\n```\n\nProviding 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.\n\nYou can build on this example to create a MUCH more complex CLI! See the [Commander documentation](https://www.npmjs.com/package/commander) for more details.\n\n**If your project requires an extensive, config-driven CLI, you might want to use my [get-dotenv-child](https://github.com/karmaniverous/get-dotenv-child) template instead!**\n\n## Formatting\n\nCode formatting is provided by [Prettier](https://prettier.io).\n\nJust run `npm run lint` to lint \u0026 format your code, or `npm run lint:fix` to resolve any issues automatically if possible.\n\nThe [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) is included in the template's VSCode [workspace recommendations](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.vscode/extensions.json), and the template contains related [workspace settings](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.vscode/settings.json), so be sure to install recommended extensions when prompted!\n\n## Linting\n\nLinting services are provided by [ESLint](https://eslint.org).\n\nJust 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 \u0026 fix formatting issues.\n\nThe [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) is included in the template's VSCode [workspace recommendations](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.vscode/extensions.json), and the template contains related [workspace settings](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.vscode/settings.json), so be sure to install recommended extensions when prompted!\n\n## Unit Testing\n\nUnit test support is provided by [Mocha](https://mochajs.org), using the [Chai](https://www.chaijs.com) assertion library.\n\nAny file containing `.test.` in its name (e.g. [`foo.test.ts`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/src/foo.test.ts)) will be treated as a test file and executed by Mocha. See [`.mocharc.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.mocharc.json) for configuration details.\n\nJust run `npm run test` to execute your tests.\n\nTest coverage reporting is provided by [`nyc`](https://www.npmjs.com/package/nyc) 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/index.html` in your browser.\n\nThe [Mocha Test Explorer Extension](https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-mocha-test-adapter) is a great way to execute \u0026 debug your Mocha tests! It's included in the template's VSCode [workspace recommendations](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.vscode/extensions.json), and the template contains related [workspace settings](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.vscode/settings.json), so be sure to install recommended extensions when prompted!\n\n## Package Pruning\n\n[Knip](https://github.com/webpro-nl/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!\n\nThis template integrates Knip into your build process so you can prune your package at every release. Edit the [config file](https://github.com/karmaniverous/npm-package-template-ts/blob/main/knip.json) to add any new cutouts, and run `npm run knip` to prune your package on demand!\n\n## Bundling\n\nThis template uses [Rollup](https://rollupjs.org) to bundle your code. See the [References](#references) section for more detailed notes. It creates several kinds of outputs:\n\n- ESM, for import into most TS/JS code.\n- IIFE ([Immediately Invoked Function Expression](https://medium.com/@rabailzaheer/iife-explained-immediately-invoked-function-expressions-fccd8f53123d)), for direct browser import.\n- CJS, for lulz.\n- Type definition files to support TypeScript imports and power IntelliSense in Javascript.\n- CLI commands for execution from your command line. See the [CLI Generation](#cli-generation) section for details. Don't forget to update the `bin` field in [`package.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/package.json)!\n\nType declarations are properly bundled and should be available no matter how your package is imported.\n\nJust run `npm run build` to bundle your code, and the output will be in the `dist` directory.\n\nSee [`rollup.config.ts`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/rollup.config.ts) for details. If you don't need all of the output types listed above, it should be fairly straightforward to modify this file to suit your needs.\n\n### Incremental Build Warning\n\nIncremental builds are turned on in this template. This will save you some build time, but [`@rollup/plugin-typescript`](https://www.npmjs.com/package/@rollup/plugin-typescript) will emit the following warning at build time:\n\n```bash\n(!) [plugin typescript] @rollup/plugin-typescript: outputToFilesystem option is defaulting to true.\n```\n\nThis is a [known issue](https://github.com/rollup/plugins/issues/1227) and should have no negative effect on your build. If you can figure out how to suppress this warning, please [submit a PR](https://github.com/karmaniverous/npm-package-template-ts/issues/11)!\n\n### External Dependencies\n\n[`rollup.config.ts`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/rollup.config.ts) is configured to treat all non-dev and peer dependencies listed in `package.json` as external dependencies. This means...\n\n- These dependencies will not be bundled into your package, but should be installed as a matter of course when you run `npm install`.\n\n- Your distribution files will be located in your dist directory as specified in your `package.json` exports field (e.g. `dist/mjs/index.js`).\n\nIt 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...\n\n- the dependency would _not_ be listed as an external dependency by `rollup.config.ts`, and\n\n- your distribution files would shift to `dist/mjs/src/index.js`, breaking your package.\n\nTo prevent this, simply list the dependency as a regular dependency in your `package.json` file... **which is exactly where it belongs anyway!**\n\nThis will restore the structure of your build AND ensure proper tree-shaking of your dependencies.\n\n## Publishing\n\nThis template uses [ReleaseIt](https://github.com/release-it/release-it) to create a release on GitHub and publish your package to NPM.\n\nJust run `npm run release` and the following will happen:\n\n- ESLint will lint your code.\n- Mocha will execute your tests and NYC will assess code coverage. Open `coverage/index.html` to see the results.\n- Rollup will bundle your code.\n- TypeDoc will generate \u0026 commit your API documentation.\n- ReleaseIt will create a release on GitHub and publish your package to NPM.\n\nTo 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.\n\nSee the `release-it` section in [`package.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/package.json) for details.\n\n## Validating Your Package\n\nUse [this awesome utility](https://arethetypeswrong.github.io/) to validate that the types in your package are actually accessible in key target development environments.\n\n## Git Hooks\n\nThis template assumes you will be using something like [Git Flow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) with a [strong Git branch naming convention](https://medium.com/@abhay.pixolo/naming-conventions-for-git-branches-a-cheatsheet-8549feca2534).\n\nThe template uses [Lefthook](https://evilmartians.com/opensource/lefthook) to perform two services:\n\n- It will prevent you from committing to a branch with an invalid name. See the [`branch-naming-policy`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.lefthook/pre-commit/branch-naming-policy) script for details.\n\n- If your branch name begins with a standard-format issue number (e.g. [GH-1](https://github.com/karmaniverous/npm-package-template-ts/issues/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`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/.lefthook/prepare-commit-msg/add-issue) script for details.\n\nTo activate this functionality, be sure to run `npx lefthook install` after cloning the repository \u0026 installing dependencies!\n\n## API Documentation\n\nThis is really slick!\n\nIf you've been careful to document your code according to [TSDoc](https://tsdoc.org/) conventions, then when you run `npm run docs` or `npm run build`, [TypeDoc](https://typedoc.org/) will generate API documentation, wrap it up with your README file, and publish it in browsable form to the `docs` directory of your repo.\n\nYou can alter the outcome by editing [`typedoc.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/typedoc.json). See the [TypeDoc options documentation](https://typedoc.org/options/) for more info.\n\nUpdate your repository's GitHub Pages settings as illustrated below, and this site will be published to `\u003cyour GitHub username\u003e.github.io/\u003cyour repo name\u003e`. You can also assign it a custom domain.\n\n![GitHub Pages Settings](./assets/github-pages-config.png)\n\nIf you already have a custom domain set up for a GitHub Pages site at `\u003cyour GitHub username\u003e.github.io`, this documentation will appear at `\u003cyour custom domain\u003e/\u003cyour repo name\u003e`.\n\nFor example, see https://karmanivero.us/npm-package-template-ts.\n\nFinally, 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.\n\nThis is accomplished with the [`typedoc-plugin-replace-text`](https://www.npmjs.com/package/typedoc-plugin-replace-text) TypeDoc plugin. It's already installed \u0026 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:\n\n```md\n\u003c!-- TYPEDOC_EXCLUDE --\u003e\n\n\u003e [API Documentation](https://karmaniverous.github.io/npm-package-template-ts)!\n\n\u003c!-- /TYPEDOC_EXCLUDE --\u003e\n```\n\nAnything 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 documenation!\n\nSome tips:\n\n- 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.\n\n\u003e Do you know how to restrict this behavior to certain file extensions? [Start a discussion](https://github.com/karmaniverous/npm-package-template-ts/discussions) and let me know!\n\n- The organization of your documentation site mostly reflects the organization of your code. So make full use of the [tags](https://typedoc.org/guides/tags/) supported by TypeDoc!\n\n- I added convenient links in [`typedoc.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/typedoc.json) to the project GitHub repository and my GitHub profile. You'll want to change these to reflect your own info.\n\nAlso note that this template generates [API Documentation](#api-documentation) with [TypeDoc](https://typedoc.org/). The TypeDoc spec includes a few tags that TSDoc doesn't support. [`tsdoc.json`](https://github.com/karmaniverous/npm-package-template-ts/tree/main/tsdoc.json) specifies these extra tags and ensures you can use them in your code without generating ESLint warnings!\n\n## References\n\n- [Building a TypeScript CLI with Node.js and Commander](https://blog.logrocket.com/building-typescript-cli-node-js-commander/)\n\n- [Bundling TypeScript in different formats with rollup.js](https://datomarjanidze.medium.com/bundling-typescript-in-different-formats-with-rollup-js-3397b3a84e4e)\n\n- [Naming conventions for Git Branches — a Cheatsheet](https://medium.com/@abhay.pixolo/naming-conventions-for-git-branches-a-cheatsheet-8549feca2534)\n\n- [TypeScript and NPM package.json exports the 2024 way](https://www.kravchyk.com/typescript-npm-package-json-exports/). Note that [this snippet](https://www.kravchyk.com/typescript-npm-package-json-exports/#:~:text=the%20types%20may%20need%20to%20be%20.d.cjs) is wrong; it should read _the types may need to be `.d.cts`_. That's how this template is implemented. Also note that we're just using a second (and third) `rollup` type declarations target instead of employing [rollup-plugin-copy](https://www.npmjs.com/package/rollup-plugin-copy) as suggested in the article.\n\n---\n\nBuilt for you with ❤️ on Bali! Find more great tools \u0026 templates on [my GitHub Profile](https://github.com/karmaniverous).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarmaniverous%2Fnpm-package-template-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarmaniverous%2Fnpm-package-template-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarmaniverous%2Fnpm-package-template-ts/lists"}