Experiments Never Fail

Azure の Functions Bot を TypeScript で作る(+ VSCodeでデバッグする)

Bot Application が Azure Functions で作れるようになっていました。

image.png

Node.js か C# のいくつかのテンプレートから選択できます。

Node.js → Basic を選択して作った Functions は JavaScript なので、これを TypeScript に変えてみます。

Node.js のサンプルをダウンロードする #

Bot を作成したあと、ビルド → zip ファイルをダウンロード でソースコード一式がダウンロードできます。

そのディレクトリ構成は次の図に。

image.png

TypeScript に書き換える #

/messages ディレクトリが Function のソースなので、ターミナルでここに移動し、

tsc init

を実行します。すると tsconfig.json が作成されるので、それを次のように書き換えます。

messages/tsconfig.json

{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"sourceMap": true,
"strict": false,
"esModuleInterop": true
}
}

コメント行や説明のコメントは省略しています。既定値から変えたのは次の通り。

次に TypeScript で必要なモジュールをインストールします。

ターミナルで messages ディレクトリに移動し、

npm install @types/node --save-dev

を実行します。実行後、 package.json@types/node が追加されます。

messages/package.json

{
"name": "emptybot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"botbuilder": "^3.13.1",
"botbuilder-azure": "^3.0.4"
},
"devDependencies": {
"@types/node": "^10.5.1", <-- ここが追加された
"restify": "^5.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

次に index.js をリネームし index.ts とし、内容を次のように書き換えます。

messages/index.ts

import { ChatConnector, MemoryBotStorage, UniversalBot, Session } from 'botbuilder';
import { BotServiceConnector, AzureTableClient, AzureBotStorage } from 'botbuilder-azure';
import * as path from 'path';

const useEmulator = (process.env.NODE_ENV == 'development');

const connector = useEmulator ? new ChatConnector() : new BotServiceConnector({
appId: process.env['MicrosoftAppId'],
appPassword: process.env['MicrosoftAppPassword'],
openIdMetadata: process.env['BotOpenIdMetadata']
});

/*----------------------------------------------------------------------------------------
* Bot Storage: This is a great spot to register the private state storage for your bot.
* We provide adapters for Azure Table, CosmosDb, SQL Azure, or you can implement your own!
* For samples and documentation, see: https://github.com/Microsoft/BotBuilder-Azure
* ---------------------------------------------------------------------------------------- */


const tableName = 'botdata';
const azureTableClient = new AzureTableClient(tableName, process.env['AzureWebJobsStorage']);
const storage = useEmulator ? new MemoryBotStorage() : new AzureBotStorage({ gzipData: false }, azureTableClient);

const bot = new UniversalBot(connector);
bot.localePath(path.join(__dirname, './locale'));
bot.set('storage', storage);

bot.dialog('/', function (session: Session) {
session.send('あなたは ' + session.message.text + 'と言いましたね。');
});

if (useEmulator) {
const restify = require('restify');
const server = restify.createServer();
server.listen(3978, function() {
console.log('test bot endpont at http://localhost:3978/api/messages');
});
server.post('/api/messages', connector.listen());
} else {
module.exports = connector.listen();
}

処理内容はほぼ変えず、文法を TypeScript にしただけです(MemoryBotStorage を使うとこだけ処理を追加してます、これをしないとローカルで動かなかったので)。

messages ディレクトリで

tsc

を実行します。すると同じディレクトリに index.jsindex.js.mmap が生成されます。

この index.js をこれまでの index.js の代わりに Azure にアップロードすれば、関数はいままでどおり動作します。

ローカルでデバッグする(VSCode使用) #

launch.json の定義が古いのでちょっと追記します。

messages/.vscode/launch.json

{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"protocol": "inspector", <-- この行を追加
"program": "${workspaceRoot}/index.js",
"cwd": "${workspaceRoot}",
"env": {
"NODE_ENV": "development"
}
}
]
}

index.ts(.js じゃないよ) の適当な行にブレークポイントを仕掛けて、メニュー -> デバッグ -> デバッグの開始 をします。

image.png

ちゃんと止まるはずです。

BotFramework-Emulator にローカルのエンドポイントである http://localhost:3978/api/messages を指定すれば、ボットのデバッグができます。

image.png

環境 #

参考 #

published at tags: Azure AzureFunctions BotFramework TypeScript VSCode