ngx-deploy-npm ๐Ÿš€

May 30, 2026 ยท View on GitHub

NPM version NPM donwoads The MIT License Conventional Commits

Reliability Rating Security Rating Maintainability Rating

Linux macOS Windows

Publishment Status Test nx@next Test nx@latest

Cover Image

Publish your libraries to NPM with one command

Table of contents:


๐Ÿš€ Quick Start (local development)

  1. Add ngx-deploy-npm and configure one library at a time with --project and --dist-folder-path:

    npm install --save-dev ngx-deploy-npm
    npm exec nx generate ngx-deploy-npm:install --project=your-library --dist-folder-path=dist/libs/your-library
    

    Repeat the generator for each library you want to publish. There is no bulk --projects install.

  2. Deploy your library to NPM with all default settings.

    nx deploy your-library --dry-run
    
  3. When you are happy with the result, remove the --dry-run option

๐Ÿš€ Continuous Delivery

You can publish from CI in two ways:

  • OIDC trusted publishing (recommended for GitHub Actions) โ€” short-lived credentials from your workflow; no long-lived NPM_TOKEN. See npm trusted publishing.
  • NPM token โ€” classic automation token written to .npmrc. Create one via the NPM web page or npm token create.

GitHub Actions (OIDC trusted publishing)

  1. Configure a trusted publisher on npmjs.com

    • Open your package on npm โ†’ Settings โ†’ Trusted publishing.
    • Choose GitHub Actions and set the Organization/user, Repository, and Workflow filename (e.g. publish.yml โ€” filename only, including .yml).
    • If you use a GitHub environment (e.g. production), enter the same name in npm.
    • Ensure the repository field in the published package.json matches your GitHub repo URL.
  2. Grant OIDC permissions in the workflow

    permissions:
      id-token: write # required for npm OIDC
      contents: read
    
  3. Build, then deploy with ngx-deploy-npm

    Trusted publishing requires npm CLI v11.5.1+. The executor runs npm publish for you โ€” no NPM_TOKEN is needed when OIDC is configured.

    # .github/workflows/publish.yml
    name: Publish
    
    on:
      push:
        branches:
          - main
    
    jobs:
      publish:
        runs-on: ubuntu-latest
        environment: production # optional; must match npm trusted publisher if set
        permissions:
          id-token: write
          contents: read
        steps:
          - uses: actions/checkout@v6
          - uses: actions/setup-node@v6
            with:
              node-version: '22'
              # Do not set registry-url here unless you also provide NODE_AUTH_TOKEN
              # for private dependency installs โ€” an empty token blocks OIDC publish.
          - run: npm ci
          - run: npx nx build your-library
          - run: npx nx deploy your-library
    

    When publishing with OIDC from a public repository, npm adds provenance attestations automatically. To disable them, set NPM_CONFIG_PROVENANCE=false on the deploy step.

  4. Scoped packages, custom registries, and .npmrc

    • For scoped packages on the public registry, set "access": "public" in the deploy target or pass --access=public.

    • For a custom registry, use the deploy --registry option or set it in the project's deploy target options.

    • Add a repo-level .npmrc when you need registry defaults, for example:

      @my-org:registry=https://registry.npmjs.org/
      

      Or for GitHub Packages:

      @my-org:registry=https://npm.pkg.github.com
      

    OIDC trusted publishing applies to npm publish on the registry you configure; private dependency installs may still need a read-only NODE_AUTH_TOKEN on npm ci (see npm docs).

  5. Enjoy your just-released package ๐ŸŽ‰๐Ÿ“ฆ

This repo publishes with OIDC in .github/workflows/publishment.yml โ€” no NPM_TOKEN secret.

GitHub Actions with @jscutlery/semver

@jscutlery/semver bumps the version from your commits and can chain build and deploy via postTargets. Configure a version target on your library (see this repo's project.json):

"version": {
  "executor": "@jscutlery/semver:version",
  "options": {
    "postTargets": ["build", "deploy"]
  }
}

In CI, a single command bumps, builds, and publishes:

permissions:
  id-token: write # omit if using NPM_TOKEN instead (see below)
  contents: read

steps:
  - uses: actions/checkout@v6
    with:
      fetch-depth: 0 # required by semver to read commit history
  - uses: actions/setup-node@v6
    with:
      node-version: '22'
  - run: npm ci
  - run: npx nx version your-library

GitHub Actions with an NPM token

If you are not using OIDC trusted publishing yet, store an automation token as NPM_TOKEN and pass it through setup-node:

# .github/workflows/publish.yml
name: Publish

on:
  push:
    branches:
      - main

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: '22'
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      - run: npx nx build your-library
      - run: npx nx deploy your-library
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

With semver, pass NODE_AUTH_TOKEN on the npx nx version your-library step instead of separate build/deploy steps.

Troubleshooting GitHub Actions auth

SymptomLikely causeFix
ENEEDAUTH with OIDC configured on npmsetup-node wrote //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} but NODE_AUTH_TOKEN is empty, so npm skips OIDCOmit registry-url from setup-node on the publish job, or supply a read-only token only on npm ci
OIDC publish rejectedTrusted publisher workflow filename, repo, or environment does not match npm settingsMatch npm Trusted publishing fields exactly (case-sensitive .yml filename)
OIDC publish rejected from a forkrepository in package.json still points at the upstream repoAlign repository.url with the repo that runs the workflow

CircleCI

  1. Set the env variable

    • On your project setting the env variable. Let's call it NPM_TOKEN
  2. Indicate how to find the token

    • Before publishing, we must indicate to npm how to find that token, do it by creating a step with run: echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > YOUR_REPO_DIRECTORY/.npmrc
    • Replace YOUR_REPO_DIRECTORY for the path of your project, commonly is /home/circleci/repo
  3. (Optional) check that you are logged

    • Creating a step with run: npm whoami
    • The output should be the username of your npm account
  4. Deploy your package

    • Create a step with:

      nx deploy your-library
      
  5. Enjoy your just-released package ๐ŸŽ‰๐Ÿ“ฆ

The complete job example is:

# .circleci/config.yml
jobs:
  init-deploy:
    executor: my-executor
    steps:
      - attach_workspace:
          at: /home/circleci/repo/
      # Set NPM token to be able to publish
      - run: echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > /home/circleci/repo/.npmrc
      - run: npm whoami
      - run: npx nx deploy YOUR_PACKAGE

You can check the steps suggested in the CircleCI's guide

๐Ÿ“ฆ Options

install

--dist-folder-path

  • required
  • Example:
    • nx generate ngx-deploy-npm:install --project=lib-1 --dist-folder-path="dist/libs/lib-1"

Indicates the dist folder path. The path where is located the bundle of your library. The path should be relative to the project's root.

--project

  • required
  • Example:
    • nx generate ngx-deploy-npm:install --project=lib-1 --dist-folder-path="dist/libs/lib-1" โ€“ lib-1 will be configured. It will create the target deploy with the default options on the project lib-1.

Specify which library should be configured.

--access

  • optional
  • Default: public
  • Example:
    • nx generate ngx-deploy-npm:install --access=restricted --project=lib-1 --dist-folder-path="dist/libs/lib-1"

Tells the registry whether to publish the package as public or restricted. It only applies to scoped packages, which default to restricted. If you don't have a paid account, you must publish with --access public to publish scoped packages.

deploy

--dist-folder-path

  • required
  • Example:
    • nx deploy --dist-folder-path='dist/libs/my-project'

Indicate the dist folder path. The path must relative to project's root.

--check-existing

  • optional
  • Example:
    • nx deploy --check-existing=warning
    • nx deploy --check-existing=error
    • nx deploy --check-existing=skip

Check if the package version already exists before publishing. If it exists and --check-existing=warning, it will skip the publishing and log a warning. If it exists and --check-existing=error, it will throw an error. If it exists and --check-existing=skip, it will skip the publishing silently (useful in CI).

--check-tag

  • optional
  • Default: false (boolean)
  • Example:
    • nx deploy --check-existing=warning --check-tag

When set, the duplicate version check only runs when publishing to a non-latest tag. Publishing with the default latest tag (or without --tag) skips the check even if --check-existing is set.

--package-version

  • optional
  • Example:
    • nx deploy --package-version 2.3.4

It's going to put that version on your package.json and publish the library with that version on NPM.

--tag

  • optional
  • Default: latest (string)
  • Example:
    • nx deploy --tag alpha โ€“ Your package will be available for download using that tag, npm install your-package@alpha useful for RC versions, alpha, betas.

Registers the published package with the given tag, such that npm install @ will install this version. By default, npm publish updates and npm install installs the latest tag. See npm-dist-tag for details about tags.

--access

  • Default: public (string)
  • Example:
    • nx deploy --access public

Tells the registry whether to publish the package as public or restricted. It only applies to scoped packages, which default to restricted. If you don't have a paid account, you must publish with --access public to publish scoped packages.

--otp

  • optional
  • Example:
    • nx deploy --otp TOKEN

If you have two-factor authentication enabled in auth-and-writes mode, you can provide a code from your authenticator.

--registry

  • optional
  • Example:
    • nx deploy --registry http://localhost:4873

Configure npm to use any compatible registry you like, and even run your own registry.

--dry-run

  • optional
  • Default: false (boolean)
  • Example:
    • nx deploy --dry-run

For testing: Run through without making any changes. Execute with --dry-run, and nothing will happen. It will show a list of the options used on the console.

Compatibility overview with Nx

VersionNx Workspace Version
v9.1.0>=19.x
v9.0.0>=19.x <21.x
v8.4.0>=16.x <20.x
v8.2.0>=16.x <19.x
v8.1.0>=16.x <18.x
v8.0.0>=16.x <17.x
v7.1.0>=16.x <17.x
v7.0.116.x

๐Ÿ“ Configuration File

To avoid all these command-line cmd options, you can write down your configuration in the project.json file in the options attribute of your deploy project's executor. Just change the option to lower camel case.

A list of all available options is also available here.

Example:

nx deploy your-library --tag alpha --access public --dry-run

becomes

"deploy": {
  "executor": "ngx-deploy-npm:deploy",
  "options": {
    "tag": "alpha",
    "access": "public",
    "dryRun": true
  }
}

Now you can just run nx deploy YOUR-LIBRARY without all the options in the command line! ๐Ÿ˜„

โ„น๏ธ You can always use the --dry-run option to verify if your configuration is correct.

๐Ÿง Essential considerations

Version Generation

This deployer doesn't bump or generate a new package version; here, we care about doing one thing well, publish your libs to NPM. You can change the version package at publishment using the --package-version option.

We strongly recommend using @jscutlery/semver to generate your package's version based on your commits automatically. When a new version is generated you can specify to publish it using ngx-deploy-npm.

For more information go to semver's documentation

We use @jscutlery/semver here on ngx-deploy-npm to generate the package's next version, and we use ngx-deploy-npm to publish that version to NPM. Yes, it uses itself, take a look by yourself ngx-deploy-npm/project.json

One library per install run

The install generator configures a single project per invocation (--project + --dist-folder-path). Run it again for each library you publish.

๐ŸŽ‰ Do you Want to Contribute?

We create a unique document for you to give you through this path.

Readme for Contributors

License

Code released under the MIT license.

Recognitions