Node-REDのノードをつくる手順

本記事は、2024年1月5日に開催した下記「Node-REDのノードを作るハンズオン」イベントの資料です。

https://youtu.be/96ZPiRmHxO4

Node-REDのコントリビュータの横井一仁です。
今回は、[公式サイトに掲載されているサンプルノード](https://nodered.jp/docs/creating-nodes/)をもとに、Node-REDのノードを自作する手順について説明します。

現在、Node-REDは月間15万回ダウンロードされており、急速に普及しています。また、[reTerminal DM](https://qiita.com/kazuhitoyokoi/items/ecf60f30a15457d48c2b)などの産業向けRaspberry Piの標準搭載ソフトウェアにもなっています。Node-REDが普及していることの理由の1つとして、「ノードを自由に追加できる」ことによるコミュニティの力が影響していると考えます。現在、[フローライブラリ](http://flows.nodered.org)には、約5000個のノードが登録されており、様々な企業が自社のサービスの利用促進のためにノードを提供しています。
また、Node-REDのユーザ層は、コードが書けないユーザにも大きく拡大するポテンシャルがあります。そのため、コードを書けるエンジニアは、自身が広めたいサービスやプログラムをエンジニアでないユーザにも使ってもらうよう、ノードを開発して提供しましょう。

# ノードの構成するファイル
Node-REDのノードは、JavaScriptファイルとHTMLファイルの2つで構成されています。JavaScriptファイルには、Node.jsのプログラムが書かれており、前のノードから受け取ったメッセージをもとにどの様な処理を行い、次のノードへどの様なメッセージを出力するかを記述します。HTMLファイルは、Node-REDのフローエディタで表示されるプロパティ設定画面やヘルプなどが記述されています。

![what_is_node.png](https://qiita-image-store.s3.amazonaws.com/0/98354/88759e5d-a934-b5cd-d03b-cbdb54db075c.png)
※2016年6月のNode-RED Tech Talkのスライド

その他、フローライブラリに登録する際に必要なパッケージ化で用いるpackage.jsonファイル、テストケースのファイル、サンプルフローのJSONファイルを置くこともできます。

# ノードの開発、公開手順
典型的なノードの開発、公開手順は以下のようになります。この記事では本手順に沿って説明をしてゆきます。

1. GitHub上にリポジトリを作成
2. リポジトリをローカルに取得 (git clone)
3. ノードのプログラムを開発
4. パッケージ化 (npm init)
5. package.jsonを編集
6. テストケースを作成
7. tgzファイルを作成 (npm pack)
8. ローカルのNode-REDにノードをインストール
9. インストールしたノードの動作確認
10. サンプルフローの保存
11. README.mdファイルを編集
12. ノードの検証
13. GitHubへソースコードをアップロード (git push)
14. npmのトークン発行
15. GitHub Actionsの設定
16. リリース
17. Node-REDフローライブラリに登録

本記事では、受け取った文字列をすべて小文字に変換するオリジナルノードを例として作成します。例えば「AbCdEf」という文字列を受け取った場合は「abcdef」という文字列を出力します。

# ノード開発に必要なもの
Windows PCまたはmacOSにて、次のソフトウェアのインストールとアカウント作成を行います。

- Node.js v20.x LTS https://nodejs.org
- Node-RED v3.x (Windowsの場合はnpm install -g node-red、macOSの場合はsudo npm install -g node-redのコマンドを実行してインストール)
- Git https://git-scm.com/downloads
- Visual Studio Code https://code.visualstudio.com/download
- GitHubアカウント https://github.com/signup
- npmアカウント https://www.npmjs.com/signup

# GitHub上にリポジトリを作成
https://github.com/new へアクセスし、GitHubアカウントでログインします。すると以下の様な新規リポジトリ作成のページが表示されます。

![スクリーンショット 2024-01-04 181340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/0d0bfc19-c986-55f8-ebd1-180f1b67b998.png)

| # | 設定項目 | 設定内容 |
|---|---------|----------|
| 1 | Repository name | ノードのモジュール名を指定します。Node-REDのモジュール名は、「node-red-contrib-<任意の名前>」をという命名ルールがあります。ここでは、「node-red-contrib-example-lower-case」という名前にしました。 |
| 2 | Description | リポジトリの説明を入力します。オリジナルノードの説明「A simple node that converts the message payloads into all lower-case」としました。 |
| 3 | リポジトリの公開設定 | 「Public」を選択します(もしフローライブラリに公開しない場合は「Private」でも構いません)。 |
| 4 | Add a README.md file | オリジナルノードのドキュメントを記載するREADME.mdファイルを作成するため「Add a README file」のチェックボックスは有効にします。 |
| 5 | Add .gitignore | Node-REDのオリジナルノードはNode.jsのプログラムであるため「Add .gitignore」は「Node」を選択します。これによってNode.js関連の一時ファイルがGitHub上にアップロードされないようになります。 |
| 6 | Choose a license | プルダウンメニューからライセンスを選択します。ここではNode-REDと同じApache License 2.0を選択しました。 |

最後に緑色の「Create repository」ボタンをクリックします。すると、作成されたリポジトリの画面に遷移します。

![スクリーンショット 2024-01-04 181612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/b7a09db6-a681-fd24-43ff-9e3ae5bbb05e.png)

次のgit cloneコマンドで用いるため、リポジトリのURL「[https://github.com/\<ユーザ名\>/node-red-contrib-example-lower-case.git](https://github.com/<ユーザ名>/node-red-contrib-example-lower-case.git)」をクリップボードへコピーします。緑色の「Code」ボタンをクリックして「Copy url to clipboard」という吹き出しが表示されるURL右横のボタンをクリックしましょう。

# リポジトリをローカルに取得 (git clone)
Windowsのメニューから「ターミナル」を開きます。

![スクリーンショット 2024-01-04 180102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/1403f132-9783-cd11-8e9f-798cd94d45a8.png)

※ Windows 10ユーザの場合は、PowerShellを用いてください。

※ macOSの場合はLaunchpadから「ターミナル」を開きます。

![Screenshot 2024-01-04 at 17.56.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/2ea7bf71-2cb3-a9d6-f4b7-e112fad5036d.png)

ターミナル上で以下のコマンドを実行し、カレントディレクトリをデスクトップにします。

```
cd Desktop
```

![スクリーンショット 2024-01-04 183019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/f28912d1-bdb9-b773-abb8-0d22415bb4d7.png)

次に、クリップボードにコピーしたパスを用いて以下のコマンドを実行し、リポジトリを取得します。

```
git clone https://github.com/<ユーザ名>/node-red-contrib-example-lower-case.git
```

![スクリーンショット 2024-01-04 183352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/90586c20-ea27-6840-7445-491f867f3d49.png)

デスクトップには「node-red-contrib-example-lower-case」という名前のフォルダができています。このフォルダへ移動します。

```
cd node-red-contrib-example-lower-case
```

![スクリーンショット 2024-01-04 183652.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/3ba3627f-a5cc-9cad-d505-d9be70a3ed55.png)

# ノードのプログラムを開発
「node-red-contrib-example-lower-case」のフォルダの中に「lower-case.js」と「lower-case.html」いう2つのファイルを作成します。最初は、Node-REDのサイトに掲載されている[大文字を全て小文字に変換するノードのサンプルコード](https://nodered.jp/docs/creating-nodes/first-node)を貼り付けます。

- Visual Studio CodeでJavaScriptファイルを作成
```
code lower-case.js
```

![スクリーンショット 2024-01-04 183849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/995e4071-8b99-04fe-981c-508d154e281d.png)

- サンプルコードを貼り付けて、ファイル保存

```js:lower-case.js
module.exports = function (RED) {
    function LowerCaseNode(config) {
        RED.nodes.createNode(this, config);
        var node = this;
        node.on('input', function (msg) {
            msg.payload = msg.payload.toLowerCase();
            node.send(msg);
        });
    }
    RED.nodes.registerType('lower-case', LowerCaseNode);
}
```

![スクリーンショット 2024-01-04 184204.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/29f0e99b-88e0-0135-54ea-30813203badb.png)

- Visual Studio CodeでHTMLファイルを作成

```
code lower-case.html
```

![スクリーンショット 2024-01-04 184034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/5faa39e9-ad1a-bdc8-e655-385a1c206a85.png)

- サンプルコードを貼り付けて、ファイル保存

```html:lower-case.html
<script type="text/javascript">
    RED.nodes.registerType('lower-case', {
        category: 'function',
        color: '#a6bbcf',
        defaults: {
            name: { value: '' }
        },
        inputs: 1,
        outputs: 1,
        icon: 'file.svg',
        label: function () {
            return this.name || 'lower-case';
        }
    });
</script>

<script type="text/html" data-template-name="lower-case">
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
</script>

<script type="text/html" data-help-name="lower-case">
    <p>A simple node that converts the message payloads into all lower-case characters</p>
</script>
```

![スクリーンショット 2024-01-04 184136.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/6e1c6e52-e2ff-e316-9fc7-5551d16e56c9.png)

- lsコマンドを実行し、JavaScriptファイルとHTMLファイルが作成されていることを確認

```
ls
```

![スクリーンショット 2024-01-04 184252.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/4d6ebd1f-2959-623f-252c-f9ed6140bd81.png)

これでオリジナルノードを実現する必要最小限のJavaScriptファイルとHTMLファイルを作成できました。

# ノードをパッケージ化 (npm init)
オリジナルノードのパッケージを作るnpm initコマンドを実行します。

```
npm init
```

![スクリーンショット 2024-01-04 185103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/f6564ecd-b14b-6849-74f0-e29615e55f81.png)

npm initコマンドでの設定項目は以下の通りです。

| # | 設定項目 | 設定内容 |
|---|---------|----------|
| 1 | name | ノードのモジュール名として「@\<npmユーザ名\>/node-red-contrib-example-lower-case」を入力します。 |
| 2 | version | ノードのバージョンを指定します。最初は「0.0.1」を指定します(安定するまでは0.2.x、0.3.xとベータ番号を使い、正式版から1.0.0、1.1.xという番号付けをします。その後、仕様が大幅に変わる時に2.0.0、3.0.0とメジャーバージョンアップします)。 |
| 3 | description | ノードの説明を記述します。ここで記述した説明は、[フローライブラリ](http://flows.nodered.org)やNode-REDのノードのインストール画面で表示されます。GitHubリポジトリの説明で入力した「A simple node that converts the message payloads into all lower-case」で良いでしょう。 |
| 4 | entry point | ノードのプログラムのファイル名を指定します。デフォルトの「lower-case.js」のままでOKです。 |
| 5 | test command | ノードのテストケースを実行するmochaコマンドを「mocha test/**/*_spec.js」の様に入力します。npm testコマンドを実行するとテストが行われるようになります。 |
| 6 | git repository | GitHubのリポジトリのURLを指定します。GitHubリポジトリのページからコピーした「[https://github.com/\<GitHubユーザ名\>/node-red-contrib-example-lower-case.git](https://github.com/\<GitHubユーザ名\>/node-red-contrib-example-lower-case.git)」を入力しましょう。このURLは、最終的にNode-REDフローライブラリのオリジナルノードのページに掲載される「View on GitHub」のリンクで使われます。 |
| 7 | keywords | フローライブラリやNode-REDのインストール画面の検索で用いるキーワードを半角の空白区切りで指定します。ここでは「node-red lower-case」としました。フローライブラリに登録する場合はキーワード「node-red」を忘れずに入力してください。 |
| 8 | author | ノードの開発者名を指定します。npmアカウントと同じユーザ名を入力します。 |
| 9 | license | ノードのライセンスを指定します。GitHubリポジトリに設定したものと同じライセンスを入力します。ここではNode-REDと同じライセンスである「Apache-2.0」を指定しました。 |

以上の設定を入力し、最後の確認で「yes」を入力します。npm initコマンドにより、package.jsonファイルが生成されます。

```
ls
```

![スクリーンショット 2024-01-04 185407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/87b203f6-8cc0-5880-20d0-1e916b1b7921.png)

# package.jsonを編集
package.jsonには、手動でNode-RED固有の設定を追加する必要があります。package.jsonファイルをVisual Studio Codeで開きましょう。

```
code package.json
```

![スクリーンショット 2024-01-04 185504.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/95c5481e-62db-df64-c695-fb68cf746007.png)

以下の様に"name"や"version"と並列して"egines"と"node-red"のセクションを追加します。ここでは、動作環境としてNode.js v14.0.0以上、Node-RED v1.3.7以上をサポートするという定義を記載しました。末尾のカンマを忘れずに追加してください。

```json:package.json
{
  "name": "<@npmユーザ名>/node-red-contrib-example-lower-case",
  "version": "0.0.1",
  (省略)
  "engines": {
    "node": ">=14.0.0"
  },
  "node-red": {
    "version": ">=1.3.7",
    "nodes": {
      "lower-case": "lower-case.js"
    }
  },
  (省略)
}
```

Visual Studio CodeでNode-RED固有の設定を追加した様子は以下の通りです。選択部分を手動で追加しました。

![スクリーンショット 2024-01-04 185706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/61ffa30e-b721-6281-28be-7229e4ff7a33.png)

# テストケースを作成
Node-REDのオリジナルノードの品質を担保するには、テストケースが必須です。testフォルダの下に「<JavaScriptファイルの名前>_spec.js」というファイル名でテストケースを記載します。

```
code test/lower-case_spec.js
```

![スクリーンショット 2024-01-04 185800.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/14c486af-8749-6ace-fb14-2b2cc608ddf0.png)

- 貼り付けるテストケースのコード
```js:node.js
var helper = require("node-red-node-test-helper");
var lowerNode = require("../lower-case.js");

describe('lower-case Node', function () {

    afterEach(function () {
        helper.unload();
    });

    it('should be loaded', function (done) {
        var flow = [{ id: "n1", type: "lower-case", name: "test name" }];
        helper.load(lowerNode, flow, function () {
            var n1 = helper.getNode("n1");
            n1.should.have.property('name', 'test name');
            done();
        });
    });

    it('should make payload lower case', function (done) {
        var flow = [{ id: "n1", type: "lower-case", name: "test name", wires: [["n2"]] },
        { id: "n2", type: "helper" }];
        helper.load(lowerNode, flow, function () {
            var n2 = helper.getNode("n2");
            var n1 = helper.getNode("n1");
            n2.on("input", function (msg) {
                msg.should.have.property('payload', 'uppercase');
                done();
            });
            n1.receive({ payload: "UpperCase" });
        });
    });
});
```

![スクリーンショット 2024-01-04 185945.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/b2e96bab-ce47-d929-0315-7c2211b7ebb5.png)

本ファイルには、2つのテストケースが含まれています。1つ目は「should be loaded」で、オリジナルノードが正しく読み込まれるか確認するテストです。2つ目は「should make payload lower case」で、文字列「UpperCase」をオリジナルノードの入力とした際に、出力が文字列「uppercase」となっているかをテストします。

本テストケースを実行する前に、mocha、node-red、node-red-node-test-helperのnpmモジュールをdevDependenciesとして追加します。

```
npm install mocha node-red node-red-node-test-helper --save-dev
```

![スクリーンショット 2024-01-04 190203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/ff0bd363-e803-bb02-f182-ceccc8c48de4.png)

最後にテストケースを実行するには、以下のコマンドを実行します。

```
npm test
```

2つのテストケースが実行され、緑色のチェックがつけばテスト成功です。

![スクリーンショット 2024-01-04 190247.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/24a8a8e9-25b5-ea4f-512e-91b3339aa8fb.png)

# tgzファイルを作成 (npm pack)
次に以下のコマンドを実行し、オリジナルノードのファイルを固めたtgzファイルを作成します。

```
npm pack --pack-destination ..
```

![スクリーンショット 2024-01-04 190335.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/6778e94e-b44b-3e33-54af-204139bc2b66.png)

一つ上の階層に対して、lsコマンドを実行するとtgzファイルが追加されていることが分かります。

```
ls ..
```

![スクリーンショット 2024-01-04 190415.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/8e1757d9-a961-a6d2-1b80-45f45b5479d1.png)

# ローカルのNode-REDにノードをインストール
次にローカルのNode-RED上に、tgzファイルをアップロードして作成したオリジナルノードを追加します。タブ横の「+」ボタンをクリックして別のターミナルを開き「node-red」コマンドを入力し、Node-REDの起動しましょう。

```
node-red
```

![スクリーンショット 2024-01-04 192305.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/872a0f5d-d4ea-4064-de89-0a7ab82b74ff.png)

※ もし「node-red : このシステムではスクリプトの実行が無効になっているため、ファイルC:\Users\<ユーザ名>\AppData\Roaming\npm\node-red.ps1 を読み込むことができません。」というエラーが出てNode-REDが起動しない場合は「Set-ExecutionPolicy RemoteSigned」というコマンドを入力してポリシを変更してください。

EdgeまたはGoogle Chromeのブラウザから http://localhost:1880 にアクセスし、Node-REDのフローエディタを表示します。ここからtgzファイルをアップロードしてオリジナルノードをインストールします。そのためには、まず右上メニュー内の「パレットの管理」を選択して「ユーザ設定」の画面を表示します。

![スクリーンショット 2024-01-04 191150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/921c7c29-b309-d1cc-689a-120a3edc3b6a.png)

「ユーザ設定」の画面では「ノードを追加」タブを選択し、「モジュールのtgzファイルをアップロード」という吹き出しが表示される上矢印ボタンをクリックします。

![スクリーンショット 2024-01-04 191224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/b9121f6c-5c44-4d94-075b-6f815772c305.png)

すると、ファイル選択を行うダイアログが表示されるため、作成したtgzファイルを選択しましょう。

![スクリーンショット 2024-01-04 191302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/a7e2c15c-5ac6-2281-3449-1d8b25d899bc.png)

準備が整ったため「アップロード」ボタンをクリックします。

![スクリーンショット 2024-01-04 191344.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/2cf934f3-f11d-a2c1-4e12-f54d47b03582.png)

上手くインストールできると「ノードをパレットへ追加しました: ・lower-case」という通知ダイアログが表示されます。

![スクリーンショット 2024-01-04 191402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/281f9aba-ab35-4b6f-194a-2964a677953a.png)

ユーザ設定を閉じると、左側のパレットの機能グループの中に「lower - case」という青色のノードが登場していれば、オリジナルノードのインストール成功です。

![スクリーンショット 2024-01-04 191500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/0525eca1-839e-1acd-e3b8-9927b47b6d54.png)

# インストールしたノードの動作確認
次にオリジナルノードの動作確認を行ってみます。以下の様にinjectノード、オリジナルノード、debugノードをつないだフローを作成します。

![スクリーンショット 2024-01-04 191618.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/bfb527f9-1447-3e55-0490-4f12e8970771.png)

injectノードは、デフォルトのタイムスタンプから「AbCdEf」という文字列に変更します。タイムスタンプと書かれたノードをダブルクリックして、プロパティ設定を開きます。msg.payloadは「日時」が選択されているため、「文字列」に変更します。

![スクリーンショット 2024-01-04 191648.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/90c9f703-7cef-84f1-72fb-794ec030825b.png)

その後に表示される入力欄に「AbCdEf」と入力して、完了ボタンをクリックします。

![スクリーンショット 2024-01-04 191715.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/f16676b5-cf99-a1f6-d389-f8bdd5e87895.png)

デプロイボタンを押してフローを反映させた後、右側の虫アイコンをクリックしてデバックタブを開きましょう。

![スクリーンショット 2024-01-04 191758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/85b6fe3d-59bd-35aa-eb15-8f4d2a225d32.png)

injectノードの左側のボタンをクリックすると、全て小文字に変換された「abcdef」という文字列がデバックタブに表示されます。

![スクリーンショット 2024-01-04 192812.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/369f87db-8b41-3267-e265-d4d5ac3f49d0.png)

開発したノードが他の環境でも正しく動作するか確認するため、異なるOSのNode-RED、Raspberry Pi版Node-RED、クラウド環境のNode-RED ([enebular](https://www.enebular.com/ja/)など)にノードをインストールしてテストしてみると良いでしょう。

# サンプルフローの保存
ユーザにオリジナルノードの使い方を理解してもらうには、サンプルフローを作成しておくと良いです。現在フローライブラリに登録するオリジナルノードは、サンプルフローがないと警告が出るため、作成しておく必要があります。

オリジナルノードの編集操作を行ったターミナルに戻り、以下の様に「examples」フォルダの下に「<サンプルフロー名>.json」という名前のJSONファイルを作成します。

```
code examples/lower-case.json
```

![スクリーンショット 2024-01-04 192641.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/3dc6eb12-c4e1-b23c-5224-b0a4a392452d.png)

![スクリーンショット 2024-01-04 223502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/20bb005c-0caa-b985-744b-eb3cf839f2d3.png)

Visual Studio Codeのウィンドウはそのままにしておきます。

次にNode-REDフローエディタ上で、マウスをドラッグしてサンプルとしたいフローを選択します。

![スクリーンショット 2024-01-04 192914.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/b3dfeb48-02aa-36e3-acfd-3de2cf1c51bb.png)

フローを選択した状態で、右上メニューから「書き出し」を選択します。

![スクリーンショット 2024-01-04 191911.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/95f1cbff-af07-114a-af5e-3f0696f1aff2.png)

次にダイアログ上の「書き出し」ボタンをクリックして、クリップボードにフローのJSONデータをコピーします。

![スクリーンショット 2024-01-04 191928.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/57cdbddf-05c5-47cc-4152-6d0c75bc8c39.png)

最後にNode-REDフローエディタ上でクリップボードに書き出したJSONデータを、Visual Studio Codeの「examples\/lower-case.json」ファイルに貼り付けて保存します。

![スクリーンショット 2024-01-04 223317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/cb5c65c6-060f-fb63-d35c-f6b099ce6143.png)

# ノードをアンインストール
オリジナルノードの動作確認をした後は、一旦オリジナルノードを削除します。まずオリジナルノードを含むフローを選択して、右クリックして「選択したノードや接続を削除」を選択して全て削除します。

![スクリーンショット 2024-01-04 193404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/d539cc17-08cb-b179-e843-6011c064687b.png)

デプロイボタンを押してフローを反映させた後、右上メニューから「パレットの管理」を選択します。

![スクリーンショット 2024-01-01 220612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/20f7eb49-d664-7089-4bcf-f1bf01ac5d69.png)

「現在のノード」のタブの中に、インストールしたオリジナルノードが存在するため、「削除」ボタンをクリックして削除します(「使用中」と表示されている場合は、どこかのフローでオリジナルノードが使われているため、削除されているか、デプロイしてフローが反映されているかを確認します)。

![スクリーンショット 2024-01-04 193507.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/ab4ba701-8a4b-2b45-676a-d6b4844ff9d3.png)

本当に削除して良いかの確認ダイアログが表示されるため「削除」ボタンをクリックします。

![スクリーンショット 2024-01-04 193526.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/06df8977-6615-6f6d-12c4-81829784c8e5.png)

上手くオリジナルノードが削除できたら「ノードをパレットから削除しました: ・lower-case」という通知が表示されます。

![スクリーンショット 2024-01-04 193547.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/e72ace8b-6408-d3f9-debb-e33e6ab73d39.png)

このノードの削除は、コードを更新した新しいtgzファイルをインストールする際、フローライブラリからインストールする際に必要となります。

以降はノードをフローライブラリに登録する前に行う手順になります。

# README.mdファイルを編集
ノードをフローライブラリに公開するには、ノードの説明を記載したREADME.mdファイルを作成する必要があります。

```
code README.md
```

![スクリーンショット 2024-01-04 193748.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/35022bb0-04b9-8bd3-8e90-5fe3de1718ee.png)

言語は日本語でも大丈夫ですが、英語の方が多くのユーザに親切です。例えば以下の内容を記載します。

- 概要説明
- 使用方法
- スクリーンショット
- 本ノードを用いたサンプルフロー
- 前提環境
- 更新履歴

![スクリーンショット 2024-01-04 193732.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/41f2548e-57d5-e8d3-8d0b-64bdb676ba0a.png)

# ノードの検証
ノードを公開する前に、オリジナルノードの検証してくれる[「Node-RED Node Developer Tools」](https://nodered.jp/blog/2022/01/31/introducing-scorecard#node-developers)というNode-REDプロジェクト公式ツールで必要な設定が漏れていないか確認します。本ツールは以下のコマンドでインストールできます(macOSの場合は「sudo npm install -g node-red-dev」)。

```
npm install -g node-red-dev
```

![スクリーンショット 2024-01-04 194048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/3f3ca738-f0f6-695b-e8e9-f66fa7a894ff.png)

インストールした後は、オリジナルノードのファイルが格納されているフォルダ内で以下のコマンドを実行することで、検証処理が走ります。

```
node-red-dev validate
```

![スクリーンショット 2024-01-04 194304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/74e3d425-bfbc-274d-27c5-5f9b5fc62577.png)

正常な項目はチェックマークが付きます。「lower-case」というノード名は他のノード開発者も試してフローライブラリに公開しているため「Warning: Duplicate nodename lower-case found in package」という警告が出ます。本手順では無視して良いですが、公開後にノード名の衝突を避けるため、自身で別のノードを開発した際に、この警告が出た場合はノード名を変更する必要があります。

# GitHubへソースコードをアップロード (git push)
examplesとtestの2つのフォルダ、LICENSE、README.md、lower-case.html、lower-case.js、package-lock.json、package.jsonの6つのファイル、があることを確認します。

```
ls
```

![スクリーンショット 2024-01-04 194405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/c68a7063-4896-d3fa-0969-2059d0468106.png)

次にGitHub上のリポジトリへソースコードを置きます。まずgit addコマンドを用いて、全てのファイルをコミット対象として追加します。

```
git add -A
```

![スクリーンショット 2024-01-04 194458.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/e0dc1e27-d172-0610-13ab-c261495fb163.png)

変更履歴として「The first commit」というコミットメッセージをつけて、git commitコマンドを実行します。

```
git commit -m "The first commit"
```

![スクリーンショット 2024-01-04 194702.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/a73084ad-a6c9-97ce-179e-402b76283458.png)

※ もしgit commitを実行した際に、メールアドレスとユーザ名を求められた場合は、以下のコマンドを実行してください。

```
git config --global user.email "<メールアドレス>"
git config --global user.name "<ユーザ名>"
```

ソースコードをアップロードするには、以下のgit pushコマンドを実行します。

```
git push
```

![スクリーンショット 2024-01-04 195706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/bb10b3b5-7b7e-44ac-818d-1346c829afdf.png)

※ git pushでGitHubへのログインを求められた場合は、GitHubアカウントのユーザ名とパスワードを入力してください。

正しく操作が行われると、GitHub上のリポジトリにファイルが登場します。

![スクリーンショット 2024-01-04 195758.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/d38b7fdb-f1a7-9898-6022-4608f2b0a7d3.png)

# npmのトークン発行とGitHubへの登録
最後に、ノードをモジュールとしてnpmへ公開するために、GitHub Actionを用います。

まずnpmに公開するためのトークンを発行するため、ブラウザから https://www.npmjs.com/login にアクセスします。その後、右上のユーザアイコンをクリックしてメニューを開き、「Access Tokens」をクリックします。

![スクリーンショット 2024-01-03 191857.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/2a89b687-e276-ca61-1ba2-064608f3129a.png)

するとアクセストークン一覧のページが表示されます。ここで右上にある「Generate New Token」ボタンをクリックし、その中の「Granular Access Token」を選択します。

![スクリーンショット 2024-01-03 191928.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/bb247511-6e6a-c28d-460e-a633ef34efbb.png)

以下の様なアクセストークンを発行する画面が表示されます。

![スクリーンショット 2024-01-04 153043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/00378c4d-bd26-c9ff-38a0-79944a73df2f.png)

まず「Token name」の欄を入力します。どのオリジナルノード向けのアクセストークンか後から識別できるよう、モジュール名と同じにすると分かりやすいでしょう。ここでは「node-red-contrib-example-lower-case」としました。

![スクリーンショット 2024-01-04 200604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/0b64168b-8264-7b8f-1152-66bb266406df.png)

「Permissions」の設定では、GitHub Actionsがカスタムノードをnpmに公開できるよう「Read and write」を選択し、「Select package」では「Only select packages and scopes」を選択して、「Select packages and scopes」のプルダウンメニューから「@npmユーザ名」のスコープを選択します。最後に一番下にある「Generate token」ボタンをクリックすると、次の様な画面に遷移し、アクセストークンが表示されます。

![access.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/c289430c-2b4a-e51a-af1d-1f75384c4bf4.png)

アクセストークンの右側にあるコピーボタンを押して、クリップボードへコピーしておきます。

次に、カスタムノードを生成したGitHubリポジトリを開き、GitHub Actionsが利用する環境変数にアクセストークンを登録します。登録するには、GitHubリポジトリの上の「Settings」タブを選択し、左側の「Secrets and variables」の中の「Actions」をクリックし、次のようなページを開きます。

![スクリーンショット 2024-01-04 200723.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/4457abc4-d408-6a88-ca8d-1b16507c1144.png)

ここで緑色の「New repositry secret」ボタンをクリックします。すると次のような環境変数名と値を設定できる画面が表示されます。

![スクリーンショット 2024-01-04 200803.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/5dcb497a-9976-6e44-3f10-55f7f3f1d119.png)

この画面では「Name」として「npm_token」、「Secret」としてクリップボードに格納されているアクセストークンを貼り付けます。最後に下にある「Add secret」ボタンを押せば設定完了です。

# GitHub Actionsの設定
次に、リリース操作の時に実行するGitHub Actionsのスクリプトを登録します。ここではGitHubに用意されている、npmへ公開するためのスクリプトを用います。まずGitHubリポジトリの「Actions」タブをクリックし、その中にある「Publish Node.js Packge」の「Configure」ボタンをクリックします。

![スクリーンショット 2024-01-04 200844.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/7c448fb9-9864-9441-08ad-5530c989d0d5.png)

見つからない場合は、「Search workflows」の検索欄で検索すると良いでしょう。

次の画面には、GitHub Actionsのスクリプトが表示されます。ここには、テスト実行やnpm公開のためのコマンドが既に記載されています。npmモジュールに「@<npmユーザ名>」というスコープをつける場合は、npm publishコマンドに「--access=public」オプションを追加する必要があります。以下のスクリーンショットのように、31行目の「- run: npm publish」を「- run: npm publish --access=public」に変更します。

![npmpublish.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/383fc891-1b6e-17f2-bec6-7cab561310d1.png)

次に、右上にある緑色の「Commit Changes...」ボタンをクリックして反映させましょう。この修正によって、GitHub Releasesのページから直接npmにカスタムノードを公開できるようになりました。

# ノードをリリース

さっそく公開するため、GitHubリポジトリのページの右下にある「Create a new release」ボタンをクリックします。

![スクリーンショット 2024-01-04 201323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/edcae090-5c8e-a929-0787-60c1efffbce1.png)

リリースの最初のタグを作成するには、「Choose a tag」をクリックし、「v0.0.1」と入力した後、「+ Create new tag: v0.0.1 on publish」をクリックします。

![スクリーンショット 2024-01-04 201443.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/f0e243ef-d17e-3c66-62c3-c4666f0e1d15.png)

リリースのタイトルには「v0.0.1: The First Release」のようなリリースの内容が分かる文字列を入力します。

![スクリーンショット 2024-01-04 201520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/f7ae6f5c-0493-8e18-c925-1539ec72ddd2.png)

ノードのバージョンアップを行なった際は、Writeのタブの中に更新内容を書いておくと親切でしょう。

最後に、一番下にある「Publish release」ボタンを押すと「v0.0.1: The First Release」のリリースページに飛ばされます。カスタムノードの生成の進行状況を知りたい場合は、再生アイコンのある「Actions」タブからGitHub Actionsのページで処理のログを確認できます。

![スクリーンショット 2024-01-04 201628.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/c78153b1-b96f-6a12-c909-85be8c39af01.png)

しばらく待つと、自分のnpmアカウントの配下に、カスタムノードが公開されます。正しく登録できると [https://www.npmjs.com/package/@\<npmユーザ名\>/node-red-contrib-example-lower-case](https://www.npmjs.com/package/@\<npmユーザ名\>/node-red-contrib-example-lower-case) というURLにて公開されます。

![スクリーンショット 2024-01-04 161651.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/88b8d2f7-f3ca-e2c2-5396-76c24aed152d.png)

# Node-REDフローライブラリに登録
フローライブラリに登録するには、手動でフォームで申請する必要があります。 https://flows.nodered.org/add/node のページにアクセスし「3. Add your node to the Flow Library」の入力欄に、npmモジュール名「@\<npmユーザ名\>/node-red-contrib-example-lower-case」を入力します。

![スクリーンショット 2024-01-04 162120.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/a8a7a20e-ab49-d471-5eac-1981baede3fd.png)

「add node」ボタンをクリックすると、フローライブラリが新規にnpmに登録されたノードをフローライブラリに登録します。

![スクリーンショット 2024-01-04 162509.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/770a96be-9347-692c-1d24-4ab5da54dba9.png)

しばらくするとフローエディタ用のカタログが作成され、他の全てのNode-REDのフローエディタからノードをインストールできるようになります。

![スクリーンショット 2024-01-04 163701.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/0498a5fb-1107-09bb-1af1-c442e4cd2f78.png)

カタログの作成状況は以下のURLから参照できますので、なかなか登録されない場合は確認してみましょう。

https://github.com/node-red/catalogue.nodered.org/actions

## 公開したノードを削除する方法
今回作成したノードはお試し用ですので、フローライブラリから削除しておきましょう。まず、公開したnpmのページを開き、タブの一番右にある「Settings」を選択します。

![スクリーンショット 2024-01-04 161722.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/1e2926f8-d75d-4ce5-758c-9abfdd5ad872.png)

一番下に「Delete package」のボタンがあるため、クリックします。

![スクリーンショット 2024-01-03 195638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/7b750b1b-eb73-41f9-4d0b-50bfb13f3dfb.png)

本当に削除して良いかの確認画面が表示されるため、「@\<npmユーザ名\>/node-red-contrib-example-lower-case」を入力します。これでnpmから削除されました。

![スクリーンショット 2024-01-04 172549.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/46f4b2b7-56d1-fc7a-f8db-6dd192c0ecb3.png)

まだフローライブラリには、カタログが残っているため、こちらも削除する必要があります。ノードの登録手順と同じ様に https://flows.nodered.org/add/node を開き「@\<npmユーザ名\>/node-red-contrib-example-lower-case」を入力します。

![スクリーンショット 2024-01-04 173237.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287766/bb94159f-49df-6482-8f31-711171049cca.png)

「add node」ボタンをクリックすると「TypeError: Cannot read properties of undefined (reading 'latest')」とエラーが出ますが、これで削除できています。念のため、フローライブラリからも消えているか確認しておきましょう。

<!--
# ノードの処理や見た目をカスタマイズする
次にインストールしたノードをカスタマイズしてみましょう。ノードは例えば、以下の様な変更を行うことができます。

## ノード名を変更する
ノードの名前がサンプルプログラムの「lower-case」のままであるため、この名前を他の名前に変更します。その変更を行うには以下の3つの操作を行います。

- pakcage.jsonで使われている「lower-case」を「hello」に変更
- node.jsファイルで使われている「lower-case」を「hello」に変更
- node.jsファイルで使われている「LowerCaseNode」2ヵ所を「HelloNode」に変更
- node.htmlで使われている「lower-case」4ヵ所を「hello-node」に変更

tgzファイルを作成し、Node-REDへインストールすると、正しく名前が変更されていることを確認できます(ここでは「lower-case」から「hello」へ変更されました)。

## ノードの処理を変更する
主にノードの処理を行うコードは、以下の部分です。この「msg.payload = msg.payload.toLowerCase();」の部分を書き換えるのみで、ノードの処理を変更できます。

```js:node.js
        (省略)
        node.on('input', function(msg) {
            msg.payload = msg.payload.toLowerCase();
            node.send(msg);
        }
        (省略)
```

このソースコードでは、ノードがメッセージがを受け取ると、「function(msg)」関数が呼び出されます。その時、メッセージのデータは変数msgに入ります。次にノード特有の処理を行い、変数msg内のデータを加工した後、「node.send(msg);」で後続のノードにメッセージを引き継ぎます。ほぼfunctionノードの末尾に書く「return msg;」が「node.send(msg);」に変わるだけのイメージです。

```js:node.js
        (省略)
        node.on('input', function(msg) {
            msg.payload = 'hello';
            node.send(msg);
        }
        (省略)
```

tgzファイルを作成し、ノードをインストールして動作を確認します。デバッグタブを見ると、処理を変更したノードが正しく動作していることを確認できるでしょう。

## ノードのアイコンを変更する
[公式サイトのページ](https://nodered.jp/docs/creating-nodes/appearance)を参考に、ノードのアイコンを変更します。ノードのアイコンを変更するには、node.htmlファイルの"icons"の設定を変更します。Node-REDはデフォルトで以下の様なアイコンを持っています。

![nodered_icons.png](https://qiita-image-store.s3.amazonaws.com/0/98354/bbd02369-ad34-d048-2640-b0989e93e9e6.png)

ここでは、マイクの様に見えなくもない"light.png"を指定します。

![vscode_change_icon.png](https://qiita-image-store.s3.amazonaws.com/0/98354/8f1345be-4c4c-fc99-9ff3-92e38290b1dd.png)

Node-REDにインストールすると、ノードのアイコンがファイルからマイクに変更されていることを確認できました。

![nodered_zundoko_node2.png](https://qiita-image-store.s3.amazonaws.com/0/98354/7b99cf32-d298-8b06-735a-5eefab9b65ef.png)

## ノードの色を変更する
ノードの色の変更はアイコンの変更と同じように、node.htmlファイルの"color"の設定を変更します。ここでは"yellow"を指定しました。

![vscode_change_color.png](https://qiita-image-store.s3.amazonaws.com/0/98354/929b8900-d8ea-f74a-4fd3-a66ff65d8afc.png)

Node-REDを再起動してフローエディタを確認すると、正しく黄色のノードになりました。

![nodered_zundoko_node3.png](https://qiita-image-store.s3.amazonaws.com/0/98354/2eb60498-1f98-c45a-797d-db5d01da1118.png)

## その他の設定項目
その他、htmlファイルを編集して、[プロパティ画面変更](http://nodered.jp/docs/creating-nodes/node-html)や、[ポートラベリングの表示の設定](http://nodered.jp/docs/creating-nodes/appearance)、独自のアイコンの設定なども行えますので試してみてください。

※npmに更新したノードを公開するには、前回よりバージョン番号を上げる必要があります。そのため、2回目以降の際は、事前にpachage.jsonを編集してバージョン番号を上げてください。
-->

# 最後に
Node-REDのノードが簡単に開発、公開できることを理解して頂けたと思います。既存のソフトウェアでもNode.jsのSDKがあれば簡単にノード化することができます。ぜひノードを沢山開発してフローライブラリさらに充実させましょう。

# 参考記事
- [Node-RED オリジナルノードの開発](https://github.com/IBMDeveloperTokyo/node-red-making-node-handson)
  この記事のもととなっているノード開発手順です。

- [Node-REDのサブフローからカスタムノードを作成する](https://qiita.com/kazuhitoyokoi/items/2e34ad85caace099745f)
  サブフローからノンコーディングでオリジナルノードを作成する手順です。