From 2772e5c9d96edf29d1c9f372e98ddedbea7f12a4 Mon Sep 17 00:00:00 2001 From: ma91n Date: Thu, 9 Jan 2025 11:48:39 +0900 Subject: [PATCH] url-tify --- ...43\343\201\246\343\201\277\343\201\237.md" | 167 ++++++++++++++++++ source/images/20250109a/thumbnail.png | Bin 0 -> 11188 bytes source/images/20250109a/urltidy.png | Bin 0 -> 22827 bytes 3 files changed, 167 insertions(+) create mode 100644 "source/_posts/20250109a_\346\247\213\351\200\240\345\214\226\343\203\206\343\202\255\343\202\271\343\203\210(URL)\343\202\222\346\226\207\345\255\227\345\210\227\347\265\220\345\220\210\343\201\247\344\275\234\343\202\211\343\201\252\343\201\204\343\202\210\343\201\206\343\201\253\343\201\231\343\202\213\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" create mode 100644 source/images/20250109a/thumbnail.png create mode 100644 source/images/20250109a/urltidy.png diff --git "a/source/_posts/20250109a_\346\247\213\351\200\240\345\214\226\343\203\206\343\202\255\343\202\271\343\203\210(URL)\343\202\222\346\226\207\345\255\227\345\210\227\347\265\220\345\220\210\343\201\247\344\275\234\343\202\211\343\201\252\343\201\204\343\202\210\343\201\206\343\201\253\343\201\231\343\202\213\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" "b/source/_posts/20250109a_\346\247\213\351\200\240\345\214\226\343\203\206\343\202\255\343\202\271\343\203\210(URL)\343\202\222\346\226\207\345\255\227\345\210\227\347\265\220\345\220\210\343\201\247\344\275\234\343\202\211\343\201\252\343\201\204\343\202\210\343\201\206\343\201\253\343\201\231\343\202\213\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" new file mode 100644 index 00000000000..13a492c28b5 --- /dev/null +++ "b/source/_posts/20250109a_\346\247\213\351\200\240\345\214\226\343\203\206\343\202\255\343\202\271\343\203\210(URL)\343\202\222\346\226\207\345\255\227\345\210\227\347\265\220\345\220\210\343\201\247\344\275\234\343\202\211\343\201\252\343\201\204\343\202\210\343\201\206\343\201\253\343\201\231\343\202\213\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\343\202\222\344\275\234\343\201\243\343\201\246\343\201\277\343\201\237.md" @@ -0,0 +1,167 @@ +--- +title: "構造化テキスト(URL)を文字列結合で作らないようにするライブラリを作ってみた" +date: 2025/01/09 00:00:00 +postid: a +tag: + - TypeScript + - npm + - tsup + - Go +category: + - Programming +thumbnail: /images/20250109a/thumbnail.png +author: 澁川喜規 +lede: "SQL、ファイルパスなどの構造化テキストを文字列結合で作ると、不正な文字列が入ってきた時に困るよ、というのはプログラミングの基本原則ですが、URLはついついやってしまいがちな部分です。だいたいの言語には" +--- + + + +SQL、ファイルパスなどの構造化テキストを文字列結合で作ると、不正な文字列が入ってきた時に困るよ、というのはプログラミングの基本原則ですが、URLはついついやってしまいがちな部分です。 + +だいたいの言語にはURLクラスとかURIクラスとかその手のものがあり、それを使うことで安全にパースしたり組み立てたりできるのですが、いかんせんコードが長くなりがち、ということがあります。 + +TypeScriptをビルドしてnpmパッケージを作るのに便利な[tsup](https://tsup.egoist.dev)というツールを使ってみたかったので、その題材としてURLを簡単かつ安全に組み立てるユーティリティを作ってみました。Node.js、Deno、Bunで動作確認しています。 + +* NPM: https://www.npmjs.com/package/url-tidy +* GitHub: https://github.com/shibukawa/url-tidy + +テンプレートリテラルの前に関数をつける記法、タグ付きテンプレートリテラルというのがあります。文字列にする代わりに、テンプレートの文字列と間の値がこの関数の入力値になり、関数の返り値が実際のリテラルの評価値になる、というものです。[lit](https://lit.dev/docs/v1/lit-html/introduction/)のHTMLテンプレートとして使われているやつですね。 + +# 作ったユーティリティの紹介 + +それを使ってURLを組み立てます。 `url`というのがこの変換関数です。 + +```ts +import { url } from "url-tidy"; +``` + +こんな感じで、文字列テンプレートとあまり変わらない感じですが、固定の文字列部分もきちんとURLの要素(プロトコルとかホストとかパスとかクエリーとか)にパースして要素分解しますし、固定部分もプレースホルダーで渡されるパス部分は`encodeURI()`を通すし、最後のURLの組み立ては`URL`クラスとか`URLSearchParams`を裏で使うので、不正な文字が入って不正なURLになるということは防げているかと思います。まああまり遅いことはなさそうですが、固定文字列部分は一度パースしたらその状態をキャッシュするようにしています。 + +プレースホルダーはパス、クエリーの値、フラグメントなど、1つの要素に対してのみしか使えないようにしています。パスの末尾とクエリーをまるごと文字列で渡す、みたいなことはできません。 + +一番基本的な使い方はパスの一部の置き換えでしょう。 + +```ts +const id = 1000; +url`https://example.com/api/users/${id}/profile` +// => 'https://example.com/api/users/1000/profile' +``` + +配列を渡すと`/`区切りで繋いだURLにするので階層が可変なURLでも安心ですね。 + +```ts +const areaList = ["japan", "tokyo", "shinjuku"]; +url`https://example.com/menu/${areaList}` +// => 'https://example.com/menu/japan/tokyo/shinjuku' +``` + +プロトコル、ポート、クエリーの値を設定する場合に`null`を渡すと、前後の記号やクエリーならキー部分も出力からは消去します。検索条件のクエリーの入った文字列を作るけど、無駄に長くはしたくない時はこういうの欲しくなりますよね?こういうのをきちんとやろうとすると、`URLSearchParams`を使うことになりますが、直接扱うとコードがかなりやりたいことのわりに増えちゃうな、という痒いところに届くようにしてみました。 + +```ts +const word = "spicy food"; +const page = 10; +const perPage = null; // デフォルト値を使うので設定しない +const limit = null; // デフォルト値を使うので設定しない + +url`https://example.com/api/search?word=${word}&page=${page}&perPage=${perPage}&limit=${limit}` +// => 'https://example.com/api/search?word=spicy+food&page=10' +``` + +逆にクエリー部分はZodやReact Hook Formでバリデーションした結果をオブジェクト形式で渡すよ、という場合も多いと思うので、オブジェクトや`URLSearchParams`でまとめて渡せるようにしています。固定のクエリーや他のクエリーのプレースホルダーとマージした結果を作ります。 + +```ts +const searchParams = { + word: "spicy food", + safeSearch: false, + spicyLevel: Infinity, +} + +url`https://example.com/api/search?${searchParams}` +// => 'https://example.com/api/search?word=spicy+food&safeSearch=false&spicyLevel=Infinity' +``` + +URL周りでよくあるユースケースだと、開発環境や本番などで、接続先のホスト部分が変わるよ、というのもあります。あとは、ユーザー名とパスワードはソースコード中にハードコーディングしたくないはずなのでテンプレートリテラルの中には存在することはなさそうということで、この方法でしか設定できないようになっています。 + +```ts +import { customFormatter } from 'url-tidy'; + +const apiUrl = customFormatter({ + hostname: process.env.API_SERVER_HOST, // 'https://localhost:8080' + username: process.env.API_USER, // 'user' + password: process.env.API_PASSWORD, // 'pAssw0rd' + +}) + +const id = 1000; + +apiUrl`https://api-server/api/users/${id}/profile` +// => 'https://user:pAssw0rd@localhost:8080/api/users/1000/profile' +``` + +# 開発環境 + +TypeScriptでライブラリを作るのは、tscを駆使すれば可能ではありますが、配布するならバンドルしたいし、モジュール形式も複数対応しないと、など考えることはたくさんあります。いろんなゼロコンフィグとか設定が少ない便利ツールは雨後の筍のごとくたくさん登場しますが、それらを活用して「設定のメンテには手間をかけない」「新しいことをやりくなったら、すぐに捨てて、別のツールに乗り換え」がフロントエンド周りではベストかな、と思っています。式年遷宮し続ける方式。 + +今回は、[tsdx](https://tsdx.io)、[Viteのライブラリモード](https://vite.dev/guide/build#library-mode)も試してみましたが、前者は依存のツール類がちょっと古くて、最近の高速ツールの恩恵がなさそう、後者は開発サーバー付きでReactとかVueのコンポーネントライブラリ開発なら便利そうだが、今回のような純粋なロジックの開発だと余計なものが多いな、と思い、tsupを選びました。 + +設定はpackage.jsonに直接書く方式で書きましたがこのぐらいで済みました。 + +```json package.json +{ + "tsup": { + "target": "es2020", + "format": [ + "cjs", + "esm" + ], + "entry": [ + "src/index.ts", + "!src/*.spec.ts" + ], + "splitting": false, + "sourcemap": true, + "clean": true, + "dts": true + } +} +``` + +tsup固有要素以外のパッケージ化に必要だった設定はこれぐらいですかね。あとはリポジトリのURLを書いたり、ライセンスを書いたり、バンドルするファイル一覧を書いたり、private: falseにしたり。 + +```json package.json +{ + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "require": "./dist/index.cjs", + "import": "./dist/index.js" + } + }, + "main": "./dist/index.cjs", + "module": "./dist/index.js" +} +``` + +今回はテストランナーはVitestを使いました。Node.jsもDenoもBunも内蔵のテストランナーを押す流れで、そちらを使うと高速という話も見ますが、Deno、BunのNode.js互換性も高くなり、Vitestで書いたテストを3つの環境で実行できました。[GitHub Actionsで3つのテストを実行する](https://github.com/shibukawa/url-tidy/blob/main/.github/workflows/ci.yaml)ようにしています。 + +コードチェックとフォーマッターは最近はBiomeを押す声が多いです。高速ではあるものの、ESLint+Prettierの方が個人的には好きかも。ESLintとPrettierの共存設定も[以前よりもだいぶシンプル](https://github.com/prettier/eslint-config-prettier#installation)ですし、Prettierが何もしなくても対応するEditorConfig対応はBiomeでは明示的に有効にしないといけないとかまああまり手間は変わらないかな、と。 + +# おまけ + +Go版も作りました。Goにはタグ付きテンプレートリテラル構文がないので、PrintfスタイルのAPIで実装しました。 + +* [github.com/shibukawa/urlf](https://github.com/shibukawa/urlf) + +```go +import ( + "github.com/shibukawa/urlf" +) + +urlf.Urlf(`https://example.com/api/users/{}?key1={}&key2={}`, userCode, value1, value2) +``` + +# まとめ + +新しいツールの使い方を知るついでに前々から気になっていた、構造化文字列なのについ文字列結合で作ってしまいがちなURLの組み立てのユーティリティを作ってみました、というお話でした。 + diff --git a/source/images/20250109a/thumbnail.png b/source/images/20250109a/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..085e3ac73a1a813d5a9aef4f12dd47e52083c258 GIT binary patch literal 11188 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 kX5h{_d_-6)=m)>}4Nk}LaM#d)#B2 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