まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:npm

IBM Domino 10 の新機能の1つで、個人的にすごく楽しみにしていた domino-db パッケージを遅ればせながら使ってみました。

このパッケージについて簡単に説明します。IBM Domino サーバーのアプリケーションデータベースにアクセスする方法は何通りかありますが、一般的にはこれまで以下の3通りありました:

(1) 専用クライアント(IBM Notes)を使う
(2) サーバー側で HTTP タスクを有効にした上で、ブラウザなどの HTTP クライアントからアクセスする
(3) IBM Notes が導入されたシステムから C/C++ や Java、ActiveX でプログラミングを行ってアクセスする

(1) はごくごく一般的な、いわゆる「ノーツ」を使ってアクセスする方法で、(2) はブラウザを使ってアクセスします。この2つはプログラミングというよりは、普通に提供されている機能です。(3) はプログラミングによってアプリケーションやマクロを作成してアクセスする方法なのですが、そのための SDK やインターフェースは同システム内にノーツが導入されている前提で提供されているものでした。つまりプログラミングで IBM Domino サーバーにアクセスする場合、IBM Notes クライアントがインストールされていることが前提条件であり、IBM Notes がインストールされていない(またはインストールできない)環境からはプログラミングしてもネイティブコードが存在しないので実行できない、という制約があったのでした。


このたび IBM Domino 10.0 から提供された App Dev Pack という拡張機能によって、この制約がなくなりました。つまり、

(4) App Dev Pack で提供される domino-db パッケージを使ってプログラミングし、Node.js からアクセスする

という4つ目の選択肢が新たに与えられたことになります。なお App Dev Pack は IBM Domino 10.0.1 と同時に提供が開始されました。またこの段階では Linux 版の App Dev Pack のみが提供されています。詳しくは以下でも紹介しますが、2019/01/14 時点では Linux (CentOS7/RHEL7)版の IBM Domino 10.0.1 サーバーと、Linux 上の Node.js 環境で動作します(2019/01/18 修正 domino-db パッケージは Linux 以外でも動くようです。少なくとも Windows からは動きました)

この App Dev Pack を実際に使って試してみました。今回は以下のような2台の Linux システム間で実際に動かしています:
2019011302


【IBM Domino サーバー】
OS: CentOS 7
Domino: 10.0.1

【クライアント】
OS: Ubuntu 16.04
Notes: インストールせず
Node.js: 8.11

今回は同一ネットワーク上に上記2台の Linux マシンを構築していますが、実際にはクライアントから IBM Domino サーバーに(名前とポート番号指定だけで)アクセスすることが可能であれば、インターネット越しでも可能だと思っています。


【環境準備】
CentOS 7 上に IBM Domino 10.0.1 環境を構築します。こちらの手順はすぐ下に記載した部分以外は省略します(私がこちらを参照したわけではないのですが、詳しくはこちらに記載された方法で導入できるようです)。なお Linux 版の Domino 10.x は CentOS/RHEL 7 以上でないとインストールできません。

ただ上記リンク先に書かれていなくて、ちと注意が必要な点があるのでそこだけ追記しておきます。

後述の環境では(Proton の動作ポートが動的な設定のままでも動くように)インフラ部分のセキュリティレベルをかなり緩めに作りました。具体的には SELinux を無効にし、更にファイアウォール(firewalld)も止めている、という点をコメントしておきます。具体的なコマンドとしては IBM Domino インストール後に root でログインして以下を実行しました:
(firewalld を停止)
# systemctl stop firewalld

(firewalld の無効化)
# systemctl disable firewalld

(SELinux の設定ファイルを編集)
# vi /etc/selinux/config

(SELINUX=enforcing とあった行を以下のように更新して、保存)
SELINUX=disabled

(システム再起動)
# shutdown -r now

これでファイアウォールや実行ポート番号を意識せずに以下の記述内容が実行できる環境にしています。



そして上記の環境を使い、CentOS 7側には Proton というサーバータスクを、Ubuntu 側には domino-db パッケージをそれぞれ追加導入しています。つまりシステム的にはこんな感じで Proton と domino-db パッケージを経由して通信しています:
2019011303


以下、それぞれの追加モジュールについて紹介します。

まずクライアント側に domino-db という npm パッケージを用意します。このパッケージが IBM Domino とのアクセスを提供しており、Node.js を使ったプログラム内で IBM Domino のデータベースを読み書きすることができるようになります。なお 2019/01/14 時点で提供されている domino-db パッケージのバージョンは 1.1.0 であり、Linux 版のみが提供されているようでした。

またサーバー側にも Proton というアプリケーション(正確にはサーバータスク・アプリケーション)が必要です。この Proton が前述の domino-db を使ったアプリケーションからのリクエストやレスポンスに対応します。なお 2019/01/14 時点で提供されている Proton のバージョンは 0.2.2 であり、こちらも Linux 版のみが提供されているようでした。

これら2つのモジュールが互いに通信しあって Node.js プログラムからの IBM Domino へのリクエスト制御やデータベースの読み書きに対応します。


実際にこれらをインストールする手順を紹介します。まず Domino 10 のインストールモジュールをダウンロードした IBM サイトなどから IBM Domino AppDev Pack をダウンロードします。2019/01/15 時点でのバージョンは 1.0 で Linux English 版のみ、 DOMINO_APPDEV_PACK_1.0_LNX_EN.tgz というファイル名でした:
2019011502


このアーカイブファイルを展開すると、以下のようなファイル群が表れます。なお、今回以下で紹介するものの中で使っているのは青のファイルのみで、これらのファイルが /tmp 以下に展開されているものとします:
- LICENSE
- NOTICE
- domino-appdev-docs-site.tgz : ドキュメント
- domino-domino-db-1.1.0.tgz : domino-db パッケージ
- domino-iam-service-1.0.15.tgz : IAM 認証用モジュール
- domino-node-iam-client-1.0.22.tgz : IAM 認証用の Node.js クライアントモジュール
- node-demo.nsf : デモ用アプリケーション
- oauth-dsapi-0.2.2.tgz : OAuth 用モジュール
- proton-addin-0.2.2.tgz : Proton 一式

なお、以下で紹介する内容は domino-appdev-docs-site.tgz を展開したドキュメント内にかかれている内容をベースに独自にカスタマイズしたものです。以下ではこのファイルを参照することはありませんが、domino-db パッケージを使ってアプリケーション開発をする場合の API リファレンスなども含まれているので、こちらは必ず手元で参照できるようにしておきましょう:
2019011501


まずはサンプルで使うドミノデータベース node-demo.nsf をデータフォルダに移動させます。いったん IBM Domino サーバーをシャットダウンし、notes ユーザー(Linux 内で IBM Domino を実行するユーザー)でログインします。そして node-demo.nsf をデータフォルダ直下にコピーしておきます:
$ cd /local/notesdata

$ cp /tmp/node-demo.nsf .

$ chown notes.notes node-demo.nsf

なお、このデータベースに特別な設計が含まれているわけではありません。ただし、今回の設定では Anonymous ユーザーでこのデータベースにアクセスして文書を作成することになるので、Anonymous ユーザーで文書を読み書きができるような権限設定が必要です。他のデータベースを使う場合も同様です。

次に IBM Domino 10 サーバーに Proton を導入します。notes ユーザーで以下のコマンドを実行してファイルコピー&セットアップを行います:
Domino バイナリのあるフォルダに移動
$ cd /opt/ibm/domino/notes/latest/linux

libnotes.so が存在していることを確認
$ ls -la libnotes.so

Proton ファイルをこのフォルダ内に展開
$ sudo tar -xzvf /tmp/proton-addin-0.2.2.tgz

setup_proton.sh を使ってセットアップ
$ sudo sh -v ./setup_proton.sh

この時点で Proton を起動することは可能ですが、デフォルト状態のままだと同一システムからのリクエストのみ受け付けます。今回は外部の別マシンから Node.js アプリケーションを実行したいので、外部リクエストを受け付けるための設定を追加する必要があります。

そのため、データフォルダ(/local/notesdata/)以下の notes.ini ファイルをテキストエディタで開き、以下の1行を追加します:
PROTON_LISTEN_ADDRESS=0.0.0.0

PROTON_LISTEN_ADDRESS は Proton へのリクエストを受け付けるホストの IP アドレスです。デフォルトは 127.0.0.1 なので同一システムからのリクエストのみ受け付けます。上記の 0.0.0.0 は全ての外部ホストからのリクエストを受け付ける、という設定です。

ここで1つ注意を。実は Proton の実行ポート番号は動的に決まるのですが notes.ini に以下の一行を追加することで実行ポート番号を指定できることになっています(この例の場合は 6000 番ポート):
PROTON_LISTEN_PORT=6000

が、私が試した限りでは、この1行を追加すると Proton 自身が起動に失敗するようになってしまいました。原因はよくわからないのですが、先に進めるため、今回は上記の設定はしていません。つまり Proton は起動時に空きポートを探して動的なポートで起動されるようにしています。

ここまでの設定ができたら IBM Domino サーバーを起動し、更に起動後のサーバーコンソールに以下を実行して Proton サーバータスクを実行します:
> load proton

するとコマンドに続いて以下のような実行ログが表示されます:
> load proton

PROTON> Build 0.2.2
PROTON> Listening on 0.0.0.0:1217, INSECURE
PROTON> Note: Requested port was 0, Actual listen port is 1217
PROTON> Server initialized
PROTON> Server allows Anonymous access only.
  :

この場合の例では Proton は 1217 番ポートが空いていることを確認し、1217 番ポートでリクエストを待ち受けている状態になりました。この番号は後で使うので覚えておきましょう。

これで IBM Domino サーバー側の設定は終わりです。実際には通信に SSL を使ったり、IAM による認証や権限管理を行ったりする設定もできるようですが今回は試していません。興味ある方はドキュメントを参照して挑戦してみてください。


次にクライアント側である Ubuntu システムのセットアップに移ります。まず Ubuntu に Node.js を導入します。ドキュメントによると Node.js V8.x で動作確認を行っている模様なので、今回も Node.js V8 を導入することにします(V10.x でも動くらしい、とは書かれていました、念の為)。多くの環境で Node.js を導入するとデフォルトで V8.x になると思っていますが、6以下だったり10以上だったりする場合は nvm などを使って Node.js V8.x (と npm)が動く環境を用意してください。

そして AppDev Pack 内に含まれている domino-db パッケージを転送するなどして、Ubuntu 側にコピーしておきます(以下の紹介ではカレントフォルダ内に domino-domino-db-1.1.0.tgz が存在しているものとします)。これでアプリケーション開発の準備は完了です。

チュートリアルをベースに、以下のような Node.js プログラムコード(test01.js)を記述します:
//. test01.js

//. domino-db のロード
const { useServer } = require( '@domino/domino-db' );

//. Domino サーバー(192.168.1.100)と Proton の実行ポート(1217)を指定
const serverConfig = {
  hostName: '192.168.1.100',
  connection: {
    port:1217
  }
};

//. 対象とするデータベース
const databaseConfig = {
  filePath: 'node-demo.nsf'
};

//. データベースに新規に作成する文書の内容
const createOptions = {
  documents: [
    {
      Form: 'Contact',
      Firstname: 'Kei',
      LastName: 'Kimura',
      City: 'Funabashi',
      State: 'Chiba'
    }
  ]
};

//. domino-db を使って Proton に接続
useServer( serverConfig ).then( async server => {
  //. 接続に成功したら処理対象データベースを指定
  const database = await server.useDatabase( databaseConfig );

  //. 設定した内容で文書を作成
  const response = await database.bulkCreateDocuments( createOptions );

  //. 作成した文書の unid を取得
  const unids = response.documents.map( doc => doc['@unid'] );

  //. 作成した文書の unid をコンソールに表示して終了
  console.log( `Documents created: ${unids}` );
});

Node.js に慣れている人であればなんとな~く処理内容は理解できると思います。1点だけコメントすると、上記の青字部分で指定した内容でデータベース内に新規文書を作成します。上記例では documents は配列になっていますが、その要素は1つだけです(つまり1文書だけ作成します)。配列要素の中身は作成する文書の各フィールドとその値を指定します。つまり今回の例では以下のようなフィールドとその値を指定してノーツの文書を新規に作成することになります:
フィールド名フィールド値
FormContact
FirstNameKei
LastNameKimura
CityFunabashi
StateChiba


また documents は配列なので、ここに2つ以上のオブジェクトを指定することも可能です。その場合は2つの文書がバルクインサートで作成され、結果の unid も2つ得ることができます。 ただ今回は1文書のみ作成する前提で上記コードが記述されている点にご注意ください。

このコードを実行してみます。まず上記で作成した test01.js ファイルがあるフォルダで domino-db パッケージを npm install します。domino-db はまだ npmjs に登録されているわけではなく、あくまでインストールモジュールから導入する必要があります。したがって以下のようなコマンドでローカルファイルシステムの同一フォルダにある domino-domino-db-1.1.0.tgz を指定してインストールします:
$ npm install ./domino-domino-db-1.1.0.tgz --save

domino-db のインストールができれば test01.js を実行することができます。また実行結果には作成された文書の UNID が表示されます:
$ node test01

Documents created: 5F29E1B7FD62450649258383005083FE

実際に Domino 10 サーバー上の node-demo.nsf ファイルを開いてみると、All Names ビューから Name が Kei Kimura となった文書が追加されていることが確認できます:
2019011301


この文書を開いてみると、入力した通りの内容で文書が作成されていることが確認できます。本当に Notes/Domino の導入されていないシステムから domino-db パッケージを使ってデータベース内に文書を作成することができました:
2019011503


本当に domino-db パッケージ(と Node.js)だけでリモートの IBM Domino データベースに文書を作成することができちゃいました。今はサーバー側もクライアントも Linux 環境でないとできない(2019/01/18 修正 サーバー側が Linux 環境でないとできない)、という制約がありますが、いずれ他のシステムでもこの機能が提供される(勝手にそう思ってますが・・)と超便利だと思いました。

1点だけ、Proton の実行ポート番号を notes.ini で指定すると動かなくなる、という現象は自分だけなのでしょうか?この辺りはまだ情報があまりなく、うまい回避方法があるといちいち実行ポートをコンソールで確認する必要がなくなって便利なんだけどな・・・ 情報求む。


これまであまり積極的に使うことのなかった webpack を使ってみました:
2018082300


webpack は複数のモジュール(ファイル)を1つに(場合によっては複数に)まとめるバンドラ(bundler)ツールです。Node.js でいうと、エントリーポイントとなる main.js ファイルと、ここから呼ばれるサブ機能が sub1.js や sub2.js などの別ファイルに分かれている場合に、これら3つのファイルを1つのファイルにまとめるというものです。

【サンプルの紹介】
今回は jsonwebtoken パッケージを使ったシンプルなサンプルコード(main.js)を用意しました:
// main.js
const jwt = require( 'jsonwebtoken' );

function main( params ){
  const id = params.id;
  const password = params.password;
  const token = jwt.sign( { id: id, password: password }, 'secret' );

  console.log( token );
}

main({
  id: 'userid',
  password: 'password'
});

global.main = main;

↑ main() 関数の中で2つのパラメータ(id と password)を受け取り、JSON をトークン化して出力する、というものです。そして id = 'userid', password = 'password' を指定して main を実行しています。

この main.js を実行する前に、コード内で使っている jsonwebtoken パッケージをインストールする必要があります。以下の内容の package.json を用意します:
{
  "name": "jwt_test",
  "version": "0.0.1",
  "main": "main.js",
  "dependencies": {
    "jsonwebtoken": "^8.3.0"
  }
}

そして以下のコマンドで jsonwebtoken パッケージをインストールします:
$ npm install


その後に main.js を普通に実行すると、{ id: 'userid', password: 'password' } をトークン化した結果が表示されます:
$ node main.js
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRvdG5zZiIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJpYXQiOjE1MzQ5OTU5NTh9.LUx0q5ycwIFeR1HNnNFgUrlX0w0cny0qDVsPmiVtVnI

とりあえずこの状態で動くことは確認できました。コードは main.js 1つだけに記述されていますが、jsonwebtoken パッケージを利用しているので、実行前に $npm install (jsonwebtoken) を実施しておく必要があり、実際にはここでインストールされるモジュールファイルも使われながら動作します。これらを1ファイルにまとめた上で実行できるようにするというのが今回の目的です。


【webpack のインストール】
webpack は npm を使ってインストールします。例えば以下のコマンドでグローバルインストールすることができます:
$ npm install webpack -g

今回は webpack を(このプロジェクト用に)ローカルインストールして使うことにします。なお webpack 4.0 以降では webpack-cli も合わせて導入する必要があるのでまとめてインストールし、webpack コマンドが実行できるようローカルモジュールへのパスを通します:
$ npm install webpack webpack-cli

$ export PATH=$PATH:./node_modules/.bin


【config ファイルの用意】
webpack を使ってバンドルする作業の条件を config ファイルと呼ばれるファイルで指定します。以下の内容で webpack.js ファイルを作成します:
var path = require( 'path' );
module.exports = {
  entry: './main.js',
  output: {
    path: path.resolve( __dirname, 'dist' ),
    filename: 'bundle.js'
  },
  target: 'node'
};

↑ main.js をエントリーポイント(最初に実行するファイル)とする一連の処理の中で必要とされるモジュール(今回の例では jsonwebtoken パッケージ)がバンドルの対象となり、バンドル結果は dist/bundle.js というファイルに出力される、という指定をしています。


【バンドルと実行】
ここまでに準備した環境とファイルを使って webpack を使ってみます。

まずはバンドル、上記で作成した webpack.js を config ファイルとして指定して webpack コマンドを実行します:
$ webpack --config webpack.js

バンドルが成功すると dist/bundle.js というファイルが生成され、この1ファイルに main.js と jsonwebtoken パッケージがバンドルされているはずです。

確認のため生成されたファイルを実行します。念の為、これらのパッケージモジュールが存在しないテンポラリディレクトリ(/tmp)に bundle.js ファイル1つだけをコピーした上で実行します:
$ cp dist/bundle.js /tmp
$ cd /tmp
$ node bundle.js
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImRvdG5zZiIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJpYXQiOjE1MzUwMDM1MjF9.llZuuWxqX607AWrJBvMEDpFksFX8IvigUrdIWbhItRg

期待通りにトークンが表示される結果になりました。この bundle.js 1ファイルの中に jsonwebtoken パッケージやその依存パッケージまでが含まれる形でバンドルされて実行されたことが確認できました。


webpack を使うことで今回の例のように依存関係ごとファイルをまとめることができるだけでなく、ファイルのモジュール化が促進されたり、一度のロードで全ファイルを読み込めることから SPA(Single Page Application) が作りやすくなったりします。その一方で、バンドル先のファイルが大きくなってしまうと最初のロードに時間がかかるようになる、という問題もあります。個人的にはパッケージ化されたあとに開発コンソールを使ったデバッグが難しくなることに懸念も持っています。

まあケース・バイ・ケース、なんだろうなあ。。

 

Node.js を使ったアプリケーション開発中に npm install を実行して、こんなエラーに遭遇することがあります(個人的な印象では下の例のように canvas モジュールをインストールしようとした際によく遭遇します):
$ npm install canvas

> canvas@1.6.11 install /Users/dotnsf/src/tmp/node_modules/canvas
> node-gyp rebuild

gyp WARN download NVM_NODEJS_ORG_MIRROR is deprecated and will be removed in node-gyp v4, please use NODEJS_ORG_MIRROR
gyp ERR! configure error 
gyp ERR! stack Error: Python executable "/Users/dotnsf/.pyenv/shims/python" is v3.6.5, which is not supported by gyp.
gyp ERR! stack You can pass the --python switch to point to Python >= v2.5.0 & < 3.0.0.
gyp ERR! stack     at PythonFinder.failPythonVersion (/Users/dotnsf/.nvm/versions/node/v8.9.4/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:492:19)
gyp ERR! stack     at PythonFinder. (/Users/dotnsf/.nvm/versions/node/v8.9.4/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:474:14)
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:267:7)
gyp ERR! stack     at emitTwo (events.js:126:13)
gyp ERR! stack     at ChildProcess.emit (events.js:214:7)
      :
      :

スクリーンショット 2018-08-21 9.44.07


Node.js でネイティブモジュールのビルドが必要になった場合に node-gyp を使ってビルドが行われるのですが、その際に使われる Python のバージョンがあっていない、というエラーです。ちと厄介なのは Python のバージョンが古くて問題になっているのではなく、新しすぎてエラーが発生している、ということです(上の例では v2.5.0 以上 v3.0.0 未満でないといけないのに v3.6.5 がインストールされていてエラーが発生している、というメッセージが表示されています)。

この解決のためにわざわざ古いバージョンをインストールしないといけないのか、ということはなく、以下のようにバージョンを明示して npm install することで解決できます:
$ npm install canvas --python=python2.7

> canvas@1.6.11 install /Users/dotnsf/src/tmp/node_modules/canvas
> node-gyp rebuild

gyp WARN download NVM_NODEJS_ORG_MIRROR is deprecated and will be removed in node-gyp v4, please use NODEJS_ORG_MIRROR
      :
      :

+ canvas@1.6.11
added 2 packages in 10.027s


Slack のボットを作るためのフレームワークである BotKit の使い方(というか導入方法)を紹介します。


前提条件として、当然ですが Slack のアカウントは必要です。お持ちでない場合は Slack のページでサインアップおよびサインインを済ませておいてください。サインイン済みの環境に対してボットを作成します。

また BotKit は Node.js のアプリケーションとして動作するので、そのパッケージマネージャである npm が導入されている必要があります。(CentOS 環境用の内容ですが)以下のページを参照するなどして、npm コマンドが使える状態を作っておいてください:
CentOS に StrongLoop をインストールする


最初に Slack の Bot creation page にアクセスして、新しいボットを1つ作成します:
Bot creation page


アクセス先でボットの名前を指定(下図では @dotnsf_bot)して、"Add bot integration" ボタンをクリックすると、ボットが作成されます。ボットの名前は他の人が使っていると使えないので気をつけてください:
2016031701


ボットの作成に成功すると以下の様な画面になり、API Token が表示されます。この値を後で使います。メモ帳などにコピーしておきます:
2016031702


仮にこの API Token の値が xoxb-XXX(API Token)XXX であったとして以下を紹介します。適宜自分の環境と読み替えてください。

次に BotKit をダウンロードします。npm をセットアップしたシステムにログインし、適当なディレクトリ(以下の例では /usr/local/src/)で以下のコマンドを続けて実行し、必要なパッケージとその依存パッケージをダウンロードします:
# cd /usr/local/src
# git clone https://github.com/howdyai/botkit.git
# cd botkit
# npm install

全て導入が完了したら、上記で取得した API Token を使ってボットを動かします(以下を一行で実行します):
# token=xoxb-XXX(API Token)XXX node bot.js

すると以下の様な画面になって、ボットが起動します(途中でボットを強制終了させる場合は Ctrl+C で抜けます):
2016031703



デフォルトのボット(実体は bot.js)ではいくつかの決められた挙動をするように実装されています。いくつか試してみましょう。


まず自分の Slack ID で(ボットを作成した時の Slack ID で)Slack にアクセスし、適当なチャネル(例えば #general)に入ります:
2016031704


以下のコマンドをメッセージとして入力し、ボットをこのチャネルに招待します:
/invite @(ボットの名前)
2016031705


続けて "Hello" というメッセージをこのボット宛に送ります。頭に @(ボットの名前): を付けてメッセージを送ります:
@(ボットの名前): Hello


するとボットが反応し、Hello というメッセージを返してくれます。最初の会話が成立しました:
2016031706



続けて自分のことを聞いてみます。先程と同様にして "Who am i" というメッセージを送ってみますが、"I don't know yet!"(「まだ知らない」)という答が返ってきました。そりゃそうだ:
2016031707


というわけで自分のことを教えてあげましょう。"call me (名前)" というメッセージを送ります。「次からはそう呼ぶ」と分かってくれたっぽい感じ:
2016031708


では改めて "Who am i" と聞いてみます。今度は自分が指定した名前を返してくれました。一応覚えていてくれたっぽいです:
2016031709


最後にこのボットを Slack から終了する方法も紹介します。実行中のコマンドラインから Ctrl + C で強制終了することもできますが、"shutdown" と命令し、確認のメッセージに "Y" と回答するとボットはシャットダウンします(コマンドも終了します):
2016031801




と、デフォルトのボットの挙動はまあこんな感じです。この中身は bot.js の中で実装されていて、そのカスタマイズもこのファイルを編集することになりますが、それについては別のまた機会に。

(2016/Mar/22 追記)
続きはこちら


サーバーサイド JavaScript アプリケーションサーバーである Node.js の MVC フレームワーク Sails.js を API 管理っぽい感じで使ってみました。使ってみた感想としては「(Ruby on )Rails や Strongloop っぽい」という印象です:
2016011001


Sails.js を使う前提として、Node.js の動作環境が必要です。こちらを参照するなどして Node.js アプリケーションサーバーの実行環境を用意しておいてください:
http://dotnsf.blog.jp/archives/1036420834.html


ここに npm を使って Sails.js を導入します。が、そのためには npm のバージョンが 1.4.0 以上である必要があります。まずは npm そのものをアップデートしておきましょう:
# npm update -g npm

その後、npm を使って Sails.js をインストールします:
# npm install -g sails

これで Sail.js の導入は完了したので、sails コマンドが使える状態になっているはずです。試しに1つプロジェクト(mysailsapp)を作ってみましょう。コマンドラインから以下のように入力します(この辺りからして Rails っぽいです):
# sails new mysailsapp

試しにこの状態で一度アプリケーションサーバーを起動して、ウェブブラウザからプロジェクトを参照してみます。作成したプロジェクトのディレクトリに移ってから sails の lift コマンドで HTTP サーバーを起動します:
# cd mysailsapp
# sails lift

2016011002


この状態でウェブブラウザで 1337 番ポートを指定してアクセス(http://XX.XX.XX.XX:1337/)するとデフォルト状態でのプロジェクトページが確認できます:
2016011003


では MVC フレームワークっぽいこともやってみましょう。いったん Ctrl+C で sails lift を終了してから、改めて "item" という名前で商品を扱うような Model と Controller を生成します(sails lift で HTTP サーバーも再起動します):
# sails generate api item
# sails lift

この状態で http://XX.XX.XX.XX:1337/item/ にアクセスすると、現在の item の状態が JSON で確認できます(今はまだ作っただけで中身がないのでこのような空配列の状態になっています):
2016011004


item に1つの要素を追加してみます。ウェブブラウザで http://xx.xx.xx.xx:1337/item/create/?name1=valu1&name2=value2&name3=value3&... といった感じの URL を指定してアクセスしてみます。例えば今回は商品の名称(name)と商品コード(code)を指定してこのような URL にしました:
http://xx.xx.xx.xx:1337/item/create/?name=キュレル薬用シャンプー&code=4901301223159

するとこのような結果が表示されます。データレコードが生成され、id (1)も割り振られました。GET でレコード作れちゃうんですね、へー。。。
これを何度か繰り返して、必要なだけ商品を登録しておきます:
2016011005


改めて /item/ にアクセスすると、作成したデータレコードの配列が取得できることが確認できます:
2016011007


id を指定して、/item/(id) にアクセスすると、その指定した商品の情報を取得することもできます:
2016011008


とりあえず Model と Controller を簡単に作って API 生成ツールとして使えそうなことはわかりました。では更に View の機能も使ってみます。上記で作成した item を表示する test というビューを定義して、
/item/test/(id) にアクセスすると、指定した id の商品情報を出力できるようにしてみます。

まずはコントローラー内に test ビューを定義し、item というパラメータで指定 id の商品をビューに送るような処理を記述します。api/Controllers/ItemController.js というファイルが生成されていると思うので、このファイルを編集して以下の様な処理を追加します(青字部分を追加):
  :
  :
module.exports = { _config: {}, test: function( req, res ){ Item.findById( req.param( 'id' ) ).exec( function( err, item ){ res.view( {item: item[0]} ); }); } }

/item/test/(id) というリクエストの (id) 部分を使って Item を検索し、見つかった結果(結果は配列なので、配列の0番目)を item という名前でビューに送ってレンダリングする、という処理内容です。

更に views/item/test.ejs というファイルを以下の内容で新規に作成します:
<h1><%= item.name %></h1>
<h3>コード = <%= item.code %></h3>
<hr/>
作成日 : <%= item.createdAt %>

この状態で Sails を再起動(Ctrl+C で止めてから再び sails lift)し、ウェブブラウザで /item/test/(id) にアクセスすると、指定した ID の商品が指定したビューのフォーマットで表示できることが確認できるはずです:
2016011009


モデルとコントローラを簡単に生成しての API 作成ツールとしてだけではなく、ビューも使った MVC のフレームワークとしても Sails.js は便利に使えそうです。


 

このページのトップヘ