It's my life
Recent posts 6 / 102
CI回してたら変な星条旗おじさんが出てきて動かなくなってしまったので直しつつOSSのあり方を考える2022年はもっと生産的に過ごすためにGitHub Projectを使ったToDo管理やります!!!今年も最後だからBlogのBootstrap v3を何とかするdepcheckをGitHub Actionで使い、PRコメントに結果を出力させるヤクの毛刈りから考えるヤクの可愛さDenoを使ってGraphQLを叩きながらSlackに投稿するSearchBox
Search my blog.体重が落ちてきました!
前回Hasura CloudのGraphQLが便利すぎた話の記事の最後の方でSlackにダッシュボードの情報をあげるスクリプトを作って定期的に実行させることをしました。
がしかし、あろうことかスクリプトはTypeScriptじゃなく、**JavaScript(ES module)**でした。
どうして、TypeScriptにしなかったかというと、
という理由で、まぁただの付加機能でしかないのでmjsでぱぱっと作ってしまった、というわけです。
今回はロジックは特に変えずにランタイムをDenoに変更し、ついでにTypeScript化させちゃいましょう。
Denoとは、Node.jsの作者であるRyan Dahlによって作られた、新しいJavaScript/TypeScriptランタイムです。
Node.jsに関する10の反省点という講演の中で氏がNode.jsのここがまずかった!ということをあげて、Denoのプロトタイプ版を出したのが始まりとか。
ちなみに、Nodeを並べ替えるとDeno。
ちなみにアイコンは恐竜らしい。ダイナソーでDeno。
アイコンについてのおもしろ話は
https://hashrock.hatenablog.com/entry/2019/02/04/040505
を参照しよう!直接作者と会話できるのはいいですね。
実際、Denoで動かそうがNodeで動かそうがあまり違いがないと思ってたのですが細かい違いがありました。(初心者)
まず、基本的なことですがビルトインの機能がすべてDenoに内包されてます。
なので環境変数は
const imgurClientId = Deno.env.get('IMGUR_CLIENT_ID') as string;
のように取得します。process.envではないんですね。 あとas stringという記述がありますがas stringしておかないと、fetch関数に渡すときTypeErrorとなってしまいます。
Denoにはnpmやらpackage.jsonのようなモジュール管理がランタイムに内蔵されているため、importはURLで参照します。
もちろんCommonJSのrequireなんてありません。なので、requireしていた部分も書き直しです。
やはり便利だなと思ったのはサーバーでfetchが使えることでしょうか?cross-fetchとか入れないでいいんですよ!
(でもaxios使いたいマンなので、喜び半分くらいですね。)
あと便利だなと思ったのはtop levelのコードでawaitって書いていいことですね。これはありがたい。
import {encode} from 'https://deno.land/std/encoding/base64.ts';
const URI_ENDPOINT = 'https://xxxxx.hasura.app/v1/graphql';
const filePath = './cypress/screenshots/screenshot.spec.js/screenShot.png';
const dashBoardUrl = 'https://plant-check-graph.vercel.app/'
const slackWebhookUrl = Deno.env.get('SLACK_WEBHOOK_URL') as string;
const imgurClientId = Deno.env.get('IMGUR_CLIENT_ID') as string;
const readImageData = await Deno.readFile(filePath);
const encodedData = encode(readImageData);
const imgurPayload = {
image: encodedData.replace(new RegExp('data.*base64,'), ''),
type: 'base64'
}
const imgurHeaders = {
'Accept': 'application/json',
'Authorization': `Client-ID ${imgurClientId}`,
'Content-Type': 'application/json'
}
const imgurRes = await fetch('https://api.imgur.com/3/image', {method: 'POST', headers: imgurHeaders, body: JSON.stringify(imgurPayload)})
const imgurJson = imgurRes.json()
const { data: imgurData } = await imgurJson
const imgurLink = imgurData.link
const query = {
query: 'query MyQuery {\nraspi_plant_checker(order_by: {timestamp: desc}, limit: 1) {\n light\n moisture\n timestamp\n id\n }\n}',
variables: null,
operationName: 'MyQuery'
}
const hasuraHeaders = {
'Content-Type': 'application/json'
}
const hasuraRes = await fetch(URI_ENDPOINT, {method: 'POST', headers: hasuraHeaders, body: JSON.stringify(query)})
const hasuraJson = hasuraRes.json()
const hasuraData = await hasuraJson
const latestHasuraData = hasuraData.data.raspi_plant_checker[0]
console.log(latestHasuraData)
const slackPayload = {
text: `*How are you?* \n<${dashBoardUrl}|Click here> for details! \n${imgurLink}`,
attachments: [
{
fields: [
{
title: 'Moisture',
value: latestHasuraData.moisture,
short: 'true'
},
{
title: 'Light',
value: latestHasuraData.light,
short: 'true'
},
]
}
]
}
const slackHeaders = {
'Accept': 'application/json',
'Content-Type': 'application/json'
};
await fetch(slackWebhookUrl, {method: 'POST', headers: slackHeaders, body: JSON.stringify(slackPayload)})
使いどころはまだ限られる気もしますが、徐々にDenoに慣れていこうと思います!!!!