Running Scripts

The primary way you will likely interact with tooling is via package scripts using nr. ts provides a robust set of default package scripts for most common tasks like building, testing, and releasing, and you are able to add your own (or even overwrite the defaults) in your nr.config.ts file.

For a list of all scripts provided by ts, make sure you have created an nr.config.js file in your project root, then run:

npx nr --scripts

This will print a list of all defined scripts and a brief description of what each script does.

If you prefer to run scripts using npm run script-name, you can alias any nr script in package.json thusly:

package.json
{
  "scripts": {
    "script-name": "nr script.name"
  }
}

The npx prefix is not required here because NPM will automatically look for the nr executable in your local node_modules folder.

This rest of this section will go over the most common scripts used to manage a project. It assumes the user has not installed nr globally (not recommended) nor added ./node_modules/.bin to their $PATH, so each example will use the long form notation with npx.

Building

The build script will lint your project using ESLint and compile it using TypeScript to type-check and emit type declaration files. These two processes are run in parallel.

To execute this script, run:

npx nr build

To continuously build and type-check the project in watch mode, run:

npx nr build.watch

Development

In addition to the build.watch script, ts also includes a start script that will run vite build --watch and start nodemon. The entry point that nodemon uses will be the main file declared in package.json.

Example

Given the following package.json, nodemon will run dist/server.js and restart the process whenever files in the dist folder are changed. Meanwhile, Vite will incrementally rebuild the project when source files are changed.

package.json
{
  "main": "dist/server.js"
}

Pre-Build & Post-Build Scripts

If you define prebuild and/or postbuild scripts in nr.config.ts, nr will run them before and after the build script. These scripts are not run with build.watch.

nr.config.ts
import { withDefaultPackageScripts } from '@darkobits/ts';

export default withDefaultPackageScripts(({ script, command }) => {
  script('postbuild', [
    // Example: Runs del .cache --force
    command('del', {
      args: ['.cache', { force: true }]
    })
  ], {
    description: 'Runs after the "build" script.'
  })
});

Testing

To run unit tests for your project with Vitest:

npx nr test

To continuously run tests in watch mode:

npx nr test.watch

To run unit tests and generate a coverage report:

npx nr test.coverage

Linting

Linting is performed automatically as part of the build script, but you can manually lint the project by running:

npx nr lint

To automatically fix any fixable errors in the project:

npx nr lint.fix

Releasing in CI

If you prefer to release your project automatically from a CI environment, ts ships with semantic-release and a configuration preset. To use semantic-release with the provided configuration, simply run one of the release scripts.

To release a new verion from CI:

npx nr release

When using this method, you do not need to create a release.config.js file; semantic-release will be invoked with the configuration preset for you.

If you prefer or need to configure semantic-release manually but would still like to use the configuration preset, you can extend it from your configuration file:

release.config.js
module.exports = {
  extends: '@darkobits/semantic-release-config'
};

When using your own configuration file, invoke semantic-release directly rather than using the release script.

Publishing Releases to GitHub

If you need to publish your project to GitHub, you will need to create a personal access token with the public_repo scope and then configure a GH_TOKEN environment variable in your CI environment with this value. If GH_TOKEN is not present, ts will omit the GitHub plugin from its semantic-release configuration.

Publishing to NPM

If you need to publish your project to NPM, you will need to create an NPM Access Token (the "Automation" token type is recommended) and then configure an NPM_TOKEN environment variable in your CI environment with this value. If NPM_TOKEN is not present, ts will omit the NPM plugin from its semantic-release configuration.

Releasing Locally

If you prefer to manage publishing locally, ts ships with standard-version. To generate (or update) your project's CHANGELOG.md and bump the project's version in package.json:

npx nr bump

To create a beta release:

npx nr bump.beta

For your project's first release, you may not want to bump the version at all, and only generate a change-log and release commit:

npx nr bump.first

Pre-Bump & Post-Bump Scripts

If you define prebump and/or postbump scripts in nr.config.ts, nr will run them before and after any bump* scripts.

nr.config.ts
import { withDefaultPackageScripts } from '@darkobits/ts';

export default withDefaultPackageScripts(({ script, command }) => {
  script('postbump', [
    // Runs del .cache --force
    command('del', {
      args: ['.cache', { force: true }]
    })
  ], {
    description: 'Runs after the "bump" script.'
  })
});

NPM Lifecycles

ts also provides a prepare script that will build and lint the project and run unit tests. The prepare lifecycle script is designed to ensure that when a developer clones a repository for the first time and runs npm install, they can be confident that the project builds and that its tests are passing. This gives the developer confidence that the project's tooling is configured correctly and that its source code is in a good, working state.

To have NPM run this script as part of the "prepare" lifecycle, you must create an alias in package.json:

package.json
{
  "scripts": {
    "prepare": "nr prepare"
  }
}

Last updated