|
| 1 | +# Publishing PCN to npm |
| 2 | + |
| 3 | +The PCN monorepo uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing. Packages are published under the scope `@pcn-js/*` (e.g. `@pcn-js/core`, `@pcn-js/ui`, `@pcn-js/data360`, `@pcn-js/fixtures`). |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +- **npm account** — for [public npm](https://www.npmjs.com/) you need an account. |
| 8 | +- **Scope / org** — packages use the scope `@pcn-js/*`. You must [create an npm organization](https://www.npmjs.com/org/create) named **`pcn-js`** (same as the scope) **before** the first publish; otherwise publish returns **E404 Not Found**. If that name is not available, use an [alternative scope](#organization-name-not-available) (e.g. your user scope or a different org name). |
| 9 | +- **Build** — ensure all packages build: from repo root run `pnpm build`. |
| 10 | + |
| 11 | +## Option A: Publish to the public npm registry (registry.npmjs.org) |
| 12 | + |
| 13 | +Use this so any app can install with `npm install @pcn-js/core @pcn-js/ui @pcn-js/data360` (or pnpm/yarn). |
| 14 | + |
| 15 | +1. **Log in to npm** (public registry): |
| 16 | + |
| 17 | + ```bash |
| 18 | + npm login |
| 19 | + # Use your npmjs.com credentials; this targets registry.npmjs.org |
| 20 | + ``` |
| 21 | + |
| 22 | +2. **Add changesets** for the changes you want to release: |
| 23 | + |
| 24 | + ```bash |
| 25 | + pnpm changeset |
| 26 | + # Follow prompts: select packages, choose bump type (major/minor/patch), add summary |
| 27 | + ``` |
| 28 | + |
| 29 | +3. **Version packages** (updates `package.json` versions and CHANGELOGs): |
| 30 | + |
| 31 | + ```bash |
| 32 | + pnpm version-packages |
| 33 | + ``` |
| 34 | + |
| 35 | +4. **Publish** to the public registry. Override the registry so publish goes to npm (not your `.npmrc` default, e.g. Artifactory): |
| 36 | + |
| 37 | + ```bash |
| 38 | + npm config set registry https://registry.npmjs.org/ |
| 39 | + pnpm release |
| 40 | + npm config delete registry # optional: restore previous default |
| 41 | + ``` |
| 42 | + |
| 43 | + Or in one go without changing global config: |
| 44 | + |
| 45 | + ```bash |
| 46 | + npm publish -w @pcn-js/core --registry https://registry.npmjs.org/ |
| 47 | + npm publish -w @pcn-js/ui --registry https://registry.npmjs.org/ |
| 48 | + npm publish -w @pcn-js/data360 --registry https://registry.npmjs.org/ |
| 49 | + npm publish -w @pcn-js/fixtures --registry https://registry.npmjs.org/ |
| 50 | + ``` |
| 51 | + |
| 52 | + With Changesets, the usual flow is `pnpm release`, which runs `changeset publish` (and will use whatever registry is currently configured). So set registry to `https://registry.npmjs.org/` before `pnpm release` when publishing to public npm. |
| 53 | + |
| 54 | +5. **Commit and push** the version bumps and changelogs (and tag if your CI does it): |
| 55 | + |
| 56 | + ```bash |
| 57 | + git add . && git commit -m "chore: release @pcn-js/*" && git push |
| 58 | + ``` |
| 59 | + |
| 60 | +## Option B: Publish to an internal registry (e.g. Artifactory) |
| 61 | + |
| 62 | +If your repo `.npmrc` points to an internal registry (e.g. Artifactory), you can publish there so internal apps can install `@pcn-js/*` from that registry. |
| 63 | + |
| 64 | +1. **Authenticate** to the internal registry (e.g. `npm login` against Artifactory, or use `.npmrc` with `_auth` as already configured). |
| 65 | + |
| 66 | +2. **Add changesets** and **version** as above: |
| 67 | + |
| 68 | + ```bash |
| 69 | + pnpm changeset |
| 70 | + pnpm version-packages |
| 71 | + ``` |
| 72 | + |
| 73 | +3. **Publish** (uses registry from `.npmrc`): |
| 74 | + |
| 75 | + ```bash |
| 76 | + pnpm release |
| 77 | + ``` |
| 78 | + |
| 79 | +4. **Commit and push** version and changelog updates. |
| 80 | + |
| 81 | +## Installing in an app after publishing |
| 82 | + |
| 83 | +- **From public npm:** |
| 84 | + In the app (e.g. vercel-ai-chatbot frontend), replace `file:` links with version ranges: |
| 85 | + |
| 86 | + ```json |
| 87 | + { |
| 88 | + "dependencies": { |
| 89 | + "@pcn-js/core": "^0.1.0", |
| 90 | + "@pcn-js/ui": "^0.1.0", |
| 91 | + "@pcn-js/data360": "^0.1.0" |
| 92 | + } |
| 93 | + } |
| 94 | + ``` |
| 95 | + |
| 96 | + Then run `pnpm install` (or `npm install`). Remove any `pnpm.overrides` that pointed at `file:../../pcn/...` for these packages. |
| 97 | + |
| 98 | +- **From internal registry:** |
| 99 | + Ensure the app’s npm/pnpm config uses the same registry and auth; then use the same version ranges and install as above. |
| 100 | + |
| 101 | +## Summary |
| 102 | + |
| 103 | +| Step | Command | |
| 104 | +| ------------------ | ---------------------------------------------- | |
| 105 | +| Add changesets | `pnpm changeset` | |
| 106 | +| Bump versions | `pnpm version-packages` | |
| 107 | +| Publish (public) | Set registry to npmjs.org, then `pnpm release` | |
| 108 | +| Publish (internal) | `pnpm release` (with registry in `.npmrc`) | |
| 109 | + |
| 110 | +Each package has `"publishConfig": { "access": "public" }` so the scoped packages `@pcn-js/*` are published as public when the target registry supports it (e.g. npm). |
| 111 | + |
| 112 | +## Troubleshooting (public npm) |
| 113 | + |
| 114 | +### E403: Two-factor authentication or granular access token required |
| 115 | + |
| 116 | +npm requires one of the following to publish: |
| 117 | + |
| 118 | +1. **Enable 2FA on your npm account** (recommended): |
| 119 | + - Go to [npm → Account Settings → Two-Factor Authentication](https://www.npmjs.com/settings/~yourusername/account) |
| 120 | + - Turn on “Require two-factor authentication for writes (publishing)” |
| 121 | + - Run `npm login` again; npm will prompt for your OTP when you publish. |
| 122 | + |
| 123 | +2. **Use a granular access token with publish and “bypass 2FA”** (for CI or headless use): |
| 124 | + - Go to [npm → Access Tokens](https://www.npmjs.com/settings/~yourusername/tokens) |
| 125 | + - Create token → “Granular access token” |
| 126 | + - Set permissions: **Packages and scopes** → Read and write for `@pcn-js` (or your scope) |
| 127 | + - Enable “Bypass two-factor authentication when publishing from the command line” |
| 128 | + - Use the token when logging in: `npm login --auth-type=legacy` and paste the token as the password (username can be your npm username or `_authToken`-style usage), or set in `.npmrc`: |
| 129 | + `//registry.npmjs.org/:_authToken=YOUR_TOKEN` |
| 130 | + |
| 131 | +After changing 2FA or creating a token, run **`npm login`** again (with registry set to `https://registry.npmjs.org/` if needed), then retry `pnpm release`. |
| 132 | + |
| 133 | +### E404: Not Found when publishing @pcn-js/* |
| 134 | + |
| 135 | +If you see **404 Not Found - PUT https://registry.npmjs.org/@pcn-js%2f...** or "The requested resource '@pcn-js/...' could not be found or you do not have permission": |
| 136 | + |
| 137 | +- The scope `@pcn-js` must exist on npm. [Create an organization](https://www.npmjs.com/org/create) named **`pcn-js`** (same as the scope). Until the org exists, npm returns 404 for PUT. |
| 138 | +- Ensure you're logged in (`npm login` with registry `https://registry.npmjs.org/`) with the account that owns that org (or is a member with publish rights). |
| 139 | + |
| 140 | +### Organization name not available |
| 141 | + |
| 142 | +If the organization name **pcn** is not available on npm, you can publish under a different scope: |
| 143 | + |
| 144 | +1. **User scope (no org needed)** — Use your npm username. For example, if your username is `avsolatorio`, rename packages to `@avsolatorio/pcn-core`, `@avsolatorio/pcn-ui`, `@avsolatorio/pcn-data360`, `@avsolatorio/pcn-fixtures`. You can publish under your user scope without creating an organization. |
| 145 | +2. **Different org name** — Create an organization with another name (e.g. `pcn-js`, `proof-carrying-numbers`) and use that as the scope: `@pcn-js/core`, `@pcn-js/ui`, etc. |
| 146 | +3. **Unscoped packages** — Publish without a scope: `pcn-core`, `pcn-ui`, `pcn-data360`, `pcn-fixtures`. Install with `npm install pcn-core pcn-ui pcn-data360`. Unscoped names must be globally unique on npm. |
| 147 | + |
| 148 | +To switch scope, update the `name` field in each package's `package.json`, update internal references (e.g. `@pcn-js/core` → `@yourscope/core` in dependencies), and update any docs or app `package.json` that install these packages. |
| 149 | + |
| 150 | +### One-time password (OTP) when 2FA is enabled |
| 151 | + |
| 152 | +If you see **"This operation requires a one-time password from your authenticator"**: |
| 153 | + |
| 154 | +- npm is asking for your 2FA code. Run `pnpm release` in an **interactive** terminal and enter the 6-digit code from your authenticator when prompted. |
| 155 | +- If the prompt doesn't appear (e.g. in a non-interactive or CI environment), pass the OTP for that run: |
| 156 | + `NPM_CONFIG_OTP=123456 pnpm release` |
| 157 | + (Replace `123456` with the current code; it changes every ~30 seconds.) |
| 158 | + |
| 159 | +### Access token expired or revoked |
| 160 | + |
| 161 | +If you see “Access token expired or revoked. Please try logging in again”: |
| 162 | + |
| 163 | +- Run `npm login` (with registry `https://registry.npmjs.org/`). |
| 164 | +- If you use a token in `.npmrc`, generate a new token at [npm Access Tokens](https://www.npmjs.com/settings/~yourusername/tokens) and update the value. |
0 commit comments