blog.bouzuya.net

2017-03-04 bath をつかった router の bouzuya/spa-town 0.1.2 をつくった

bouzuya/spa-town 0.1.0 0.1.1 0.1.2 をつくった。

spa-town は bouzuya/bath を基にしたシンプルなルーターだ。paramsFn ごとに name をつけた route pattern をつくっておき、複数の route pattern を並べて router にする。 router は path に対応する nameparams を返すようになっている。どれにも当てはまらないときは事前に設定された既定値を返す。

コード例は次のとおりだ。

import * as assert from 'assert';
import { result, route, router } from 'spa-town';

const router1 = router([
  route('root#index', '/'),
  route('users#index', '/users'),
  route('users#index', '/users/'),
  route('users#show', '/users/{id}', { id: /^\w+$/ }),
  route('users#show', '/users/{id}/', { id: /^\w+$/ })
], result('root#notfound', {}));

assert.deepEqual(router1('/'), result('root#index', {}));
assert.deepEqual(router1('/users'), result('users#index', {}));
assert.deepEqual(router1('/users/'), result('users#index', {}));
assert.deepEqual(router1('/users/123'), result('users#show', { id: '123' }));
assert.deepEqual(router1('/users/123/'), result('users#show', { id: '123' }));
assert.deepEqual(router1('/no-match'), result('root#notfound', {}));

bath の活用例になっている。一度は bath の examples/ に入れたのだけど、何かに使ってみたくなり、リポジトリを分けて npm package を公開した。

bath よりも実際のアプリケーションにありそうな形になっているはずだ。 path を解釈して、対応する name と params を返す。対応するものを選ぶあたりが routing ……と言っていいのかな。 router の範囲はさまざまだが、わりと小さい範囲に留めたつもりだ。

末尾 / のために別の route を用意しないといけないあたりは、最終的な利便性よりも学習性を採っている。ほかにも大文字小文字の区別や、 directory ごとの入れ子構造などを取りたい可能性もありそうだが、捨てている。 server-side を考えると method も判定に含めたいかもしれない。

入れ子構造はわりと欲しい気がするのだけど、優先順位が複雑になりそうなので避けている。現状は単純な Array なので上から順に見て、なければ default という単純な挙動だ。

上記のような要望やあるいは他の要望も、必要に応じて変更するかもしれないし、別物としてつくるかもしれない。これくらいならアプリケーションごとに実装しても良いとは思うので、無理にこれを使う必要はない。