# npm, pnpm, Yarn and Bun

> Install JavaScript packages from Telesphorepo with npm, pnpm, Yarn or Bun, and what is different when you publish them.

Source: https://docs.telesphorepo.com/npm/

This page sets up a project to install packages from Telesphorepo. To publish a package, see [Publish from a project](/publish-from-a-project/), under Publish your packages; what is different for npm is under [Publish to this repository](#publish-to-this-repository).

An admin first makes a repository with the format **npm** (see [Make a repository](/repositories-and-access/#make-a-repository)). The examples use the server `repo.example.com` and a repository named `js`, so the registry is this:

```text
https://repo.example.com/npm/js/
```

Put your own values in the blocks below. The **Use this repository** tab of the repository shows the same blocks with your values.

## Install packages

1. Point the project at the repository. Put the file in the project folder, next to `package.json`.

   #### .npmrc, anyone can download

   ```ini title=".npmrc"
   registry=https://repo.example.com/npm/js/
   ```

   #### .npmrc, only signed-in people

   ```ini title=".npmrc"
   registry=https://repo.example.com/npm/js/
   //repo.example.com/npm/js/:_authToken=${NPM_TOKEN}
   ```

   The second line names the registry without `https:`. The file holds no token, so you can commit it.

   #### .yarnrc.yml, your own packages, anyone can download

   ```yaml title=".yarnrc.yml"
   npmRegistryServer: "https://repo.example.com/npm/js/"
   npmMinimalAgeGate: 0
   ```

   #### .yarnrc.yml, your own packages, only signed-in people

   ```yaml title=".yarnrc.yml"
   npmRegistryServer: "https://repo.example.com/npm/js/"
   npmAlwaysAuth: true
   npmAuthToken: "${NPM_TOKEN}"
   npmMinimalAgeGate: 0
   ```

   #### .yarnrc.yml, public packages too, anyone can download

   ```yaml title=".yarnrc.yml"
   npmRegistryServer: "https://repo.example.com/npm/js/"
   ```

   #### .yarnrc.yml, public packages too, only signed-in people

   ```yaml title=".yarnrc.yml"
   npmRegistryServer: "https://repo.example.com/npm/js/"
   npmAlwaysAuth: true
   npmAuthToken: "${NPM_TOKEN}"
   ```

   #### Yarn and the age gate, your own packages

   Yarn 4 installs a version only once it is a week old. `npmMinimalAgeGate: 0` turns that off, so Yarn installs a version that you published a minute ago.

   #### Yarn and the age gate, public packages too

   Yarn 4 installs a version only once it is a week old. To install your own packages at once, list them in `npmPreapprovedPackages`, for example `- "@acme/*"`.

2. Make a read token, and give it to the package manager.

   #### Anyone can download

   Skip this step. Anyone can download.

   #### Only signed-in people

   **Settings** › **Tokens** › **New read token**. Type a name, then click **Create token**. Then paste the token at the hidden prompt:

   ```sh
   printf 'Read token: '; read -rs NPM_TOKEN; echo
   export NPM_TOKEN
   ```

   In CI, keep the token in a secret, and set `NPM_TOKEN` to it.

3. Install a package.

   #### npm

   ```sh
   npm install @acme/ui@1.2.0
   ```

   #### pnpm

   ```sh
   pnpm add @acme/ui@1.2.0
   ```

   #### Yarn

   ```sh
   yarn add @acme/ui@1.2.0
   ```

   #### Bun

   ```sh
   bun add @acme/ui@1.2.0
   ```

Done when the install ends with no error, and `node_modules` holds the package.

## Your own packages

A hosted repository holds your own packages only. The package manager then cannot find a public package such as `react` through it. To install both through one address, ask your server admin for a group of your repository and a proxy of `registry.npmjs.org`. Then point the project at the group.

## Public packages too

A group asks its members in order. The first member that has a package name owns it, and the group serves every version of that name from that member only. So a public package with the name of your private package cannot take its place, even with a higher version. Your admin puts your hosted repository before the proxy.

## Publish to this repository

Publish as in [Publish from a project](/publish-from-a-project/): run the setup line in the folder that holds `package.json`, commit `telesphorepo.toml`, then run `telesphorepo publish`. Done when the publish ends with no error, and the version shows on the repository page in the web UI.

The CLI picks the package manager by the lockfile, and runs its publish with a publish token for this one repository:

| Lockfile                      | The CLI runs                   |
| ----------------------------- | ------------------------------ |
| `pnpm-lock.yaml`              | `pnpm publish --no-git-checks` |
| `yarn.lock` and `.yarnrc.yml` | `yarn npm publish`             |
| `bun.lock` or `bun.lockb`     | `bun publish`                  |
| none of these                 | `npm publish`                  |

The package manager packs the package, so `files`, `prepack` and `workspace:` ranges work as usual. You do not run `npm login`. You do not change `package.json` or `.npmrc` to publish.

### The CI file for npm

[Publish from CI](/publish-from-ci/) has the steps. When you choose **GitHub Actions** at setup, the CLI writes this file for the package manager of the project:

### GitHub Actions with npm

```yaml title=".github/workflows/publish.yml"
on:
  push:
    branches: ["main"]

permissions:
  id-token: write
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v5
        with:
          node-version: lts/*
      - run: npm ci
      - run: curl -fsSL https://repo.example.com/install.sh | sh
      - run: telesphorepo publish
```

### GitHub Actions with pnpm

```yaml title=".github/workflows/publish.yml"
on:
  push:
    branches: ["main"]

permissions:
  id-token: write
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v5
        with:
          node-version: lts/*
      - run: pnpm install --frozen-lockfile
      - run: curl -fsSL https://repo.example.com/install.sh | sh
      - run: telesphorepo publish
```

### GitHub Actions with Yarn

```yaml title=".github/workflows/publish.yml"
on:
  push:
    branches: ["main"]

permissions:
  id-token: write
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v5
        with:
          node-version: lts/*
      - run: corepack enable && yarn install --immutable
      - run: curl -fsSL https://repo.example.com/install.sh | sh
      - run: telesphorepo publish
```

### GitHub Actions with Bun

```yaml title=".github/workflows/publish.yml"
on:
  push:
    branches: ["main"]

permissions:
  id-token: write
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: oven-sh/setup-bun@v2
      - run: bun install --frozen-lockfile
      - run: curl -fsSL https://repo.example.com/install.sh | sh
      - run: telesphorepo publish
```

The identity token publishes only. If the install step reads a private repository, keep a read token in a CI secret and set `NPM_TOKEN` to it in that step. For Jenkins, see [Publish from CI](/publish-from-ci/).

## If something goes wrong

Yarn does not install a version that you just published

Yarn 4 installs a version only once it is a week old. For a hosted repository, add `npmMinimalAgeGate: 0` to `.yarnrc.yml`. For a group or a proxy, list your own packages in `npmPreapprovedPackages`.

401 when Yarn installs from a private repository

Yarn sends the token on installs only with `npmAlwaysAuth: true`. Add it to `.yarnrc.yml`.

401 when npm, pnpm or Bun installs

Check that `NPM_TOKEN` holds a read token, and that the `_authToken` line names the same address as `registry=`, without `https:`.

Yarn refuses an `http://` server

Add the host name of the server to `unsafeHttpWhitelist` in `.yarnrc.yml`. For real use, serve the server over HTTPS. See [Serve over HTTPS](/run-the-server/#serve-over-https).

The package manager cannot find a public package

The repository is hosted, and holds your own packages only. Ask your server admin for a group with a proxy of `registry.npmjs.org`.

A group serves your private package, not the public one with the same name

The first member that has a name owns it. Rename your package, or ask your admin to change the order of the members.

`npm login is not used with Telesphorepo`

To install, put a read token in `.npmrc`. To publish, run `telesphorepo publish`.

403 `version 1.2.0 of x already exists`

That version is on the server. Raise the version in `package.json`.

The CLI says that the project publishes with pnpm, and pnpm is not on the PATH

The CLI picks the package manager by the lockfile. Install that package manager, or remove the lockfile of the one you do not use.

You want to take a version back

Open the repository in the web UI, then the **Files** tab, and delete the tarball of the version. The server then drops that version from the package. You need **Delete** on the repository. A CI job cannot unpublish.
