Node.jsでAlfred Workflowsを作る
Alfredは、Macの多機能ランチャーアプリケーションです。 この記事では、Alfredの機能のひとつ、Alfred Workflows(以下、ワークフロー)をNode.jsで作成する方法を説明します。
「alfy」というライブラリを利用すると、Node.jsでワークフローをカンタンに作成できます。
動作を確認した環境
- Alfred 4(Powerpack)
- Node.js 10
ワークフローのしくみ
ワークフロー(要Powerpack)は、Alfredに割り当てたトリガーや検索ボックスのインプットをもとに、情報を加工し出力します。
たとえば筆者が作成したalfred-kibela-workflowでは、次のことを行っています。
- ユーザーより、「ワークフローのトリガーワード」+「キーワード」が入力される
- 入力されたキーワードで、Kibelaというサービスのノートを検索するため、APIを実行する
- 検索結果のノート一覧をAlfred上に表示する
- ユーザーからノートが選択される、ブラウザでそのノートを表示する
ワークフローは、Alfredの画面から「Trigers」や「Input」「Actions」などのブロックを組み合わせて作ります。
ここで、APIを実行したりAPIから取得したデータをAlfredで表示できるデータに加工するため、簡単なスクリプトを書く必要があります。
作成手順
今回は、Qiitaの記事をキーワード検索して記事一覧を表示し、ユーザーが一覧から記事を選ぶとその記事をブラウザで開くというワークフローを作成します。
1. ダミーワークフローの作成
ダミーワークフローを作って、info.plist
を作成します。 info.plist
は、Alfredワークフローのマニフェストファイルです。
2. 新規作成
- Alfredの設定画面を開き、[Workflows]タブを選択します。
- 画面下の[+]マークをクリックし、[Blank Workflow]を選択します。ワークフローの作成ダイアログが表示されます。
- ワークフローを設定します。
- あとで値は変更できますが、「Name」と「Bundle Id」は必ず入力してください。
- [Create]ボタンをクリックして作成します。Workflowのリストに作成したワークフローが表示されます。
3. ブロックの作成
- 作成したワークフローを選択します。
- 右側のブロックエディタ部分で右クリックします。
- 次のブロックを追加します。
- [Input]>[Script Filter]を選択し、「Script Filter」ブロック
- [Actions]>[Open URL]を選択し、「Open URL」ブロック
- 追加したブロックで、それぞれ次のように設定します。
「Script Filter」ブロック
項目 説明 Keyword ワークフローのトリガーキーワードを設定します。 -「with space」にチェック -「Argument Required」を選択 Language 「/bin/bash」を選択し、「with input as {query}」を選択します。 Script ./node_modules/.bin/run-node src/index.js "{query}"
と入力します。あとで作成する Node.js プログラムを実行するコマンドです。 「Open URL」
項目 説明 Encode input as UTF-8 チェックを入れる Browser 「Default Browser」を選択
- ブロックを結合します。
4. info.plistのエクスポート
- 作成したワークフローを右クリックし、[Open in Finder]を選択します。
info.plist
があるので、別の場所にコピーしておきます。- 作成したダミーワークフローを削除します。
5. Node.jsプログラムの作成
Node.jsでスクリプトを作成します。 ここでは、Qiita APIを実行して記事を検索し、取得結果をAlfredの一覧に渡すことを考えます。
プロジェクトを作成します。
mkdir alfred-workflow-example && cd $_ npm init -y
先ほどコピーした
info.plist
をプロジェクトディレクトリの直下に配置します。alfyをインストールします。
npm i --save alfy
package.json
を開き、npmスクリプトを定義します。"scripts": { "postinstall": "alfy-init", "preuninstall": "alfy-cleanup" },
jsファイルを作成します。
mkdir src touch src/index.js
src/index.js
を開き、以下を記述します。const alfy = require("alfy"); const token = process.env.QIITA_ACCESS_TOKEN || ""; const keyword = alfy.input; const resp = await alfy.fetch( `https://qiita.com/api/v2/items?query=body:${keyword}`, { method: "get", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, } ); const items = resp.map((el) => { return { title: el.title, subtitle: el.user.name, arg: el.url, }; }); alfy.output(items);
コードのポイント
アクセストークン
- アクセストークンなどのユーザー固有の値は、設定する環境変数をワークフローごとに定義します。この値は、
process.env.KEY
で受け取ることができます。
- アクセストークンなどのユーザー固有の値は、設定する環境変数をワークフローごとに定義します。この値は、
ワークフローに渡される変数
- ワークフローでトリガーと一緒に引数を渡したい場合、「Filter Script」ブロックを使ってスクリプトに渡します。渡された値は
alfy.input
を使って受け取ります。
- ワークフローでトリガーと一緒に引数を渡したい場合、「Filter Script」ブロックを使ってスクリプトに渡します。渡された値は
alfy.fetch()
を使うと、HTTPリクエストを送信できます。- http.requestをベースに作られているため、ヘッダーやデータなど渡すオプションはhttp.requestのドキュメントを参照してください。
- 戻り値はPromiseです。
alfy
ではtop-level-awaitを利用するには、package.json
に以下を追記します。"esm": { "await": true },
Alfred がサポートしている JSON オブジェクトになるよう、リクエスト結果を加工します。
- ActionsやOutputsのブロックに渡したい値を
arg
に設定します。
- ActionsやOutputsのブロックに渡したい値を
ワークフローのインストール
作成したワークフローをインストールします。プロジェクトディレクトリ直下で、次のコマンドを実行します。
npx alfy-init
Alfredワークフローの設定画面を開きます。
一覧より、インストールしたワークフローを選択します。
環境変数を設定します。[x]ボタンをクリックします。
次の環境変数を設定します。
Name Value QIITA_ACCESS_TOKEN Qiita のアクセストークン Qiita のアプリケーション設定画面から作成できます。
動作確認
- Alfredを起動します。
- 「qiita検索クエリ」を入力します。
- しばらくすると、検索結果の一覧が表示されます。
- 一覧からエンターキーで選択します。ブラウザで該当の記事が表示されます。
ワークフローの公開
作成したワークフローは、npm intallコマンドでインストールできるような形にすると、他の人に配布できます。 たとえば、GitHubリポジトリに公開したり、さらにnpm registoryに公開したりするなどです。
公開するときは、info.plist
の中に環境変数の値がセットされていないことを次の手順で確認してください。含まれていた場合は削除してください。
info.plist
をテキストエディタで開きます。- エディタ内で、環境変数名を検索します。
xml <key>variables</key> <dict> <key>QIITA_ACCESS_TOKEN</key> <string>This_is_a_Qiita_token</string> </dict>
- 環境変数の値がセットされていた場合は、値を削除しておきます。
xml <key>variables</key> <dict> <key>QIITA_ACCESS_TOKEN</key> <string></string> </dict>