AvroファイルビューワーをVSCode拡張機能で作る

R&D部のmatsushitasです。
普段はフロントもバックエンドも満遍なく触る方なのですが、最近はApache KafkaやApache Sparkによるストリーム処理の領域を担当することが増えました。

タイトルにあるAvroというのはスキーマ定義の付いたJSONのようなもので、KafkaやSparkで扱うことができます。
ストリーミングデータは最終的にHDFSに.avroファイルとして保存されるのですが、このAvroファイルはバイナリで、通常のエディタで開くことはできません。
普段開きっぱなしにしていることの多いVSCodeで見れたら楽だなと思い拡張機能を探したのですが見当たらず。もうこれは作るしかありません。

作ったもの

VSCode上で.avroファイルを選択し、右上の「Preview Avro File」をクリックして中身が確認できます。

avro viewer

後述しますがほとんどが雛形のままで、実装部分はこのファイルだけです。
https://github.com/romiogaku/vscode-avro-viewer/blob/master/src/extension.ts

拡張機能の作り方

公式ドキュメントが非常に充実しており悩むことは無かったです。
以下、開発していく上でのポイントです。

Yeomanで雛形作成

雛形作成ツールのYeomanと、VSCode拡張のジェネレータをインストールします。

npm install -g yo generator-code

以下のコマンドで雛形が作れます。

yo code

TypeScriptを選択した場合、ディレクトリ構成は以下のようになっています。

.
├── .vscode
│   ├── launch.json     // 起動・デバッグ設定
│   └── tasks.json      // TypeScrpitコンパイルのビルドタスク設定
├── .gitignore          
├── README.md           
├── src
│   └── extension.ts    // ここにプログラムを書いていく
├── package.json
├── tsconfig.json

package.jsonは拡張機能のマニフェストファイルとしても利用するため、ストアに公開する場合は以下の様にpublisherも書いておきましょう。

{
    "name": "vscode-avro-viewer",
    "displayName": "Avro Viewer for VS Code",
    "description": ".avro file viewer for VS Code",
    "version": "1.0.1",
    "publisher": "romiogaku",
    "repository": "https://github.com/romiogaku/vscode-avro-viewer",
    "engines": {
        "vscode": "^1.31.0"
    },
    "categories": [
        "Other"
    ],
    "activationEvents": [
        "onCommand:avro.preview"
    ],
    "main": "./out/extension.js",
    ・・・(略)・・・
}

デバッグ

VSCode拡張機能の開発はVSCodeでおこないます。
yo codeで雛形を作ったらF5を押すか、デバッグメニューのボタンをクリックします。


すると新たにウィンドウが立ち上がり、実際に開発中の拡張機能を動かすことができます。簡単ですね。

豊富なサンプルから目的に近いものを探す

自分の作りたい拡張機能に近いものを以下のリポジトリから探すのが手っ取り早いです。
https://github.com/Microsoft/vscode-extension-samples
今回のケースではこちらのサンプルが参考になりました。

Virtual Documentを使うとVSCodeで読み取り専用のドキュメントを作成できます。
Avroファイルの中身が見れれば良かったので採用しましたが、WebViewをエディタに表示させることもできるので、やろうと思えばもっとリッチな表示も可能です。
WebViewのサンプルはこちら

Avroファイルのデコード

Avroファイルのデコードにはmtth/avscを利用しています。

import * as avro from 'avsc';

async function decode(path: string) {
  let metadata = '';
  let datas: Array<string> = [];
  const decoder = avro.createFileDecoder(path);
  decoder.on("metadata", (type: any) => {
    metadata = JSON.stringify(type, null, 4);
  });
  decoder.on("data", (type: any) => {
    datas.push(JSON.stringify(type, null, 4));
  });
  await new Promise(resolve => decoder.on('end', () => resolve()));
  const data = datas.join("\n");
  return `=============METADATA============
${metadata}

===============DATA==============
${data}
`;
}

JSON.stringifyでいい感じに整形し、メタデータとデータ本体を文字列としてまとめて返しているだけです。

パッケージング

拡張機能のパッケージングにはvsceコマンドを使います。”Visual Studio Code Extensions”の略みたいです。

npm install -g vsce

インストールしたら拡張機能のディレクトリに移動し、

vsce package

でパッケージングします。実行すると

{name}-{version}.vsix

というファイルが生成されます。nameversionpackage.jsonで指定したものが入ります。
Marketplaceに公開しなくても、このvsixファイルをインストールしてもらうことで他の人も拡張機能が使えるようになります。

Marketplaceに公開

Visual Studio Marketplaceへ公開するには、Azure DevOpsに登録する必要があります。
こちらの手順に従ってアクセストークンを発行したら、

vsce publish <version>

で公開できます。

せっかくなので公開しました。
https://marketplace.visualstudio.com/items?itemName=romiogaku.vscode-avro-viewer
アイコンが無いので寂しいですね。拡張機能の説明はREADME.mdがそのまま表示されます。

最後に

VSCodeの拡張機能を作るのは初めてでしたが、欲しいものがシンプルだったので業務の間でサクッと実装できました。
自分はフロントにもバックエンドにも特別特化したエンジニアではなく、ずっと同じことやってると飽きてしまう性格なので、がっつりバックエンド開発をしている途中でこういうツールを作れたのは良い気晴らしになりました。
はっきりいって需要はほとんど無いと思いますが、誰かの役に立ってくれれば幸いです。

フロントやったりバックエンドやったり。 最近の趣味は自作キーボード。 PHP, JS, Go, Scala