投稿日:2021年6月5日
汎用性のあるTypeScriptコードはgithub packageとgithub actionを使ってパッケージ化しましょう。
この記事では再利用可能なTypeScriptコードをgithubのprivateパッケージとして限られた範囲で自動公開、公開したパッケージを利用する方法について解説します。
この記事では以下の環境で確認されました。
またこの記事はgithubのアカウントは作成済の前提で進みます。まだ作成していない方は先にそちらを作成してください。
また記事の内容はTypeScript、github actionへの基本的な知識を前提にしています。
パッケージ名は公式サイトの注意にあるように以下の点に注意します。
今回自分はmarsquai-sample-npm-packageという名前にします。
では実際に作成していきます。
$ mkdir marsquai-sample-npm-package
$ cd marsquai-sample-npm-package
ここでGithubでリポジトリをprivateで作成します。特に理由がない限りは作成するパッケージ名と同名のリポジトリ名にすることをおすすめします。
リポジトリの作成ができたら、ローカルのプロジェクトの設定を完了させましょう。<GITHUB_ORIGIN>には自身のgithub origin名をいれてください。
$ echo "my sample package" >> README.md
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin <GITHUB_ORIGIN>
$ git push -u origin main
次にディレクトリをnpmコマンドで初期化します。今回は簡単のためすべて初期値のまま実行します。
$ npm init -y
この時点で、絶対にリポジトリにアップロードする必要のないディレクトリがあります。それはnpmでパッケージがインストールされるディレクトリです。必要なパッケージはpackage.jsonに記述され、他者がこのパッケージを利用する場合はnpm install
コマンドによって、その都度その環境のnode_modulesディレクトリにパッケージがインストールされます。
まず、この無視するディレクトリを.gitignoreに追加しておきましょう。
node_modules/
これでディレクトリの初期設定は完了です。
ここから自身の簡単なパッケージを作成していきます。
まずは必要なパッケージをインストールします。今回はTypeScriptのパッケージを作成するのでtypescriptをインストールしましょう。typescriptは開発時にのみ使用するので--save-devでインストールします。
$ npm install --save-dev typescript
次に必要なパッケージをインストールします。今回はサンプルとしてjsonwebtokenのパッケージを使うことにします。パッケージ自体は実行時に使うため--saveで、パッケージの型定義は開発時にのみ使用するため--save-devでインストールします。
$ npm install --save jsonwebtoken
$ npm install --save-dev @types/jsonwebtoken
次にTypeScriptの設定ファイル、tsconfig.jsonを作成します。
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": true,
"outDir": "./lib",
"strict": true
},
"include": ["src"],
"exclude": ["node_modules", "**/__tests__/*"]
}
npmのパッケージとして作成する場合にはdeclarationをtrueにすることに注意してください。これをtrueにすることで、TypeScriptの型定義(d.tsファイル)がトランスパイル後のJavaScriptコードと一緒に出力されるため、JavaScript、TypeScriptの両方でこのパッケージを利用できるようになります。
では早速サンプルのtsコードを作成していきましょう。tsconfig.jsonのincludeでsrcと指定したので、すべてのtsファイルはsrcディレクトリに作成していきます。
srcディレクトリを作成してその中にindex.tsを作成しましょう。
var jwt = require('jsonwebtoken');
import {sign} from "jsonwebtoken";
/**
* 与えられた値から適当なJWTトークンを作成する
* @param value
*/
export const generateSampleJWTToken = (value: number) => {
const token = sign({value: value}, "aaaaaa");
console.log(token);
}
トランスパイルしてみましょう。
$ npx tsc
うまくトランスパイルが成功すれば、libディレクトリにトランスパイルされたJavaScriptコードと、TypeScriptの型定義が出力されます。
トランスパイルしたコードがgitの管理対象に入ってしまっていると、コンフリクトが発生した際のソースの管理が面倒になるので除外しておきましょう。
node_modules/
/lib/
次にpackage.jsonに変更を加えます。以下の文を追加しましょう。YOUR_USERNAMEには自身のgithubのユーザー名、PACKAGE_NAMEにはパッケージ名を入れてください。
"name": "@YOUR_USERNAME/PACKAGE_NAME",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": ["lib"],
"publishConfig": {
"registry":"https://npm.pkg.github.com/@YOUR_USERNAME"
},
github actionの定義を作成する前に自身が今使用しているnodeのバージョンを確認します。確認した値はgithub actionの実行環境の定義に使用します。
$ node -v
v10.19.0
自分の環境ではnodeのバージョンは10.19.0のようです。
次にgithub actionを使ってパッケージをデプロイするyamlファイルを作成します。nodeのバージョンはnode -v
の結果より10にします。
YOUR_USERNAMEにはpackage.jsonに書いたものと同じgithubのユーザー名をいれてください。
name: "publish-to-private"
on:
push:
branches:
- main
jobs:
publish-gpr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 10
registry-url: https://npm.pkg.github.com/
scope: '@YOUR_USERNAME'
- run: npm install
- run: npx tsc
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
これでgithubにソースをpushしてみましょう。
$ git add -all
$ git commit -m "publish"
$ git push
pushができたらgithubのリポジトリを見に行きましょう。
下の様にnpmのアイコンとともにパッケージが追加されていればOKです。
実際に使用できるかどうか確認してみます。
まずは確認用のサンプルプロジェクトを作成します。
$ mkdir install_demo & cd install_demo
$ npm init -y
Githubのアイコンから
settings > Developper settings > Personal access tokens
でアクセストークンのページを開きます。
そのページのGenerate new tokenボタンをクリックして生成メニューを開きます。
以下の値を入力してください。
設定できたらGenerate tokenボタンをクリックして生成は完了です。
下の様にトークンが生成されるのでコピーしておきましょう。
サンプルプロジェクトのルートに.npmrcを作成しましょう。YOUR_USERNAMEは自身のgithubのユーザー名、ACCESS_TOKENには上で生成したgithubのトークンをいれてください。
@YOUR_USERNAME:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:_authToken=ACCESS_TOKEN
これでインストールができるようになります。
$ npm install @YOUR_USERNAME/PACKAGE_NAME
コードから呼び出して実行すと問題なく動作することが確認できます。
import { generateSampleJWTToken } from "@YOUR_USERNAME/PACKAGE_NAME";
generateSampleJWTToken(100);
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2YWx1ZSI6MTAwLCJpYXQiOjE2MjMyNTc3NzB9.foO7kvBIQBnRpdq1nAqDgn1oCVdQi7LAg7cNwXgjt2k