DiffDaily

Deep & Concise - OSS変更の定点観測

[importmap-rails] ネストされたパッケージパスの正確な識別処理を実装

rails/importmap-rails

背景

importmap-railsでは、JavaScriptパッケージのバージョン管理を行う際、パッケージ名をURLから抽出する処理が実装されています。しかし、photoswipe/lightbox@github/webauthn-json/browser-ponyfill のようなネストされたパスを持つパッケージに対して、パッケージ名の識別が正しく機能していませんでした。

この問題により、outdated版のチェック時に誤ったパッケージ名で検索が行われ、バージョン比較が正常に動作しないという課題が発生していました(#321)。

技術的な変更内容

パッケージ名抽出ロジックの追加

lib/importmap/npm.rb に新しいプライベートメソッド extract_base_package_name が追加されました。このメソッドは、ネストされたパスを持つパッケージから、ベースとなるパッケージ名を正確に抽出します。

def extract_base_package_name(package)
  if package.start_with?("@")
    # Scoped packages can have nested paths, e.g. @scope/package/subpath
    parts = package.split("/", 3)
    parts.size > 2 ? parts.first(2).join("/") : package
  else
    # Non-scoped packages - just take the first part
    package.split("/").first
  end
end

このロジックは以下の2つのケースを処理します:

  1. スコープ付きパッケージ@ で始まる):最初の2つのパートを結合してパッケージ名とする

    • @github/webauthn-json/browser-ponyfill@github/webauthn-json
    • @github/webauthn-json@github/webauthn-json(変更なし)
  2. 通常のパッケージ:最初のパートのみを取得

    • photoswipe/lightboxphotoswipe
    • photoswipephotoswipe(変更なし)

packages_with_versionsメソッドの改良

抽出されたパッケージ名とバージョンのペアに対して、新しいロジックを適用し、重複を排除する処理が追加されました。

with_versions.map! do |package, version|
  [extract_base_package_name(package), version]
end.uniq!

この変更により、同一パッケージの異なるサブパスが複数存在する場合でも、ベースパッケージ名として1つにまとめられます。

実際の動作例

ネストされたパスを持つパッケージの場合

Importmap定義:

pin "photoswipe/lightbox", to: "https://ga.jspm.io/npm:photoswipe@5.4.4/dist/photoswipe-lightbox.esm.js"
pin "photoswipe", to: "https://ga.jspm.io/npm:photoswipe@5.4.4/dist/photoswipe.esm.js"

変更前: photoswipe/lightboxphotoswipe が別々のパッケージとして認識される

変更後: 両方とも photoswipe@5.4.4 として正しく認識され、outdatedチェックが正常に機能する

スコープ付きパッケージのネストされたパスの場合

pin "@github/webauthn-json/browser-ponyfill", to: "https://ga.jspm.io/npm:@github/webauthn-json@2.1.1/dist/esm/webauthn-json.browser-ponyfill.js" # @2.1.1

変更後: @github/webauthn-json@2.1.1 として正しく識別され、npmレジストリへの問い合わせが正常に行われる

テストカバレッジ

今回の変更では、以下のケースに対する包括的なテストが追加されています:

  • ネストされたパッケージパスの抽出
  • バージョンコメント付きネストパッケージの処理
  • スコープ付きパッケージのネストパス処理
  • 通常のスコープ付きパッケージの処理
  • outdatedチェックの正常動作

これにより、様々なパッケージ構造に対する堅牢性が確保されました。