Homebrew を利用して pnpm v7 をインストールする方法を探しているだけなら、
brew install ImSingee/pnpm/pnpm@7
を実行すれば良いです。
pnpm v8 は 1 ヶ月前にリリースされ、大きなバージョンアップデートの一つとして、lock file V6 を導入し、V5 のサポートを停止しました。しかし、古いバージョンを使用しているプロジェクトにプルリクエストを送る場合、新しい依存関係を追加するためには lock file を更新する必要があり、これは受け入れられません。すべてのコラボレーターが pnpm をアップグレードすることを直接期待することはできません。
これにより、pnpm V7 と V8 の共存の問題が生じました。これは難しいことではなく、Corepack や pnvm などのツールがあります。しかし、私にとってはそれらは重すぎます —— Homebrew だけで十分です。
Homebrew の問題の一つは、古いバージョンのインストールをサポートしていないことです。以前導入された homebrew/versions はすでに廃止されており、公式に推奨されている唯一の方法は自分でホスティングすることです —— もちろん、現在 pnpm は公式の古いバージョンのタップを維持していないため、自分で作業するしかありません。
タップの作成#
公式ガイド に従って、以下のコマンドを実行することで空のタップライブラリを作成できます。
brew tap-new ImSingee/homebrew-pnpm
注:ここで tap-new の後のパラメータ形式は <repo>/homebrew-<name>
でなければならず、これにより brew tap <repo>/<name>
でこのタップを有効にし、以降は brew install <repo>/<name>/<formula>
で関連パッケージを直接インストールできます【実際には、repo 名が homebrew-
で始まらない場合、このコマンドは自動的にこのプレフィックスを追加します】。
その後、以下のような情報が表示されます。
Initialized empty Git repository in /opt/homebrew/Library/Taps/imsingee/homebrew-pnpm/.git/
[main (root-commit) 1b89b92] Create imsingee/pnpm tap
3 files changed, 90 insertions(+)
create mode 100644 .github/workflows/publish.yml
create mode 100644 .github/workflows/tests.yml
create mode 100644 README.md
==> Created imsingee/pnpm
/opt/homebrew/Library/Taps/imsingee/homebrew-pnpm
When a pull request making changes to a formula (or formulae) becomes green
(all checks passed), then you can publish the built bottles.
To do so, label your PR as `pr-pull` and the workflow will be triggered.
大体の意味は、/opt/homebrew/Library/Taps/imsingee/homebrew-pnpm
にプロジェクトを作成し、GitHub Action を設定してテストとボトルの構成を手伝ってくれるということです。
フォーミュラの追加#
pnpm@7
のフォーミュラを新たに追加します。ここでは公式の pnpm.rb を使用します。
class Pnpm < Formula
require "language/node"
desc "📦🚀 高速でディスクスペース効率の良いパッケージマネージャ"
homepage "https://pnpm.io/"
url "https://registry.npmjs.org/pnpm/-/pnpm-8.3.1.tgz"
sha256 "ce038ba2617f7a93d0b1f24b733b9d64258b15c97a14c6f37673c8d49e033d9a"
license "MIT"
livecheck do
url "https://registry.npmjs.org/pnpm/latest"
regex(/["']version["']:\s*?["']([^"']+)["']/i)
end
bottle do
sha256 cellar: :any_skip_relocation, arm64_ventura: "78ecd13f60c3baf6913933c8494ca17fc4e5b9f93c46bbc131312ffe41fe7f88"
sha256 cellar: :any_skip_relocation, arm64_monterey: "78ecd13f60c3baf6913933c8494ca17fc4e5b9f93c46bbc131312ffe41fe7f88"
sha256 cellar: :any_skip_relocation, arm64_big_sur: "78ecd13f60c3baf6913933c8494ca17fc4e5b9f93c46bbc131312ffe41fe7f88"
sha256 cellar: :any_skip_relocation, ventura: "2f4f18876a3e2823f86f5500b7c47c173695e7f21eba007c2b7689dd12301145"
sha256 cellar: :any_skip_relocation, monterey: "2f4f18876a3e2823f86f5500b7c47c173695e7f21eba007c2b7689dd12301145"
sha256 cellar: :any_skip_relocation, big_sur: "4be656f6ff04e145810fb6e19f08fb01030798cec610c9d618b1fb01121d9f64"
sha256 cellar: :any_skip_relocation, x86_64_linux: "78ecd13f60c3baf6913933c8494ca17fc4e5b9f93c46bbc131312ffe41fe7f88"
end
depends_on "node" => :test
conflicts_with "corepack", because: "両方が `pnpm` と `pnpx` のバイナリをインストールします"
def install
libexec.install buildpath.glob("*")
bin.install_symlink "#{libexec}/bin/pnpm.cjs" => "pnpm"
bin.install_symlink "#{libexec}/bin/pnpx.cjs" => "pnpx"
end
def caveats
<<~EOS
pnpm は機能するために Node のインストールを必要とします。以下のコマンドでインストールできます:
brew install node
EOS
end
test do
system "#{bin}/pnpm", "init"
assert_predicate testpath/"package.json", :exist?, "package.json は存在する必要があります"
end
end
いくつかの小さな変更を行います。
- ファイル名は公式の
pnpm.rb
ですが、ここではpnpm@7.rb
に変更して区別します。 - クラス名
Pnpm
をPnpmAT7
に変更します。 - URL を必要なバージョンに変更します。現在の最新の v7 バージョンは 7.32.2 です。
- sha256 を対応するバージョンのハッシュに変更します。現在の 7.32.2 に対応するのは
f4b40caa0c6368da2f50b8ef891f225c24f14e7d60e42a703c84d3a9db8efede
です。 livecheck
セクションの URL をhttps://registry.npmjs.org/pnpm
に変更し、regex を/["']latest-7["']:\s*?["']([^"']+)["']/i
に変更します。- bottle を削除します。
最終的に修正されたバージョンは以下の通りです。
class PnpmAT7 < Formula
require "language/node"
desc "📦🚀 高速でディスクスペース効率の良いパッケージマネージャ"
homepage "https://pnpm.io/"
url "https://registry.npmjs.org/pnpm/-/pnpm-7.32.2.tgz"
sha256 "f4b40caa0c6368da2f50b8ef891f225c24f14e7d60e42a703c84d3a9db8efede"
license "MIT"
livecheck do
url "https://registry.npmjs.org/pnpm"
regex(/["']latest-7["']:\s*?["']([^"']+)["']/i)
end
depends_on "node" => :test
conflicts_with "corepack", because: "両方が `pnpm` と `pnpx` のバイナリをインストールします"
def install
libexec.install buildpath.glob("*")
bin.install_symlink "#{libexec}/bin/pnpm.cjs" => "pnpm"
bin.install_symlink "#{libexec}/bin/pnpx.cjs" => "pnpx"
end
def caveats
<<~EOS
pnpm は機能するために Node のインストールを必要とします。以下のコマンドでインストールできます:
brew install node
EOS
end
test do
system "#{bin}/pnpm", "init"
assert_predicate testpath/"package.json", :exist?, "package.json は存在する必要があります"
end
end
変更点の小さな説明#
命名(ファイル名、フォーミュラ名)に関しては、公式の pnpm と区別する必要があり、pnpm@{VERSION}
という形式を選択することで、公式の他の多バージョンパッケージの形式(例えば postgresql、llvm など)と一致させています。クラス名とファイル名は対応させる必要があり、pnpm@7
に対応するのは PnpmAT7
です。
また、pnpm@7.rb
ファイルは、前述の tap-new コマンドで作成された Formula
ディレクトリに保存することもできますし、ルートディレクトリに直接置くこともできます(HomebrewFormula に置くことも可能です)。
URL と sha256 は対応するパッケージのダウンロードアドレスとそのパッケージのダウンロードファイルのハッシュです。最新のバージョンを取得し、そのバージョンに対応するパッケージをダウンロードしてハッシュを取得するために、NPM Registry API を利用できます。
# 現在の V7 最新バージョンを取得
curl -s https://registry.npmjs.org/pnpm | jq '."dist-tags"."latest-7"'
# このバージョンに対応するハッシュを取得
curl -s https://registry.npmjs.org/pnpm/-/pnpm-7.32.2.tgz | sha256sum
livecheck は現在が最新バージョンかどうかを検出するためのもので、pnpm 公式のフォーミュラは latest を取得していますが、ここでは latest-7 を取得するように変更します。
bottle を削除します。これは自動構築の内容であり、新しいフォーミュラには含めるべきではありません。
公開#
公開前に、brew style --fix pnpm@7.rb
を実行してスタイルが規範に合っているか確認する必要があります。
GitHub Action を利用してテストとボトルの構築をトリガーします。コードをコミットした後、直接メインブランチにプッシュするのではなく、PR を提出し、すべてのテストに合格した後に pr-pull
タグを追加します。
その後、誰でも直接 pnpm@7
をインストールできるようになります!
# ケース 1: タップを有効にする
brew tap ImSingee/pnpm
brew install pnpm@7
# ケース 2: 単体の簡単なインストール
brew install ImSingee/pnpm/pnpm@7
公開後のリポジトリは https://github.com/ImSingee/homebrew-pnpm です。ぜひご利用ください、スターもお待ちしています :-)
インストール後の小さなヒント#
<name>@{VERSION}
という命名の利点は、現在使用している環境を汚染しないことです。インストール後に以下のような提示が表示されます。
pnpm@7 は keg-only であり、/opt/homebrew にシンボリックリンクされていません。
これは別のフォーミュラの代替バージョンだからです。
pnpm@7 を PATH の最初に持ってくる必要がある場合は、以下を実行してください:
echo 'export PATH="/opt/homebrew/opt/pnpm@7/bin:$PATH"' >> ~/.zshrc
一般的なフォーミュラとは異なり、このようなものは別のプログラムの異なるバージョンとして検出されるため、システムの PATH にインストールされず、追加のパスに独立して配置されます。
提示に従い、7 バージョンの pnpm を実行したい場合は、全パス /opt/homebrew/opt/pnpm@7/bin/pnpm
を使用する必要があります。これをメインバージョンとして使用したい場合は、/opt/homebrew/opt/pnpm@7/bin
を PATH に追加する必要があります。
もちろん、私のやり方はシンボリックリンクを作成することです。
ln -s /opt/homebrew/opt/pnpm@7/bin/pnpm /usr/local/bin/pnpm7
ln -s /opt/homebrew/opt/pnpm@7/bin/pnpx /usr/local/bin/pnpx7
参考#
https://docs.brew.sh/How-to-Create-and-Maintain-a-Tap
https://stackoverflow.com/questions/3987683/homebrew-install-specific-version-of-formula