◆ package.json の bin に {コマンド名: 実行するファイルのパス}
◆ js ファイルを node 実行するなら実行するファイルに "#!/usr/bin/env node" と shebang つける
◆ インストール時に作られるスクリプトが shebang に応じて変わる

ブラウザと共通のライブラリ以外にも npm のメリットがあります
グローバルインストールしておけば パッケージのプログラムをコマンドとして呼び出せます

例えば eslint
npm -g install eslint

とインストールした後は
eslint --fix -c eslint.config messy_code.js

コマンドラインからこう使えます

作り方

作るのは簡単で package.json の bin にコマンド名と実行するファイルのパスを書きます

サンプルのパッケージを作ってみます
こんなフォルダ構成にします
-- command-sample\
    -- echo1.js
    -- package.json

[echo1.js]
console.log(1)

[package.json]
{
  "name": "command-sample",
  "version": "1.0.0",
  "bin": {
    "echo1": "./echo1.js"
  }
}

1 を表示するだけの機能です
bin の中に コマンド名を key にして そのコマンドで実行するファイルのパスを value に書きます

このパッケージをグローバルでインストールします

そうすれば (Windows) だとユーザフォルダの Appdata\Roaming\npm に echo1 と echo1.cmd ファイルができています
ここに eslint など他のインストールされているコマンド一覧が並びます
nodist や nodebrew などバージョン管理ツール使ってるとそれぞれの場所にファイルが作られます

ところで コマンド名はパッケージ名以外も設定可能なので コマンド名が他のパッケージのものと重複しないように注意が必要かも


コマンドラインから実行できるようになってるので実行してみると……
ehco1

echo1.js のファイルがエディタで開きました


bin で指定したファイルはそのままだとファイルが開くだけです
このままでは .js ファイルに関連づけたプログラムが立ち上がるだけです

JavaScript として実行させるために

Windows で出力されたファイルを見るとこうなっていました

[echo1]
"$basedir/node_modules/command-sample/echo1.js"   "$@"
exit $?

[echo1.cmd]
@"%~dp0\node_modules\command-sample\echo1.js"   %*

単純に開いてるだけですね


他のファイルを見てみるとここがもっと長く色々書かれています
そのファイルの package.json を見ても bin のところは一緒です

違いは実行するファイル自体でした

echo1.js をこうします
#!/usr/bin/env node

console.log(1)

Windows で shebang つけても意味ないように思えますが こうして再度インストールすると

[echo1]
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  "$basedir/node"  "$basedir/node_modules/command-sample/echo1.js" "$@"
  ret=$?
else
  node  "$basedir/node_modules/command-sample/echo1.js" "$@"
  ret=$?
fi
exit $ret

[echo1.cmd]
@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\node_modules\command-sample\echo1.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\node_modules\command-sample\echo1.js" %*
)

実行時に shebang によって node が起動されるのではなく インストール時に shebang に応じてコマンド用のファイルの中身が変わります
なので Windows だからときにせず shebang をつけておけばいいということになります


これでコマンドラインで実行したいものも npm に置いておけば簡単に使えますね