Notion APIを使ってみた
Notionでネットの記事の積読を管理している。積読の数が1000を超え、ノイズになっていたので一度全て断捨離することにした。
状況・やりたかったこと
- Articleというデータベースで積読を管理
- Read StatusというSelectカラムでステータス管理
- 未設定:積読
- Read:読んだ
- Trash:やっぱ読むのをやめた、読まない
- → Read Statusが未設定のページのRead StatusをTrashにする
1000以上のページを手動で変更するのはできなくはなかったが、せっかくなのでNotion APIを使ってみた。
やったこと
- Getting started にしたがって作業
- Integrationを作成
- Articleデータベースを作成したIntegrationにシェア
- NotionのJavaScript SDKを使ってバッチ処理スクリプトを書いた
バッチ処理スクリプトの詳細
- メインの処理
- カーソルを使って対象のページを全件取得
- 1件ずつ直列で更新
- API:https://developers.notion.com/reference/patch-page
- Rate Limits (avg: 3rps)に引っかからないように直列にリクエスト
- さらに念のため、timersPromises.setTimeoutでsleepをかける
- サブ
- dotenv で環境変数を設定
- performance.now() を使って処理時間を計測
- Dry Runオプションをつけて、Dry Runの場合は更新処理をスキップ
実行結果
以下、試しに2件更新してみたときのRTT。
Update took 684.6306619644165ms. Update took 283.28467202186584ms.
以下、全件更新結果。
$ npm run start > notion-article-batch@1.0.0 start > node -r dotenv/config index.js Sun Aug 14 2022 hh:mm:ss GMT+0900 (日本標準時) Update started. Sun Aug 14 2022 hh:mm:ss GMT+0900 (日本標準時) 1055 pages updated. Update took 694149.2413560152ms.
特にエラーが出ることなく無事に全件更新された。
所感
.gitconfigを整備した
git config --global
コマンドで各種設定値を設定できる ~/.gitconfig
ファイルを整備した。整備した .gitconfig
ファイルは https://github.com/azujuuuuuun/dotfiles/blob/master/.gitconfig にpushした。変更前のファイルをコミットしていなかったので差分をこのブログに記録する。
変更前はuser, core, alias, credential, merge, pullを設定していた。mergeとpullはよく理解せずにその場しのぎで設定していた。
今回、Git - git-config Documentation を参照しつつ、設定を追加した。量が膨大だったのでよく使うコマンドを検索して、目についたものを設定した。fetchのpruneオプションが綺麗になったのがお気に入り。
変更前
[alias] fe = fetch -p
変更後
[alias] fe = fetch [fetch] prune = true
GitHubでメールアドレスをプライベートにする
- https://github.com/settings/emails へアクセスする
- 「Keep my email addresses private」(2022/08/11現在の文言)をチェックする
これでGitHubからマージや編集などのGitの操作をしたときのメールアドレスが ID+username@users.noreply.github.com
になる。ローカルでしたコミットに紐づくメールアドレスも他のユーザーからわからないようにするために ID+username@users.noreply.github.com
に変更する。
$ git config --global user.email "ID+username@users.noreply.github.com"
$ git config --global user.email
ID+username@users.noreply.github.com
Node.jsのバージョン管理をVoltaに移行してみた
Nodeのバージョン管理にnodenvを利用していた。Voltaは良いと聞いていたが、面倒くさくて触ってこなかった。今更ながら重い腰を上げて移行してみた。
やったこと
nodenvのアンインストール
https://github.com/nodenv/nodenv#uninstalling-nodenv に書いてあることをした。アンインストール手順まで書いてあって親切。.zshrcにあった以下の行を削除。
eval "$(nodenv init -)"
以下のコマンドを実行。
$ rm -rf `nodenv root`
$ brew uninstall nodenv
無事にアンインストールが完了した。
Voltaのインストール
https://docs.volta.sh/guide/getting-started 通りにコマンドを実行した。
$ curl https://get.volta.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 12319 100 12319 0 0 12221 0 0:00:01 0:00:01 --:--:-- 12233 Installing latest version of Volta (1.0.8) Checking for existing Volta installation Fetching archive for macOS, version 1.0.8 ######################################################################## 100.0% Creating directory layout Extracting Volta binaries and launchers Finished installation. Updating user profile settings. Updating your Volta directory. This may take a few moments... success: Setup complete. Open a new terminal to start using Volta!
以下の2つのexportコマンドが.zshrcに書き込まれた。
export VOLTA_HOME="$HOME/.volta" export PATH="$VOLTA_HOME/bin:$PATH"
Nodeをインストール
$ volta install node@16 success: installed and set node@16.16.0 (with npm@8.11.0) as default $ node -v v16.16.0 $ which node ~/.volta/bin/node
最初のコマンドで2022/08/11現在、LTS版の16.16.0がインストールされた。インストールが速いと聞いていたが、確かに速かった。
Nodeのバージョンを固定
pinコマンドでNodeのバージョンを固定するらしい。
$ volta pin node success: pinned node@16.16.0 (with npm@8.11.0) in package.json $ git diff diff --git a/package.json b/package.json index d49efda..a026ba0 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,8 @@ "eslint": "8.21.0", "eslint-config-next": "12.2.4", "typescript": "4.7.4" + }, + "volta": { + "node": "16.16.0" } }
package.jsonのvoltaフィールドにNodeのバージョンが書き込まれた。これでVoltaを利用していれば他のプロジェクトメンバーも同じNodeのバージョンで開発することができる。
ZodをNext.jsで使ってみた
最近、Zodという名前をTwitterでよく見かける。
TypeScriptファーストなスキーマベースのバリデーションライブラリらしい。試しにNext.jsのクエリパラメーターのバリデーションで使ってみた。
架空の検索結果ページのクエリパラメーターをバリデーションする想定で書いてみた。
パス
/search
クエリパラメーター
key名 | 値 | 必須 | 型 | デフォルト値 | 取りうる値 | 対応するスキーマ |
---|---|---|---|---|---|---|
q | 検索文字列 | ○ | string | 1文字以上の文字列 | https://github.com/azujuuuuuun/try-zod-in-next/blob/main/src/model/search/search-query.ts | |
page | ページ番号 | number | 1 | 正の整数 | https://github.com/azujuuuuuun/try-zod-in-next/blob/main/src/model/search/page.ts | |
sort | ソート順 | string | "recommend" | "new", "recommend" | https://github.com/azujuuuuuun/try-zod-in-next/blob/main/src/model/search/sort.ts |
感想
iOS Safariでvideo要素に設定した動画が表示されない
<input type="file”>で同じファイルを選択できるようにする - なんでもノート に続きtipsの4個目。video要素のsrc属性を動的に変更したとき、iOS Safariで動画が表示されない事象に遭遇した。結論としてはvideo要素のsrc属性を動的に変更した場合は、load()メソッドを呼ぶ必要があった。以下、React + TypeScriptのサンプルコード。CodeSandboxを使ってみた(初めて使った)。12行目をコメントアウトすると選択した動画が表示されなくなる(はず)。
<input type="file”>で同じファイルを選択できるようにする
<video>に読み込んだ動画の秒数を取得する - なんでもノート に続きtipsの3個目。でファイルを選択し、再度同じファイルを選択しても1度目のvalueが残ってしまっているため、changeイベントが発火しない。対応方法は2つある。1つ目は1度目のchangeイベントの処理の最後にvalueに空文字列を設定する方法。以下、React + TypeScriptのサンプルコード。
const ref = React.useRef<HTMLInputElement>(null); const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { // ここに処理を書く if (ref.current) { ref.current.value =""; } } // …(略)… <input ref={ref} type="file" onChange={onChange} />
2つ目はclickイベントでvalueに空文字列を設定する方法。以下、React + TypeScriptのサンプルコード。
const ref = React.useRef<HTMLInputElement>(null); const onClick = () => { if (ref.current) { ref.current.value =""; } } const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { // ここに処理を書く } // …(略)… <input ref={ref} type="file" onClick={onClick} onChange={onChange} />