Qiita記事管理CLI(qiita-cli)をTypeScriptでつくってみた


# qiita-cli 作ってみた

zenn-cli は知っていて活用しているが(と言っても今のところ zenn には一件しか投稿してないが), qiita-cli なるものはないのかと以前調査した.
結果, それらしきものがあったものの, 私の環境でまともに動くものはなかった.

最近触っていなかった TypeScript で開発したい気持ちがなぜかふつふつ湧いてきたので, zenn-cli オマージュの qiita-cli を作成してみた.
とりあえず使えるかなくらいにしてリリースしたので, 興味ある方に使って頂いてフィードバック頂きたい, という思いからの紹介記事が本記事です.

## インストール

node 環境が必要なので, 別途用意してください.14 系推奨です.
以下コマンドでまず qiit-cli をグローバルにインストールします.

```bash
npm install -g qiita-cli
```

## qiita-cli でできること

zenn-cli と同様に, ローカル環境で記事を新規作成/修正し、cli 経由で投稿することができます.
VScode 等の補完や整形が markdown に適用できるエディタを用いての効率的な執筆や, 記事修正がお手軽にできます.

zenn-cli では Github レポジトリへの push をフックとして記事とレポジトリを同期してます.
一方, qiita-cli では手動のコマンド実行で同期を行います. なので、git レポジトリに上げて管理も可能ですし、アップはぜずにローカルだけで管理も可能です.
(GithubActions 等で push をフックに qiita-cli の同期コマンドを実行すれば, zenn-cli と同様のこともできるはずですが、同期コマンドは現状未実装です.)

## 環境設定

Qiita アカウントの用意が必要です.
また, 前述の npm 経由でインストール以外に, 作業ディレクトリの用意が必要です.
記事を管理するディレクトリを事前に作成した上で qiita cli を利用してください.

```bash
mkdir -p ~/qiita-contents
cd ~/qiita-contents
```

記事は以下のような構成で管理されます.

```
.(qiita-contents)
└─ articles/
   ├── article1/
       ├── article1_id.md
   └── article2/
       ├── article1_id.md
```

## 機能紹介

### とりあえずの help コマンド

とりあえず help コマンドを実行して, 正常にインストールされているか確認します.
記載通り未実装のものはあるものの, とりあえず使える形にしたのでリリースしました.

```bash
$ qiita --help

🐥 qiita cli

Command:
  qiita init                    qiitaとの接続設定. 初回のみ実行
  qiita pull:article            既に投稿している記事をローカルにpull(強制上書き)
  qiita new:article             新しい記事を追加
  qiita post:article            ローカルで新規作成した記事を選択的に投稿
  qiita patch:article           ローカルで修正した記事を選択的に投稿
  qiita delete:article(未実装)   選択した記事の削除
  qiita sync(未実装)             ローカルで作成/修正した記事の一括反映および投稿済み記事の取得
  qiita --version, -v           qiita-cliのバージョンを表示
  qiita --help, -h              ヘルプ

Remark:
  コマンドは全て作業ディレクトリのルートでの実行を想定したものになっています.
  記事の取得・投稿は作業ディレクトリはコマンド実行場所の作業ディレクトリ内のarticlesディレクトリを基準に実行されます.
  (articlesディレクトリはqiita init や qiit pull コマンドで生成されます)
```

### 初期設定

qiita-cli の機能を利用するために, 以下コマンドで初期設定をおこないます.
下記コマンドを実行し, メッセージに従い Qiita の管理者画面 web にてアクセストークンを生成し, qiita cli に入力してください.
管理者画面でトークン生成時に, 全権限の認可を与えてください.

```bash
qiita init
```

上記コマンドで以下メッセージが表示され, デフォルトブラウザで Qiita 管理者画面が自動で開きます.
生成したアクセストークンを入力してください.

```bash
🐥 qiita cli

? 設定ファイルが既に存在します。設定が上書きされますが、よろしいですか？:  Yes
Qiiaの管理者画面にてアクセストークンを発行し、トークンをcliに入力してください

? Qiita AccessToken:
```

ここで設定したトークン情報は`~/.qiita/qiita.json`に保存されます.

### 記事のローカル保存

以下コマンドで作業ディレクトリ直下に articles ディレクトリが作成され, そこに既存投稿記事が`.md`として保存されます.

```bash
qiita pull:article
```

私の Qiita アカウントで実行すると以下のようなメッセージが出力され, articles ディレクトリ以下に`.md`ファイルが出力されます.

```bash
$ qiita pull:article
🐥 qiita cli

fetching article ...
------------------------------------------
7a0f3f3a597e4dad85e7: uuu
8a0c555399cd8c96f792: wsl2でdockerが占有する容量の開放
50d7b93fc255fabf3bb2: VScodeに求められたのでAWS SAM CLIの導入
7d49c818f829ae8a21d0: ゼロから始めるAtcoder
631c60acc5d2a3306658: wslでgh auth loginできない時の対処
54bf4bff46bd2109888e: scoopを使い始めたらなぜだかディスク逼迫していた時の対処
f9f20cf346e60599235e: ブランチ名を省略したgit pull が通らない時の対処
d21c50c9a07864af87e1: MacでR環境整備(Renv)
adbad0a85e23515b4f46: zshでタブ補完したときの(eval):1: command not found:を解消
4089576dad85530dfbbf: 【windows】git2.26以下の脆弱性回避
532bbd7e9d3d57bf5f03: R(R studio)からAWSを利用
974ee6adcb9ebf014b65: psql(Redshift)チート集
ebf4dc65ea9805cc2445: Windowsでのpsql環境設定(Redshift接続)
6ab292ea7210a5a79f4b: グローバルip取得コマンド
627a336d167945b14903: 【AWS IAM】SecurityGroupでのポリシー設定の落とし穴
9e777e8aed48b77d37ac: 約三か月でAWS SAA 合格 をするロードマップ(2019/09)
c19970d6a9a50e39ca60: wsl + pyenv + pipenv + JupyterNotebook でWindowsにpython環境構築
------------------------------------------

✨ Article fetching completed. ✨
```

### 記事の新規作成

以下コマンドで作業ディレクトリ直下の articles ディレクトリが作成され, そこに既存投稿記事が`.md`ファイルとして保存されます.

```bash
qiita new:article
```

上記コマンドを実行すると, プロンプトで記事タイトル入力を促されるので以下の例のように入力します.

```bash
$ qiita new:article

🐥 qiita cli

Qiita 記事新規作成

? 記事タイトル:  qiita-cliで新規記事作成
```

すると, `not_upload.md`ファイルが以下のパスに生成されます.
生成パスは cli から表示されます.

```bash
? 記事タイトル:  qiita-cliで新規記事作成

✨ Template article creation is complete. ✨

Your template article has been saved to the following path:

        articles/qiita-cliで新規記事作成/not_uploaded.md
```

自動生成された`.md`ファイルの中身は以下です.
以下内容がファイルないに自動記載既にされていますが, 記載通り`ここから本文を書く`以降を削除して記事を作成してください.
また, ファイル上部のハイフンで囲まれた部分(フロント・マター)内記載の tag 設定を適宜更新してください.

```markdown
---
id:
title: qiita-cliで新規記事作成
tags: [{ "name": "qiita-cli", "versions": [] }]
---

ここから本文を書く

# 🐥 qiita cli による自動生成です.

上記ハイフンで囲まれた部分(フロント・マター)より下のこちらの部分を編集して記事本文を作成してください.
フロント・マター以下の本文含めた自動生成された部分は削除して構いません.
自動生成に倣い,フロント・マター以下に 1 行改行を加え、markdown 形式で記載してください

## 記事へのタグ付け

フロント・マターの tags に以下のように配列形式で tag を記載することが可能です.
投稿するには、一つ以上の tag が設定されている必要があります.
フロント・マターへの tag 追記例

tags: [{"name":"C++","versions":[]},{"name":"AtCoder","versions":[]}]
```

### 新規作成記事の投稿

記事を書いたら次に投稿です. qiita-cli は作業ディレクトリ直下の articles ディレクトリ内の`not_uploaded.md`ファイルを新規作成記事投稿候補として認識します.(イけてないですが, 他に新規投稿記事として認識する方法で実装できそうなものが思いつきませんでした...)
以下コマンドで新規作成記事を投稿します.

```bash
qiita post:article
```

cli で候補選択を促されるので, 投稿したい記事を選択して投稿してください.
例えば, 2 つ投稿候補記事があると以下のようなメッセージが表示されます.

```bash
$ qiita post:article

🐥 qiita cli

Qiita 記事投稿


aricleディレクトリのある作業ディレクトリでコマンド実行している前提での処理です.
articleディレクトリ内の not_uploaded.md ファイルが投稿候補記事として認識されます


? アップロードする記事を選択してください:
❯ Qiita記事管理CLI(qiita-cli)をTypeScriptでつくってみた
  qiita-cliで新規記事作成
```

投稿すると, ファイル名は記事 id に自動で変更され, フロント・マターに記事投稿日時などが追記されます.

### 既存記事の修正と投稿

既存記事を修正して投稿する場合は, 修正したい記事のファイル名を`will_be_patched.md`に変更してください.(イけてないですが, ry)

```bash
qiita patch:article
```

### つくってみて

TypeScript 完全に理解した(方言)
型のせいで Javascript と比較して非常に実装面倒だなあと思った.
色々な Typescript 関連のドキュメントや技術記漁りながら作ってみたけど, Typescript むつかしい.
ESlint がうるさくて疲れた.
現状実力不足なせいもありますが, 結果 Typescript 好きになれてないので, これからも向き合って行くかあ、という感じです.
コンソールのメッセージ, 色々迷ったところもあり日本語と英語が混ざったようわからん感じになったなあ

### qiita-cli 使ってみた

この記事は qiita-cli を利用して書きました.
GitHub レポジトリ管理にして, vscode の設定ファイルとかも置いておくと,ローカルでの VScode 編集が捗ります.
<https://github.com/antyuntyuntyun/qiita-contents>

### ソースコード

以下がソースコードです.
とりあえず今の構成で残りの機能を実装しきろうとしていますが, Typescript プロジェクトとして未熟な点なり cli としての足りない機能なりの観点でレビューを求めていますので, 是非強い(優しい)エンジニアの方見ていただけると助かります.
<https://github.com/antyuntyuntyun/qiita-cli>

### 謝辞

開発初期設定(webpack とか tsconfig あたり)で詰まった時に助けてくれた, TkHS 先生ありがとう!
教わったのだいぶ前な気がしますが,うまく時間取れず気づいたら 5 月です！

### 参考

zenn cli
<https://zenn.dev/zenn/articles/zenn-cli-guide>
qiita api v2
<https://qiita.com/api/v2/docs>
cli 作成参考記事
<https://qiita.com/suzuki_sh/items/f3349efbfe1bdfc0c634>
<https://qiita.com/amay077/items/c19ab5304176326d584a>