ppp という, Node.js のパッケージ情報を表示するコマンドラインツールを作ったのでそのご紹介です.
それ npm view
で良いじゃん, とか, 前も似たようなの作っていなかった? などと思った方もおられると思いますが, 新しく作ったのにはちゃんと理由がありますので, まずはお読みください...
背景
世の中には OS / プログラミング言語ごとに様々なパッケージマネージャがありますが, これらには大体 info
サブコマンドのような機能があって, パッケージの情報を表示することができます.
例としていくつか挙げるとこんな感じです:
- Homebrew
$ brew info node node: stable 11.7.0 (bottled), HEAD Platform built on V8 to build network applications https://nodejs.org/ Not installed From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/node.rb ==> Dependencies Build: pkg-config ✔, python@2 ✔ Required: icu4c ✔ ==> Options --HEAD Install HEAD version ==> Analytics install: 289,885 (30 days), 959,391 (90 days), 3,944,852 (365 days) install_on_request: 220,363 (30 days), 722,068 (90 days), 2,846,827 (365 days) build_error: 0 (30 days)
- Cabal
$ cabal info array * array (library) Synopsis: Mutable and immutable arrays Versions available: 0.3.0.2, 0.3.0.3, 0.4.0.0, 0.4.0.1, 0.5.0.0, 0.5.1.0, 0.5.1.1, 0.5.2.0, 0.5.3.0 (and 4 others) Versions installed: 0.5.2.0 Homepage: [ Not specified ] Bug reports: http://ghc.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29&keywords=array Description: In addition to providing the "Data.Array" module <http://www.haskell.org/onlinereport/haskell2010/haskellch14.html as specified in the Haskell 2010 Language Report>, this package also defines the classes 'IArray' of immutable arrays and 'MArray' of arrays mutable within appropriate monads, as well as some instances of these classes. Category: Data Structures License: BSD3 Maintainer: libraries@haskell.org Source repo: http://git.haskell.org/packages/array.git Dependencies: base >=4.9 && <4.13 Documentation: /usr/local/Cellar/ghc/8.4.4/share/doc/ghc-8.4.4/html/libraries/array-0.5.2.0 Cached: No Modules: Data.Array Data.Array.Base Data.Array.IArray Data.Array.IO Data.Array.IO.Internals Data.Array.IO.Safe Data.Array.MArray Data.Array.MArray.Safe Data.Array.ST Data.Array.ST.Safe Data.Array.Storable Data.Array.Storable.Internals Data.Array.Storable.Safe Data.Array.Unboxed Data.Array.Unsafe
- opam
$ opam info base <><> base: information on all versions ><><><><><><><><><><><><><><><><><><> 🐫 name base all-installed-versions v0.11.0 [4.06.1] all-versions v0.9.0 v0.9.1 v0.9.2 v0.9.3 v0.9.4 v0.10.0 v0.11.0 v0.11.1 <><> Version-specific details <><><><><><><><><><><><><><><><><><><><><><><> 🐫 version v0.11.1 repository default url.src: "https://github.com/janestreet/base/releases/download/v0.11.1/base-v0.11.1.tbz" url.checksum: "md5=e7e7dc5db3f1fea19d74a31bbd4ac621" homepage: "https://github.com/janestreet/base" bug-reports: "https://github.com/janestreet/base/issues" dev-repo: "git+https://github.com/janestreet/base.git" authors: "Jane Street Group, LLC <opensource@janestreet.com>" maintainer: "opensource@janestreet.com" license: "Apache-2.0" depends: "ocaml" {>= "4.04.1"} "sexplib0" {>= "v0.11" & < "v0.12"} "jbuilder" {build & >= "1.0+beta18.1"} depopts: "base-native-int63" synopsis Full standard library replacement for OCaml description Full standard library replacement for OCaml Base is a complete and portable alternative to the OCaml standard library. It provides all standard functionalities one would expect from a language standard library. It uses consistent conventions across all of its module. Base aims to be usable in any context. As a result system dependent features such as I/O are not offered by Base. They are instead provided by companion libraries such as stdio: https://github.com/janestreet/stdio
こういったコマンドがあるといちいちパッケージリポジトリを見に行ったりしなくて良いので大変便利ですね.
我らが npm には npm view
(エイリアスとして npm info
や npm show
も使える) というサブコマンドがあります.
ところがこれは一昔前はこんな出力をしていました1:
$ npm --version 5.8.0 $ npm view react-dom { name: 'react-dom', description: 'React package for working with the DOM.', 'dist-tags': { latest: '16.7.0', next: '16.8.0-alpha.1', canary: '0.0.0-3e15b1c69', tmp: '16.3.3', unstable: '0.0.0-0c756fb-f7f79fd' }, versions: [ '0.0.0-0c756fb-697f004', '0.0.0-0c756fb-f7f79fd', '0.0.0-3e15b1c69', '0.0.0-4a1072194', '0.0.0-7325ebe4d', ... (以下 500 行ほど続く)
JSON を console.log
しただけ, みたいな雑な感じなのはこの際許すとして, 平気で数百行単位で出力されるため, とても人間が読むことはできませんでした.
(といっても頑張って読んだりしていた... またはいちいち npm view react-dom version
みたいにして個々のフィールドを見ていた.)
これではあまりに不便に感じたため, 以前この npm view
をラップして, いい感じに結果を整形して表示してくれるコマンド npm-sum
を作りました.
これを使えばそこそこ見やすい形で出力してくれます:
$ npm-sum react-dom Name : react-dom Version : 16.7.0 (12/20/2018, 10:20:03 AM) Homepage : https://reactjs.org/ License : MIT Description : React package for working with the DOM. Keywords : react Tags : canary : 0.0.0-3e15b1c69 (1/15/2019, 7:34:29 AM) latest : 16.7.0 (12/20/2018, 10:20:03 AM) next : 16.8.0-alpha.1 (1/16/2019, 8:22:20 AM) tmp : 16.3.3 (8/2/2018, 3:58:58 AM) unstable : 0.0.0-0c756fb-f7f79fd (11/13/2018, 12:47:42 PM) Dependencies : loose-envify@^1.1.0, object-assign@^4.1.1, prop-types@^15.6.2, scheduler@^0.12.0
一方, 幸い現代では npm view
も改良され2, 人間に読める形で表示されるようになりました.
$ npm --version 6.7.0 $ npm view react-dom react-dom@16.7.0 | MIT | deps: 4 | versions: 135 React package for working with the DOM. https://reactjs.org/ keywords: react dist .tarball: https://registry.npmjs.org/react-dom/-/react-dom-16.7.0.tgz .shasum: a17b2a7ca89ee7390bc1ed5eb81783c7461748b8 .integrity: sha512-D0Ufv1ExCAmF38P2Uh1lwpminZFRXEINJe53zRAbm4KPwSyd6DY/uDoS0Blj9jvPpn1+wivKpZYc8aAAN/nAkg== .unpackedSize: 4.5 MB dependencies: loose-envify: ^1.1.0 object-assign: ^4.1.1 prop-types: ^15.6.2 scheduler: ^0.12.0 maintainers: - acdlite <npm@andrewclark.io> - brianvaughn <briandavidvaughn@gmail.com> - fb <opensource+npm@fb.com> - flarnie <flarnie.npm@gmail.com> - gaearon <dan.abramov@gmail.com> - sebmarkbage <sebastian@calyptus.eu> - sophiebits <npm@sophiebits.com> - threepointone <threepointone@gmail.com> - trueadm <dg@domgan.com> - zpao <paul@oshannessy.com> dist-tags: canary: 0.0.0-3e15b1c69 next: 16.8.0-alpha.1 unstable: 0.0.0-0c756fb-f7f79fd latest: 16.7.0 tmp: 16.3.3 published a month ago by acdlite <npm@andrewclark.io>
では自作の npm-sum
を捨てて npm view
を使うようになったかと言うと, そうはなりませんでした.
というのも以下のような点で不満があったためです.
- 情報について:
- dist.tarball や .shasum を見て使うのはパッケージマネージャであって, 人間ではないのでは?
- dependencies を見て何か思うことはあまりなくて, むしろ peerDependencies の方が requirements なので知りたい
- maintainers を並べられても特に嬉しいとは思わない
- 色について:
deps: 4
とversions: 135
で数字の色が違うけれど, versions の方は黄色だから警告とかの意味があるのかな? と思うけど実は特に意味はない- 全体的にただカラフルなだけで, あまり整理されているような印象は受けず, 読みやすいとは思わない
- フォーマットについて:
見出し: 内容
のような構成なのかと思ったら例外も多かったり, 急に自然言語になったりして, 統一感がないように感じる- 最後に書いてある何時 publish されたかは割と知りたいし, 最初に書いてあるバージョンに関連した情報であって近くにある dist-tags の各バージョンとは関連しないので, どちらかといえば最初の方に書いてあって欲しい
こういった理由で npm-sum
を使い続けていたわけですが, こちらも完璧な出来というわけではありません.
再度出力例を挙げますが,
$ npm-sum react-dom Name : react-dom Version : 16.7.0 (12/20/2018, 10:20:03 AM) Homepage : https://reactjs.org/ License : MIT Description : React package for working with the DOM. Keywords : react Tags : canary : 0.0.0-3e15b1c69 (1/15/2019, 7:34:29 AM) latest : 16.7.0 (12/20/2018, 10:20:03 AM) next : 16.8.0-alpha.1 (1/16/2019, 8:22:20 AM) tmp : 16.3.3 (8/2/2018, 3:58:58 AM) unstable : 0.0.0-0c756fb-f7f79fd (11/13/2018, 12:47:42 PM) Dependencies : loose-envify@^1.1.0, object-assign@^4.1.1, prop-types@^15.6.2, scheduler@^0.12.0
- 情報の取捨選択ができていない:
- とりあえず全ては生の JSON よりマシという気持ちで雑に作ったため, あまり取捨選択はしていなかった
- 例えば
npm view
のところでも書いたように, dependencies よりも peerDependencies が表示されて欲しい
- 知りたい情報の変化:
- 例えば最近だと TypeScript 向けの型情報が提供されるかもわかると嬉しいと思う
- 表示のカスタマイズ性:
- ここまで この情報は知りたい とか 知りたくない とか書いているけれど, これは人によって違う可能性がある
といった課題が見つかってきます.
元々 npm-sum
は「パッケージの情報を人間にも読めるように表示する」というコンセプトで作ったわけですが, npm view
が人間にも読めるようになってしまった以上, この点については最早 npm-sum
の強みではなくなってしまいました.
ということで, ここまでに npm view
と npm-sum
のそれぞれで挙げたような課題を解決し, 「パッケージの情報を適切に取捨選択した上で, 見やすい形で表示する」というコンセプトで新たなツールを作ることにしました.
ppp
完成したものがこちらです.
以下のコマンドでインストールできます.
npm i -g @susisu/ppp
使い方は以下のように npm view
で取得した JSON を標準出力から受け取ります.
これは npm-sum
のように npm view
をラップして動かす設計は責任が増えて筋が悪いなと思ったのと, 昨今のツールの多様化を考慮してです.
名前に npm を含まないのもそのため.
npm view react-dom --json | ppp
とはいえ面倒なので, 私は以下のようなスクリプトを ns
という名前で作って ns react-dom
みたいに使っています (標準で同梱しても良いかもしれない).
ns
が何の略なのかはご想像におまかせします.
#!/bin/sh npm view "$@" --json | ppp
2019/02/03 追記: やっぱり ppp react-dom
みたいに直接パッケージ名を指定しても動くようにしました. 利便性には勝てなかった.
閑話休題, デフォルトの設定では以下のような表示になります:
$ npm view react-dom --json | ppp Name : react-dom Version : 16.7.0 (12/20/2018, 10:20:03 AM) Description : React package for working with the DOM. License : MIT Homepage : https://reactjs.org/ Peer Dependencies : react@^16.0.0 Tags : canary : 0.0.0-3e15b1c69 (1/15/2019, 7:34:29 AM) latest : 16.7.0 (12/20/2018, 10:20:03 AM) next : 16.8.0-alpha.1 (1/16/2019, 8:22:20 AM) tmp : 16.3.3 (8/2/2018, 3:58:58 AM) unstable : 0.0.0-0c756fb-f7f79fd (11/13/2018, 12:47:42 PM)
デフォルト設定は見て分かる通りかなり表示項目を絞っていますが, 設定ファイルを使うことで表示項目をカスタマイズできるようになっています. 詳しくは README を参照してください.
私の場合は以下のように設定して, ES Modules や TypeScript 用の型定義の有無なども表示するようにしています.
fields: - name - version - description - license - author - homepage - npm - repository - module - types - binaries - engines - peerDependencies - tags wrap: 120
こうしておくと, 例えば react-dom を TypeScript で使うときは別途型定義をインストール必要があるとか, 一方で rxjs の場合は必要ないといったことがわかって便利です.
$ npm view react-dom --json | ppp Name : react-dom Version : 16.7.0 (12/20/2018, 10:20:03 AM) Description : React package for working with the DOM. License : MIT Homepage : https://reactjs.org/ NPM : https://www.npmjs.com/package/react-dom Repository : git+https://github.com/facebook/react.git Module : No Types : No Peer Dependencies : react@^16.0.0 Tags : canary : 0.0.0-3e15b1c69 (1/15/2019, 7:34:29 AM) latest : 16.7.0 (12/20/2018, 10:20:03 AM) next : 16.8.0-alpha.1 (1/16/2019, 8:22:20 AM) tmp : 16.3.3 (8/2/2018, 3:58:58 AM) unstable : 0.0.0-0c756fb-f7f79fd (11/13/2018, 12:47:42 PM) $ npm view rxjs --json | ppp Name : rxjs Version : 6.3.3 (9/26/2018, 8:52:58 AM) Description : Reactive Extensions for modern JavaScript License : Apache-2.0 Author : Ben Lesh <ben@benlesh.com> Homepage : https://github.com/ReactiveX/RxJS NPM : https://www.npmjs.com/package/rxjs Repository : git+https://github.com/reactivex/rxjs.git Module : Yes Types : Yes Engines : npm@>=2.0.0 Tags : alpha : 6.0.0-alpha.4 (3/14/2018, 4:00:55 AM) beta : 6.0.0-beta.4 (3/30/2018, 5:15:32 AM) forward-compat : 5.6.0-forward-compat.5 (5/22/2018, 2:08:43 PM) latest : 6.3.3 (9/26/2018, 8:52:58 AM) rc : 6.0.0-uncanny-rc.7 (4/14/2018, 6:55:37 AM) smoosh : 6.0.0-smoosh.1 (4/2/2018, 5:21:39 AM) unsmoosh : 6.0.0-smoosh.2 (4/2/2018, 12:23:50 PM)
よかったですね〜.
おまけ
ところで Yarn にも yarn info
というコマンドがありますが, こちらはどうでしょうか?
$ yarn info react-dom yarn info v1.13.0 { name: 'react-dom', description: 'React package for working with the DOM.', 'dist-tags': { latest: '16.7.0', next: '16.8.0-alpha.1', canary: '0.0.0-3e15b1c69', tmp: '16.3.3', unstable: ... (以下 900 行ほど続く)
......
-
一応公平性のために言っておくと, 例として react-dom の情報を見ているのは後の話の都合上で, 私自身特に思い入れはないです.↩
-
この当たり前のような機能を搭載した npm 5.10.0 がリリースされたのはなんと 2018 年 5 月 12 日 (より正確には 5.9.0-next.0 で 2018 年 3 月 24 日) で, なんとこの記事を書いている一年前の時点ではまだなかった↩