.npm-init.js を使って package.json の初期値を設定する

これまでは npm init 実行時に作成される package.json の初期値の設定に .npmrc を使っていましたが、.npm-init.js を使ってより多くのプロパティを設定できるようにしました。

.npmrc を使って package.json の初期値を設定する

npm は設定に .npmrc ファイルを使います1。 ユーザー単位の設定ファイルは ~/.npmrc になります。

npm v6 時点では npm init 時に作成される package.json のプロパティに関係するコンフィグは以下の通りです。

package.json のプロパティ .npmrc のコンフィグ
author.name init-author-name
author.email init-author-email
author.url init-author-url
license init-license
version init-version

.npmrc を使って設定する例は以下のようになります。

init-author-name=John Due
init-author-email=john@example.com
init-license=MIT
init-version=0.1.0

~/.npmrc の問題点

npm でパッケージを公開するために npm adduser (npm login) すると、認証トークンが ~/.npmrc に書き込まれます。 ~/.npmrc を dotfiles リポジトリで管理していたりすると、この認証トークンをリポジトリにコミットする訳にはいけません。

git で特定の行だけ無視するという方法2もありますし、.npmrc を使わずに NPM_CONFIG_INIT_AUTHOR_NAME などの環境変数に設定する3ことでも初期値を設定できます。 ただ、どうせならより柔軟にプロパティを設定できる .npm-init.js を使うことにしました。

.npm-init.js を使って package.json の初期値を設定する

npm init 実行時にはコンフィグ init-module (デフォルト値は ~/.npm-init.js)に設定されたモジュールが呼び出されます。 ファイルが存在しない場合は、init-package-json パッケージの default-input.js が呼び出されます。

このモジュールの仕組みをざっくりと言うと、module.exports でエクスポートした Object がそのまま package.json の初期値に設定されるようになっています。

私は基本的にソースコードディレクトリを ~/src 以下に Go のお作法に習って配置する4ようにしているので、カレントディレクトリがその作法に則っていれば、リポジトリの URL なども初期値に設定するようにしました。

設定した package.json のプロパティ

fixpack を使って package.json をフォーマットすることが多いので、プロパティの順番をそれっぽくしています。 プロパティの詳細は https://docs.npmjs.com/files/package.json にあります。

author

author.name, author.email, author.url は、まとめて author プロパティにショートハンド文字列として設定できます。
例: "John Due <john@example.com> (https://example.com)"

repository

ホスティング先が GitHub, GitLab, Bitbucket の場合は、repository.typerepository.url をまとめて repository プロパティにショートハンド文字列として設定できます。
例: "github:user/repo"

private

意図しない npm publish を防止するために、初期値では true に設定しました。

作成した ~/.npm-init.jsソースコードは以下のようになりました。

// ~/.npm-init.js
function repositoryMeta(provider, user, repo) {
  if (provider === 'github.com' || provider === 'gitlab.com') {
    const homepage = `https://${provider}/${user}/${repo}`;
    return {
      bugs: {
        url: `${homepage}/issues`
      },
      homepage,
      repository: `${provider.replace(/\.com$/, '')}:${user}/${repo}`
    };
  }
  return null;
}

const cwdTree = process.cwd().split('/');
const repo = cwdTree.pop();
const user = cwdTree.pop();
const provider = cwdTree.pop();
const meta = repositoryMeta(provider, user, repo);

// Sort properties as `fixpack` does by default
const json = {
  name: repo,
  description: '',
  version: '0.1.0',
  author: 'Yuichi Tanikawa <kojole.jp@gmail.com> (https://kojole.jp)'
};

if (meta) {
  json.bugs = meta.bugs;
  json.homepage = meta.homepage;
}

json.keywords = [];
json.license = 'MIT';
json.main = '';
json.private = true;

if (meta) {
  json.repository = meta.repository;
}

json.scripts = {
  test: 'exit 1'
};

module.exports = json;

まとめ

npm init 実行時に作成される package.json の初期値の設定に、 ~/.npmrc ではなく ~/.npm-init.js を使うようにしました。 これにより、.npmrcを使うとき以上に柔軟にプロパティの初期値を設定できるようになりました。