【2020年クリスマスイブ版】npm install で Merry Christmas 🎉✨🎄🎅

本記事は [株式会社ピーアールオー（あったらいいな！を作ります） Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pro-japan1) の24日目、クリスマスイブの投稿です。
昨日(23日目)は @pro_matuzaki さんの「[SpreadSheetのビジター共有がかゆいところに微妙に届かなかった話](https://qiita.com/pro_matuzaki/items/b4dcfd8dcaa408b8e7d0)」でした。

それでは、今回のテーマに入りたいと思います。

# 今年も早くもクリスマス・・・

あっという間に年末、クリスマスですね。。。今年も残り僅かですが、今回はnode.jsユーザーならすぐにでも試せる `クリスマスカード` のご紹介です。

以下の記事は `名刺` を作る記事ですが、せっかくなのでこのを名刺を`クリスマスカード`に変えてみたいと思います。

- [Create your own NPM Card!](https://dev.to/cdthomp1/create-your-own-npm-card-ejp)

ターミナルからコマンドを叩くと自己紹介カードが表示される楽しいツールの作り方が紹介されております。
上記の記事を参考に、プログラマーのならではの **手作りのクリスマスカード** をお届けいたしましょう〜🎉

# 1. プロジェクトの作成

さて、まずはプロジェクトを作成いたします。今回は諸事情により `scoped(スコープ付き)` のパッケージを作成します。 

```bash
$ mkdir xmascard
$ cd xmascard
$ npm init --scope=@xxxxx
```
`npm` のスコープとはなんぞや？と思われるかもしれませんが、`@aws` とか `@angular`とかの `@グループ名` の接頭辞っぽいアレです。あれを`scope`というそうです。

- [npm Docs: Creating and publishing scoped public packages](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages)

自分も作ってみるまで気にしたことはなかったのですが、公式サイトにもちゃんと解説がございました。
以下では筆者のアカウント名と合わせるため、スコープ名を`@roomtv`としております。

# 2. 依存パッケージの追加とカードの作成

今回はターミナルを派手に彩るために以下のパッケージを使います。

- [Boxen](https://www.npmjs.com/package/boxen)
- [Chalk](https://www.npmjs.com/package/chalk)
- [Inquirer](https://www.npmjs.com/package/inquirer)
- [Clear](https://www.npmjs.com/package/clear)
- [asciify-image](https://www.npmjs.com/package/asciify-image)

以下のコマンドでパッケージを追加します。

```bash
$ npm i boxen chalk clear inquirer asciify-image
```

これらのパッケージは、それぞれ機能はシンプルなのでここでは詳しい解説は割愛しますが、以下のようなコードで大体、イメージができるかと思います。

```js:index.js
#!/usr/bin/env node

"use strict";

const boxen = require("boxen");
const chalk = require("chalk");
const inquirer = require("inquirer");
const clear = require("clear");
var asciify = require('asciify-image');

clear();

const prompt = inquirer.createPromptModule();

// Questions after the card 
const questions = [
    {
        type: "list",
        name: "action",
        message: "What you want to do?",
        choices: [

            {
                name: "Just quit.",
                value: () => {
                    console.log("Merry X'mas!\n");
                }
            }
        ]
    }
];
asciify('[画像のURL]',{
    fit: `box`,
    width:20, height:20,
}, (_, rendered)=>{

    // Data for the card
    const data = {
        name: chalk.bold.green("From koinori @ PRO"),
...
    };

    // Build the card
    const me = boxen(
        [
            `${chalk.bold("メリークリスマス !")}`,
...
            boxen(rendered, {mergin:1, borderColor: "green"}),
...
            `${data.name}`
        ].join("\n"),
        {
            margin: 1,
            float: 'center',
            padding: 1,
            borderStyle: {
                topLeft: '🎄',
...
            },
            borderColor: "cyan"
        }
    );

    // Print the card
    console.log(me);

    // Optional tip to help users use the links
    const tip = [
        `Tip: Try ${chalk.cyanBright.bold(
            "cmd/ctrl + click"
        )} on the links above`,
        '',
    ].join("\n");

    // Show the tip 
    console.log(tip);
    
    // Ask the Inquirer questions. 
    prompt(questions).then(answer => answer.action());
});
```

文言の部分をクリスマスカードにしただけで、プログラムはほとんどオリジナルです。すいません。。。

以下のコマンドでクリスマスカードが表示されればとりあえずOKです。

```bash
$ node index.js
```

ここは正直、センスですね。。。文言とスペースの調整でほとんどの時間を費やしました。

# 3. コマンドとしての動作確認

続いて、`merryxmas` コマンドとして動作するように、`package.json` に以下の定義を追加します。

```json:package.json
...
"bin": {
    "merryxmas": "index.js"
  },
...
```

続いて以下のコマンドでローカルのnpm環境に対して`merryxmas`コマンドのインストールをおこないます。

```bash
$ npm link
```

`npm link`が無事に完了したところで、`npx`で実行してみましょう。

```bash
$ npx merryxmas
```

クリスマスカードが表示されればOKです！

# 4. npmjs 本家サイトにデプロイ

さて知り合いにクリスマスカードを届けるために、npmjs サイトにデプロイしましょう。
アカウントがなければ、**これをきっかけにアカウントを作ってみましょう！**

以下からどうぞ!!

- https://www.npmjs.com/signup

アカウントが作成できたら `npm adduser` もしくは `npm login`コマンドで、ローカルにてログインいたします。

```bash
$ npm adduser
Username: xxxxx
Password: 
Email: (this IS public) xxxxx@xxxxx.co.jp
Logged in as xxxxx on https://registry.npmjs.org/.
```

ログイン完了後、`npm publish` コマンドにて、npm リポジトリにデプロイいたします。

```bash
$ npm publish --access public
npm notice 
npm notice 📦  @roomtv/xmascard@1.0.0
npm notice === Tarball Contents === 
npm notice 842B  .devcontainer/Dockerfile       
npm notice 3.4kB index.js                       
npm notice 1.0kB .devcontainer/devcontainer.json
npm notice 868B  package.json                   
npm notice 0     README.md                      
npm notice === Tarball Details === 
npm notice name:          @roomtv/xmascard                        
npm notice version:       1.0.0                                   
npm notice package size:  2.9 kB                                  
npm notice unpacked size: 6.2 kB                                  
npm notice shasum:        8a95b0822213c297d9cae0c1022d0d02c759389e
npm notice integrity:     sha512-wYvpyQglAYgjM[...]eMeeOH6DruMBg==
npm notice total files:   5                                       
npm notice 
+ @roomtv/xmascard@1.0.0
```

はい、本家リポジトリにクリスマスカードのデプロイ完了です！
ちなみに公開されたサイトは以下です。

- [@roomtv/xmascard: https://www.npmjs.com/package/@roomtv/xmascard](https://www.npmjs.com/package/@roomtv/xmascard)

クリスマスカードの見た目の調整で力尽きてしまい、README の記述にはパワーが残っていなかったので、ドキュメントの方はぼちぼち追加してまいりたいと思います。。。すいません。。。

# 5. リポジトリから取得&ローカルで実行

開発した環境とは別ディレクトリとするか、`nvm`やVSCodeのRemote Containerなどで新規のnode.js環境に切り替え、`npm install`をしてみましょう。

```bash
$ npm i -g @roomtv/xmascard
...
...
+ @roomtv/xmascard@1.0.0
added 336 packages from 239 contributors in 62.997s
```
いつもは絶対反対の`-g`ですが、今回だけは`-g`を使ってしまいます。~~大人なんてそんなもんです。~~

それでは早速、`merryxmas` コマンドを叩いてみましょう。

```bash
$ npx merryxmas
```

クリスマスカードが無事に表示されたでしょうか？！枠の中の文言の位置やセンタリング？など、スペースだけで調整してます。**めっちゃ手作りですね！**

はい、お疲れ様でした！

# 6. まとめと感想など

日頃、`npm install` ばかりですが、まさかこんなお手軽に自分の NPMパッケージを作成して公開できるとは思いませんでした。
主に気持ちの問題なのですが、きっかけの記事であったような`名刺`を表示するだけのコマンドでパッケージを公開しちゃってもいいのかよ・・・と思いましたが、**アドベントカレンダーのネタにはなるな**と考え、チャレンジしてみました。
手順は簡単ですが、いつも使っている `npm` コマンドでもなかなかお世話にならない `adduser`や`link`、`publish`などが試せたので非常に面白かったです。

相変わらずのコンソールネタとなってしまいましたが、**新人研修には是非、おすすめです。**
クリスマスカードや名刺に限らず、オリジナルのデザインとメッセージを表示するだけのジョークアプリでも、**公開することに意味がある**のだよ。(た、たぶん。。。)


それでは、*メリークリスマス !!* 🎉✨🎄🍻