Tagbangers Blog

Deno を使用して RESTful API → CSV 書き出し

こんばんわ、FE 側の JK です

業務で使用するちょっとしたツールを Deno で作ってみたかったので調べてみました

Deno とは

Deno - A secure runtime for JavaScript and TypeScript

Node.js の作者によって作られた新しいランタイム環境で 2020 年にリリースされたばかりです

TypeScript がゼロコンフィグで使用できるのが嬉しい点です

node の文字を入れ替えると deno になる話は有名だそうです

node -e "console.log('node'.split('').sort().join(''))"

準備

インストール

brew install deno

バージョン確認

$ deno --version
deno 1.9.2 (release, x86_64-apple-darwin)
v8 9.1.269.5
typescript 4.2.2

TypeScript の最新バージョンが入ってますね

VSCode で開発するのでプラグインを入れます

機能を有効にするためにプロジェクト直下に .vscode/settings.json を用意します

{
  "deno.enable": true
}

Deno は Formatter と Linter も組み込まれているので有効にしておくと良いでしょう

{
  "deno.enable": true,
  "deno.lint": true,
  "deno.unstable": true,
  "editor.formatOnSave": true
}

デモ

GitHub の REST API を使用してレポジトリ一覧を取得 → CSV として出力します

GitHubのREST API - GitHub Docs

REST API を呼ぶ

Node.js では fetch の他に npm で axios を追加して使用することが多いと思います

残念ながら Deno では npm パッケージが通常利用できないですが Deno に対応した ky というモジュールがあるのでそちらを利用します

https://github.com/sindresorhus/ky

Deno では package.json に相当するののは必要ありません、直接ファイルに URL を指定できます

バージョン固定は URL 上で行えるので、固定しておきましょう

import ky from "https://cdn.skypack.dev/ky@0.28.0?dts";

console.log(await ky.get("https://api.github.com").json());

main.ts に記述します、他にファイルは必要ないです

実行します

Deno はセキュリティが強化されているためデフォルトで実行できる権限が制限されています

今回はインターネット通信が必要なので --allow-net オプションが必要です

deno run --allow-net main.ts

JSON レスポンスが表示されました

次にレポジトリ一覧を取得して必要な情報だけテーブル出力させます

import ky from "https://cdn.skypack.dev/ky@0.28.0?dts";

const baseUrl = "https://api.github.com";
const user = "koyama-tagbangers";

type Response = {
  name: string;
  fork: boolean;
  html_url: string;
}[];

const repos = await ky.get(`${baseUrl}/users/${user}/repos`).json<Response>();

const data = repos.map(({
  name,
  fork,
  html_url,
}) => ({
  name,
  fork,
  html_url,
}));

console.table(data);

ky では json() メソッドに型を指定しないと unknown 型となり、データ加工の際に型エラーが生じるので type を指定します、TS の恩恵ですね

データをテーブル表示できました

CSV 出力

Deno の CSV モジュールを使用します

https://github.com/vslinko/deno-csv

import ky from "https://cdn.skypack.dev/ky@0.28.0?dts";
import { writeCSV } from "https://deno.land/x/csv@v0.5.1/mod.ts";

const baseUrl = "https://api.github.com";
const user = "koyama-tagbangers";

type Response = {
  name: string;
  fork: boolean;
  html_url: string;
}[];

const repos = await ky.get(`${baseUrl}/users/${user}/repos`).json<Response>();

const data = repos.map(({
  name,
  fork,
  html_url,
}) => ({
  name,
  fork,
  html_url,
}));

console.table(data);

const header = Object.keys(data[0]);
const body = data.map((values) =>
  Object.values(values).map((v) => v.toString())
);

const file = await Deno.open("./repos.csv", {
  write: true,
  create: true,
  truncate: true,
});
await writeCSV(
  file,
  [header, ...body],
);

ファイルの書き込みは Deno の組み込み変数の open を利用します

こちらもデフォルトで権限が制限されているので、書き込み・作成・上書きの権限をオプション指定する必要があります

そして実行する際もフラグが必要です

deno run --allow-net --allow-write main.ts

CSV 出力できました (UTF-8)

TS でサクッとツール作りたい時に使いたいです