@kyanny's blog

My thoughts, my life. Views/opinions are my own.

npm package をオフラインでインストールする

インターネットに接続していないホスト*1に npm パッケージをインストールするには、windows - How to install NodeJS project locally without internet connection? - Stack Overflow で紹介されているように、npm packbundledDependencies で依存パッケージを同梱した tgz ファイルを作り、そのファイルを該当ホストに scp 等でコピーして npm install すればよい。

StackOverflow のコメントでは、(npm init 等で)新しく package.json を作り、bundledDependencies に対象パッケージ名を書く、という流れを想定していそうだが、対象パッケージの package.json を書き換えてもよい。

例: https://www.npmjs.com/ では公開されていない ghec-audit-log-cli というコマンドをオフラインでインストールする場合。

1. インターネットに接続しているホスト上で対象パッケージのソースコードを手に入れる

git clone https://github.com/github/ghec-audit-log-cli
cd ghec-audit-log-cli/

2. package.jsonbundledDependencies を追加する

dependencies に列挙されているパッケージ名をコピーすればよい。それで足りなければ他の項目にある依存パッケージも追記する。テキストエディタで書き換えてもよいし、ワンライナーで片付けてもよい。

python3 -c 'import json; f=open("package.json", "r"); data=json.loads(f.read()); data["bundledDependencies"]=list(data["dependencies"].keys()); f.close(); f=open("package.json", "w"); f.write(json.dumps(data, indent=2)); f.close()'

diff はこんな感じになる。

git diff
diff --git a/package.json b/package.json
index 46e680a..d318b16 100644
--- a/package.json
+++ b/package.json
@@ -45,5 +45,15 @@
   },
   "devDependencies": {
     "standard": "^16.0.3"
-  }
-}
+  },
+  "bundledDependencies": [
+    "@octokit/plugin-enterprise-cloud",
+    "@octokit/plugin-retry",
+    "@octokit/plugin-throttling",
+    "@octokit/rest",
+    "commander",
+    "json-hash",
+    "validate.js",
+    "yaml"
+  ]
+}
\ No newline at end of file

3. npm install する

pack 前に依存パッケージをインストールするため。

npm install

4. npm pack する。

npm pack

ghec-audit-log-cli-2.0.0.tgz というファイルが作成される。パッケージ名-バージョン番号.tgz という書式。

5. 作成された tgz ファイルをインターネット接続のないホストにコピーする

scp するなり、USB メモリを介してコピーするなり、なんなりと。

6. インターネット接続のないホスト上で対象パッケージを npm install する

npm install ghec-audit-log-cli-2.0.0.tgz

Vagrant で VM を作成し、default route を削除した上で、オフラインインストールできるか検証する。検証前にNode.js をインストールしておくこと。

vagrant init ubuntu/focal64 -f
vagrant up
sudo apt update
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo apt install net-tools
sudo route del default

https://www.npmjs.com/ には接続できない。

vagrant@ubuntu-focal:~$ ping www.npmjs.com
ping: connect: Network is unreachable

vagrant@ubuntu-focal:~$ curl https://www.npmjs.com/
curl: (7) Couldn't connect to server

しかし、パッケージをインストールできる。

npm install /vagrant/ghec-audit-log-cli-2.0.0.tgz
npm WARN saveError ENOENT: no such file or directory, open '/home/vagrant/package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open '/home/vagrant/package.json'
npm WARN vagrant No description
npm WARN vagrant No repository field.
npm WARN vagrant No README data
npm WARN vagrant No license field.

+ ghec-audit-log-cli@2.0.0
added 64 packages from 74 contributors in 3.234s

1 package is looking for funding
  run `npm fund` for details

ちゃんとコマンドも実行できる。

npx ghec-audit-log-cli --help
Usage: ghec-audit-log-cli [options]

Options:
  -v, --version             Output the current version
  -t, --token <string>      the token to access the API (mandatory)
  -o, --org <string>        the organization we want to extract the audit log from
  -cfg, --config <string>   location for the config yaml file. Default ".ghec-audit-log" (default: "./.ghec-audit-log")
  -p, --pretty              prints the json data in a readable format (default: false)
  -l, --limit <number>      a maximum limit on the number of items retrieved
  -f, --file <string>       the output file where the result should be printed
  -a, --api <string>        the version of GitHub API to call (default: "v4")
  -at, --api-type <string>  Only if -a is v3. API type to bring, either all, web or git (default: "all")
  -c, --cursor <string>     if provided, this cursor will be used to query the newest entries from the cursor provided. If not present, the result will contain all the audit log
                            from the org
  -s, --source <string>     the source of the audit log. The source can be either a GitHub Enterprise or a GitHub Enterprise Organization. Accepts the following values: org |
                            enterprise. Defaults to org (default: "org")
  -h, --help                display help for command

*1:あるいは、プロキシサーバ・ファイアウォール・セキュリティソフトなどに阻まれて npm install できないホスト