`pnpm update` は `package.json` 中の `node-semver` を更新してしまうことがある

# `pnpm update` は `package.json` 中の `node-semver` を更新してしまうことがある

[pnpm update \| pnpm](https://pnpm.io/cli/update)

`.npmrc` 回避方法はあるのかもしれないが、そういう前提で利用するということで、検証結果を記録しておく.

- 本記事中に登場するパッケージは架空のものであり、出力例は一部適当な内容である
- 様々なパターンの `node-semver` で検証した訳では無い


## 検証環境

```shell-session
$ node --version
v22.14.0
$ npm --version
10.9.2
$ pnpm --version
10.11.0
```

## インストール済みのバージョンよりも新しいものが公開されている

```shell-session
$ npm info @scope/name

@scope/name@0.10.0 | MIT | deps: none | versions: 6
Package description
https://example.com/scope/name

keywords: nodejs, typescript

dist
.tarball: https://registry.npmjs.org/@scope/name/-/name-0.10.0.tgz
.shasum: 9e68b22e560cdaa486addf40bcac038459e29243
.integrity: sha512-LYvwQb1t6/42EPDrmBkuQ/vVw8nlEPaZdHyeLq5M2XCKDZ8PmxEkEPJDzfRrxFaDPo3RT/1hYmQd0pmTi6Ejqg==
.unpackedSize: 6.2 kB

maintainers:
- foo <foo@example.com>

dist-tags:
latest: 0.10.0

published 48 minutes ago by foo <foo@example.com>
```

`package.json` 中の指定内容

```shell-session
$ grep '@scope/name' packages/a/package.json packages/b/package.json 
packages/a/package.json:    "@scope/name": "~0"
packages/b/package.json:    "@scope/name": "~0.9"
```

インストール済みのもの

```shell-session
$ pnpm --filter "./packages/**" list --recursive # pnpm
Legend: production dependency, optional only, dev only

a@0.0.1 /path/to/repo-root/packages/a

dependencies:
@scope/name 0.9.0

b@0.1.0-beta /path/to/repo-root/packages/b

dependencies:
@scope/name 0.9.0
```


## `pnpm update`


今回は `--recursive --interactive` を付与して実行。付与しなくても最終的な結果は変わらない。


```shell-session
$ pnpm update --recursive --interactive # pnpm         
Scope: all 3 workspace projects
? Choose which packages to update (Press <space> to select, <a> to toggle all, <i> to invert selection) … 
❯ ○ dependencies
    ○ Package                                                    Current   Target            Workspace   URL 
    ○ @scope/name                                              0.9.0 ❯ 0.10.0            a               
```

更新


```shell-session
$ pnpm update --recursive --interactive # pnpm         
Scope: all 3 workspace projects
✔ Choose which packages to update (Press <space> to select, <a> to toggle all, <i> to invert selection) · @scope/name
.                                        |   +1 +
Progress: resolved 39, reused 39, downloaded 0, added 0, done
Done in 41.8s using pnpm v10.11.0
```




## 更新後の状態

パッケージは想定通り更新されている.

```shell-session
$ pnpm --filter "./packages/**" list --recursive # pnpm
Legend: production dependency, optional only, dev only

a@0.0.1 /path/to/repo-root/packages/a

dependencies:
@scope/name 0.10.0

b@0.1.0-beta /path/to/repo-root/packages/b

dependencies:
@scope/name 0.9.0
```

この際 `package.json` の `node-semver` が変更される。

```diff
$ git diff -- packages/
diff --git a/packages/a/package.json b/packages/a/package.json
index 8c48a56..88ac0e5 100644
--- a/packages/a/package.json
+++ b/packages/a/package.json
@@ -13,7 +13,7 @@
   "license": "ISC",
   "description": "",
   "dependencies": {
-    "@scope/name": "~0"
+    "@scope/name": "~0.10.0"
   },
   "devDependencies": {
     "abbrev": "^3.0.1"
diff --git a/packages/b/package.json b/packages/b/package.json
index 7ac9935..8683f9f 100644
--- a/packages/b/package.json
+++ b/packages/b/package.json
@@ -12,6 +12,6 @@
   "license": "ISC",
   "description": "",
   "dependencies": {
-    "@scope/name": "~0.9"
+    "@scope/name": "~0.9.0"
   }
 }
```

## なぜだろう?

[Workspace \| pnpm](https://pnpm.io/workspaces) では `"bar": "workspace:~",` が `"bar": "~1.5.0",` として扱われると書いてある、そういうことなのかな?