soseki 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.config/_is-debug-mode.ts +9 -0
  2. package/.config/dependency-cruiser.cjs +408 -0
  3. package/.config/env.d.ts +8 -0
  4. package/.config/mise.toml +28 -0
  5. package/.config/navigation-api.d.ts +18 -0
  6. package/.config/tsconfig.build.json +28 -0
  7. package/.config/tsconfig.config.json +21 -0
  8. package/.config/tsconfig.test.json +26 -0
  9. package/.config/tsconfig.web.json +26 -0
  10. package/.config/vitest.client.ts +30 -0
  11. package/package.json +45 -0
  12. package/src/components/action-id.tsx +35 -0
  13. package/src/components/browser-router.tsx +31 -0
  14. package/src/components/hidden-input.tsx +39 -0
  15. package/src/components/outlet.tsx +17 -0
  16. package/src/components/router.tsx +234 -0
  17. package/src/contexts/route-context.ts +21 -0
  18. package/src/contexts/router-context.ts +55 -0
  19. package/src/core/_action-id-registry.ts +11 -0
  20. package/src/core/_capture-stack-trace.ts +12 -0
  21. package/src/core/_compare-route-paths.ts +90 -0
  22. package/src/core/_create-html-form-element-form-form-data.ts +32 -0
  23. package/src/core/_encode-pathname.ts +17 -0
  24. package/src/core/_is-error.ts +16 -0
  25. package/src/core/_is-promise-like.ts +14 -0
  26. package/src/core/_match-route-path.ts +39 -0
  27. package/src/core/_process-routes.ts +56 -0
  28. package/src/core/_singleton.ts +45 -0
  29. package/src/core/_unreachable.ts +22 -0
  30. package/src/core/_use-singleton.ts +24 -0
  31. package/src/core/_valibot.ts +147 -0
  32. package/src/core/_weak-id-registry.ts +125 -0
  33. package/src/core/constants.ts +4 -0
  34. package/src/core/data-map.types.ts +28 -0
  35. package/src/core/data-store.types.ts +25 -0
  36. package/src/core/deferred-promise.ts +408 -0
  37. package/src/core/errors.ts +680 -0
  38. package/src/core/expect-history-entry.ts +95 -0
  39. package/src/core/history-entry-id-schema.ts +27 -0
  40. package/src/core/history-entry-url-schema.ts +35 -0
  41. package/src/core/init-loaders.ts +79 -0
  42. package/src/core/match-routes.ts +91 -0
  43. package/src/core/readonly-form-data.types.ts +63 -0
  44. package/src/core/readonly-url.types.ts +156 -0
  45. package/src/core/redirect-response.ts +36 -0
  46. package/src/core/route-request.ts +92 -0
  47. package/src/core/route.types.ts +351 -0
  48. package/src/core/start-actions.ts +274 -0
  49. package/src/core/start-loaders.ts +254 -0
  50. package/src/core.ts +43 -0
  51. package/src/engines/engine.types.ts +216 -0
  52. package/src/engines/navigation-api-engine.ts +406 -0
  53. package/src/hooks/_use-route-context.ts +19 -0
  54. package/src/hooks/_use-router-context.ts +25 -0
  55. package/src/hooks/use-action-data.ts +37 -0
  56. package/src/hooks/use-loader-data.ts +28 -0
  57. package/src/hooks/use-navigate.ts +64 -0
  58. package/src/hooks/use-params.ts +11 -0
  59. package/src/hooks/use-pathname.ts +10 -0
  60. package/src/hooks/use-submit.ts +111 -0
  61. package/src/soseki.ts +75 -0
  62. package/src/utils/get-action-id.ts +12 -0
  63. package/src/utils/href.ts +17 -0
  64. package/src/utils/redirect.ts +13 -0
  65. package/src/utils/route-index.ts +70 -0
  66. package/src/utils/route-route.ts +111 -0
  67. package/src/utils/set-action-id.ts +14 -0
  68. package/tests/core/_capture-stack-trace.test.ts +46 -0
  69. package/tests/core/_compare-route-paths.test.ts +134 -0
  70. package/tests/core/_encode-pathname.test.ts +77 -0
  71. package/tests/core/_is-error.test.ts +108 -0
  72. package/tests/core/_is-promise-like.test.ts +100 -0
  73. package/tests/core/_match-route-path.test.ts +74 -0
  74. package/tests/core/_process-routes.test.ts +146 -0
  75. package/tests/core/_singleton.test.ts +102 -0
  76. package/tests/core/_unreachable.test.ts +38 -0
  77. package/tests/core/_use-singleton.test.ts +47 -0
  78. package/tests/core/_weak-id-registry.test.ts +137 -0
  79. package/tests/core/deferred-promise.test.ts +218 -0
  80. package/tests/core/expect-history-entry.test.ts +112 -0
  81. package/tests/core/init-loaders.test.ts +172 -0
  82. package/tests/core/match-routes.test.ts +178 -0
  83. package/tests/core/redirect-response.test.ts +36 -0
  84. package/tests/core/route-request.test.ts +93 -0
  85. package/tests/core/start-actions.test.ts +319 -0
  86. package/tests/core/start-loaders.test.ts +276 -0
  87. package/tests/engines/navigation-api-engine.test.ts +162 -0
  88. package/tsconfig.json +7 -0
@@ -0,0 +1,95 @@
1
+ import singleton from "./_singleton.js";
2
+ import * as v from "./_valibot.js";
3
+ import HistoryEntryIdSchema, { type HistoryEntryId } from "./history-entry-id-schema.js";
4
+ import HistoryEntryUrlSchema, { type HistoryEntryUrl } from "./history-entry-url-schema.js";
5
+
6
+ /**
7
+ * 履歴エントリーのバリデーションスキーマを生成、または取得します。
8
+ *
9
+ * 識別子、URL、および 0 以上の整数であるインデックスを持つオブジェクト構造を定義します。
10
+ *
11
+ * @returns 履歴エントリーのスキーマです。
12
+ */
13
+ const HistoryEntrySchema = () => (singleton("HistoryEntrySchema", () => (
14
+ v.object({
15
+ id: HistoryEntryIdSchema(),
16
+ url: v.nullable(HistoryEntryUrlSchema()),
17
+ index: v.pipe(
18
+ v.number(),
19
+ v.safeInteger(),
20
+ v.minValue(0),
21
+ ),
22
+ })
23
+ )));
24
+
25
+ /**
26
+ * 履歴エントリーとして受け入れ可能な入力型の定義です。
27
+ */
28
+ export type HistoryEntryLike = Readonly<v.InferInput<ReturnType<typeof HistoryEntrySchema>>>;
29
+
30
+ /**
31
+ * バリデーション済みの履歴エントリーを表す型定義です。
32
+ */
33
+ export type HistoryEntry = {
34
+ /**
35
+ * 履歴エントリーを一意に識別する ID です。
36
+ */
37
+ readonly id: HistoryEntryId;
38
+
39
+ /**
40
+ * 正規化済みの URL オブジェクトです。
41
+ */
42
+ readonly url: HistoryEntryUrl;
43
+
44
+ /**
45
+ * 0 以上の整数で表される履歴のインデックスです。
46
+ */
47
+ readonly index: number;
48
+ };
49
+
50
+ /**
51
+ * 入力値が履歴エントリーの形式を満たしているか検証します。
52
+ *
53
+ * @param entry 検証対象のオブジェクトです。
54
+ * @returns バリデーション済み、かつ URL が存在する履歴エントリーです。
55
+ */
56
+ function expectHistoryEntry(entry: HistoryEntryLike): HistoryEntry;
57
+
58
+ /**
59
+ * 入力値が履歴エントリーの形式を満たしているか検証します。
60
+ *
61
+ * @param entry 検証対象のオブジェクト、または null 系値です。
62
+ * @returns 検証に成功した場合は履歴エントリーを、入力が null もしくは URL が欠損している場合は null を返します。
63
+ */
64
+ function expectHistoryEntry(entry: HistoryEntryLike | null | undefined): HistoryEntry | null;
65
+
66
+ /**
67
+ * 入力値が履歴エントリーの形式を満たしているか検証します。
68
+ *
69
+ * @param entry 検証対象のデータです。
70
+ * @returns 検証結果に基づく履歴エントリー、または null です。
71
+ */
72
+ function expectHistoryEntry(entry: HistoryEntryLike | null | undefined): HistoryEntry | null {
73
+ if (entry == null) {
74
+ return null;
75
+ }
76
+
77
+ const {
78
+ id,
79
+ url,
80
+ index,
81
+ } = v.expect(HistoryEntrySchema(), entry);
82
+
83
+ // URL が nullable として定義されていますが、この関数では URL が存在することを必須とします。
84
+ if (!url) {
85
+ return null;
86
+ }
87
+
88
+ return {
89
+ id,
90
+ url,
91
+ index,
92
+ };
93
+ }
94
+
95
+ export default expectHistoryEntry;
@@ -0,0 +1,27 @@
1
+ import singleton from "./_singleton.js";
2
+ import * as v from "./_valibot.js";
3
+
4
+ /**
5
+ * 履歴エントリー ID のバリデーションスキーマを作成、または取得します。
6
+ *
7
+ * @returns 履歴エントリー ID のスキーマです。
8
+ */
9
+ const HistoryEntryIdSchema = () => (singleton("HistoryEntryIdSchema", () => (
10
+ v.pipe(
11
+ v.string(),
12
+ v.uuid(),
13
+ v.brand("HistoryEntryId"),
14
+ )
15
+ )));
16
+
17
+ /**
18
+ * 履歴エントリー ID として受け入れ可能な入力型の定義です(バリデーション前の文字列など)。
19
+ */
20
+ export type HistoryEntryIdLike = v.InferInput<ReturnType<typeof HistoryEntryIdSchema>>;
21
+
22
+ /**
23
+ * バリデーション済みでブランド化された、履歴エントリー ID の出力型の定義です。
24
+ */
25
+ export type HistoryEntryId = v.InferOutput<ReturnType<typeof HistoryEntryIdSchema>>;
26
+
27
+ export default HistoryEntryIdSchema;
@@ -0,0 +1,35 @@
1
+ import singleton from "./_singleton.js";
2
+ import * as v from "./_valibot.js";
3
+ import type { ReadonlyURL } from "./readonly-url.types.js";
4
+
5
+ /**
6
+ * 履歴エントリー URL のバリデーションおよび変換スキーマを作成、または取得します。
7
+ *
8
+ * 文字列が有効な URL であるかを確認し、クエリーパラメーターをソートして正規化した `ReadonlyURL` オブジェクトを返します。
9
+ *
10
+ * @returns 履歴エントリー URL のスキーマです。
11
+ */
12
+ const HistoryEntryUrlSchema = () => (singleton("HistoryEntryUrlSchema", () => (
13
+ v.pipe(
14
+ v.string(),
15
+ v.url(),
16
+ v.transform(function createNormalizedUrl(s): ReadonlyURL {
17
+ const u = new URL(s);
18
+ // 同一の URL として比較しやすくするため、クエリーパラメーターを昇順にソートします。
19
+ u.searchParams.sort();
20
+ return u;
21
+ }),
22
+ )
23
+ )));
24
+
25
+ /**
26
+ * 履歴エントリー URL として受け入れ可能な入力型の定義です(バリデーション前の文字列など)。
27
+ */
28
+ export type HistoryEntryUrlLike = v.InferInput<ReturnType<typeof HistoryEntryUrlSchema>>;
29
+
30
+ /**
31
+ * バリデーションおよび正規化が行われた後の、履歴エントリー URL の出力型の定義です。
32
+ */
33
+ export type HistoryEntryUrl = v.InferOutput<ReturnType<typeof HistoryEntryUrlSchema>>;
34
+
35
+ export default HistoryEntryUrlSchema;
@@ -0,0 +1,79 @@
1
+ import type { IDataMap } from "./data-map.types.js";
2
+ import type { IDataStore } from "./data-store.types.js";
3
+ import DeferredPromise from "./deferred-promise.js";
4
+ import type { HistoryEntry } from "./expect-history-entry.js";
5
+ import type { MatchedRoute } from "./match-routes.js";
6
+ import RouteRequest from "./route-request.js";
7
+ import type { ILoader } from "./route.types.js";
8
+
9
+ /**
10
+ * ローダーの初期化に使用するパラメーターの型定義です。
11
+ */
12
+ export type InitLoadersParams = {
13
+ /**
14
+ * マッチしたルート情報のリストです。パラメーターとデータ関数を含みます。
15
+ */
16
+ readonly routes: readonly Pick<MatchedRoute, "params" | "dataFuncs">[];
17
+
18
+ /**
19
+ * 履歴エントリーの情報です。 ID と URL を含みます。
20
+ */
21
+ readonly entry: Pick<HistoryEntry, "id" | "url">;
22
+
23
+ /**
24
+ * データを永続化するためのデータストアです。
25
+ */
26
+ readonly dataStore: IDataStore<ILoader>;
27
+
28
+ /**
29
+ * 非同期処理を中断するためのシグナルです。
30
+ */
31
+ readonly signal: AbortSignal;
32
+ };
33
+
34
+ /**
35
+ * ルートに定義されたローダーを初期化し、実行します。
36
+ *
37
+ * 各ローダーの実行結果はデータストアに格納され、すべての実行開始を待機します。
38
+ *
39
+ * @param params ローダーの初期化に必要なパラメーターオブジェクトです。
40
+ * @returns すべてのローダーの処理が開始(Settled)されるまで待機する Promise です。
41
+ */
42
+ export default function initLoaders(params: InitLoadersParams): {
43
+ (): Promise<void>;
44
+ } {
45
+ const {
46
+ entry,
47
+ routes,
48
+ signal,
49
+ dataStore,
50
+ } = params;
51
+ const dataMap: IDataMap<ILoader> = new Map();
52
+ const request = new RouteRequest("GET", entry.url, signal);
53
+ // 各ルートおよびそのデータ関数に含まれるローダーを走査します。
54
+ for (const route of routes) {
55
+ for (const { loader } of route.dataFuncs) {
56
+ if (!loader) {
57
+ continue;
58
+ }
59
+
60
+ // ローダーの実行を遅延評価としてラップします。
61
+ const data = DeferredPromise.try(function executeLoader() {
62
+ return loader({
63
+ params: route.params,
64
+ request,
65
+ });
66
+ });
67
+ // ローダーの結果を待機、エラーハンドリングする処理は、この結果を参照するコンポーネントに任せます。
68
+ dataMap.set(loader, data);
69
+ }
70
+ }
71
+
72
+ // 生成されたデータマップを履歴エントリーの ID に紐付けて保存します。
73
+ dataStore.set(entry.id, dataMap);
74
+
75
+ return async function waitForLoadersComplete() {
76
+ // すべてのローダーの Promise が確定するまで待機します。
77
+ await Promise.allSettled(dataMap.values());
78
+ };
79
+ }
@@ -0,0 +1,91 @@
1
+ import { inject } from "regexparam";
2
+ import matchRoutePath from "./_match-route-path.js";
3
+ import type { PathParams, Route } from "./route.types.js";
4
+
5
+ /**
6
+ * マッチしたルートの情報に、抽出されたパスパラメーターを統合した型定義です。
7
+ */
8
+ export type MatchedRoute = Pick<Route, "path" | "index" | "dataFuncs" | "component"> & {
9
+ /**
10
+ * パス名から抽出された動的なパラメーターのオブジェクトです。
11
+ */
12
+ readonly params: PathParams;
13
+
14
+ /**
15
+ * ルートのパスパターンに基づく URL のパスです。
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const route = matchRoutes(routes, "/user/123/setting");
20
+ * route.path; // "/user/:id"
21
+ * route.params; // { id: "123" }
22
+ * route.urlPath; // "/user/123"
23
+ * ```
24
+ */
25
+ readonly urlPath: string;
26
+ };
27
+
28
+ /**
29
+ * 単一のルートとその子ルートに対して、再帰的にパスマッチングを試みます。
30
+ *
31
+ * @param route マッチングを確認する対象のルートオブジェクトです。
32
+ * @param pathname マッチング対象のパス名です。
33
+ * @returns マッチした場合は親から子への階層構造を保持した配列を返し、マッチしない場合は `null` を返します。
34
+ */
35
+ function matchRoute(
36
+ route: Route,
37
+ pathname: string,
38
+ ): readonly [MatchedRoute, ...MatchedRoute[]] | null {
39
+ const result = matchRoutePath(route, pathname);
40
+ if (!result) {
41
+ return null;
42
+ }
43
+
44
+ const matched: MatchedRoute = {
45
+ path: route.path,
46
+ index: route.index,
47
+ params: result.params,
48
+ urlPath: inject(route.path, result.params),
49
+ dataFuncs: route.dataFuncs,
50
+ component: route.component,
51
+ };
52
+
53
+ // インデックスルート(末端)の場合は、現在のルートを配列に含めて返します。
54
+ if (route.index) {
55
+ return [matched];
56
+ }
57
+
58
+ // 子ルートの中にマッチするものがあるか探索します。
59
+ for (const childRoute of route.children) {
60
+ const childMathced = matchRoute(childRoute, pathname);
61
+ if (childMathced) {
62
+ return [
63
+ ...childMathced,
64
+ matched,
65
+ ];
66
+ }
67
+ }
68
+
69
+ return [matched];
70
+ }
71
+
72
+ /**
73
+ * ルート定義のリスト全体から、指定されたパス名にマッチするルートを探索します。
74
+ *
75
+ * @param routes 探索対象となるルートオブジェクトの配列です。
76
+ * @param pathname マッチング対象のパス名です。
77
+ * @returns 最初にマッチしたルートとその階層構造を返し、どのルートにもマッチしない場合は `null` を返します。
78
+ */
79
+ export default function matchRoutes(
80
+ routes: readonly Route[],
81
+ pathname: string,
82
+ ): readonly [MatchedRoute, ...MatchedRoute[]] | null {
83
+ for (const route of routes) {
84
+ const matched = matchRoute(route, pathname);
85
+ if (matched) {
86
+ return matched;
87
+ }
88
+ }
89
+
90
+ return null;
91
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * **`ReadonlyFormData`** インターフェースは、フォームフィールドとその値のセットをキーと値のペアで構築する方法を提供します。
3
+ *
4
+ * 構築したデータは、`fetch()`、`XMLHttpRequest.send()`、または `navigator.sendBeacon()` メソッドを使用して送信できます。
5
+ *
6
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData)
7
+ */
8
+ export interface ReadonlyFormData {
9
+ /**
10
+ * ReadonlyFormData インターフェースの **`get()`** メソッドは、`FormData` オブジェクト内にある指定したキーに関連付けられた最初の値を返します。
11
+ *
12
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData/get)
13
+ */
14
+ get(name: string): FormDataEntryValue | null;
15
+
16
+ /**
17
+ * ReadonlyFormData インターフェースの **`getAll()`** メソッドは、`FormData` オブジェクト内にある指定したキーに関連付けられたすべての値を返します。
18
+ *
19
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData/getAll)
20
+ */
21
+ getAll(name: string): FormDataEntryValue[];
22
+
23
+ /**
24
+ * ReadonlyFormData インターフェースの **`has()`** メソッドは、`FormData` オブジェクトに特定のキーが含まれているかどうかを返します。
25
+ *
26
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData/has)
27
+ */
28
+ has(name: string): boolean;
29
+
30
+ /**
31
+ * FormData オブジェクトに含まれるすべてのキーと値のペアに対して、指定されたコールバック関数を一度ずつ実行します。
32
+ */
33
+ forEach(
34
+ callbackfn: (value: FormDataEntryValue, key: string, parent: ReadonlyFormData) => void,
35
+ thisArg?: any,
36
+ ): void;
37
+
38
+ // /**
39
+ // * ReadonlyFormData インターフェースの **`entries()`** メソッドは、このオブジェクトに含まれるすべてのキーと値のペアを順に走査するためのイテレーターを返します。
40
+ // *
41
+ // * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData/entries)
42
+ // */
43
+ // entries(): IterableIterator<[string, FormDataEntryValue]>;
44
+
45
+ // /**
46
+ // * ReadonlyFormData インターフェースの **`keys()`** メソッドは、このオブジェクトに含まれるすべてのキー(name)を順に走査するためのイテレーターを返します。
47
+ // *
48
+ // * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData/keys)
49
+ // */
50
+ // keys(): IterableIterator<string>;
51
+
52
+ // /**
53
+ // * ReadonlyFormData インターフェースの **`values()`** メソッドは、このオブジェクトに含まれるすべての値を順に走査するためのイテレーターを返します。
54
+ // *
55
+ // * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/FormData/values)
56
+ // */
57
+ // values(): IterableIterator<FormDataEntryValue>;
58
+
59
+ // /**
60
+ // * FormData オブジェクトのデフォルトのイテレーターです。これにより `for...of` ループで直接 `entries()` と同様の挙動(キーと値のペアの取得)が可能になります。
61
+ // */
62
+ // [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
63
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * **`ReadonlyURL`** インターフェースは、URL の解析、構築、正規化、およびエンコードを行うために使用されます。
3
+ *
4
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL)
5
+ */
6
+ export interface ReadonlyURL {
7
+ /**
8
+ * ReadonlyURL インターフェースの **`hash`** プロパティーは、"#" とそれに続く ReadonlyURL のフラグメント識別子を含む文字列です。
9
+ *
10
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/hash)
11
+ */
12
+ readonly hash: string;
13
+
14
+ /**
15
+ * ReadonlyURL インターフェースの **`host`** プロパティーは、ホスト(`ReadonlyURL.hostname`)と、URL のポートが空でない場合は ":" に続くポート(`ReadonlyURL.port`)を含む文字列です。
16
+ *
17
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/host)
18
+ */
19
+ readonly host: string;
20
+
21
+ /**
22
+ * ReadonlyURL インターフェースの **`hostname`** プロパティーは、URL のドメイン名または IP アドレスを含む文字列です。
23
+ *
24
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/hostname)
25
+ */
26
+ readonly hostname: string;
27
+
28
+ /**
29
+ * ReadonlyURL インターフェースの **`href`** プロパティーは、URL 全体を含む文字列です。
30
+ *
31
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/href)
32
+ */
33
+ readonly href: string;
34
+
35
+ /**
36
+ * ReadonlyURL インターフェースの **`toString()`** メソッドは、URL をシリアライズした文字列を返します。実際には `ReadonlyURL.href` と同じ値を返します。
37
+ *
38
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/toString)
39
+ */
40
+ toString(): string;
41
+
42
+ /**
43
+ * ReadonlyURL インターフェースの **`origin`** プロパティーは、対象となる ReadonlyURL のオリジンを Unicode 形式でシリアライズした文字列を返します。
44
+ *
45
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/origin)
46
+ */
47
+ readonly origin: string;
48
+
49
+ /**
50
+ * ReadonlyURL インターフェースの **`password`** プロパティーは、URL のパスワード成分を含む文字列です。
51
+ *
52
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/password)
53
+ */
54
+ readonly password: string;
55
+
56
+ /**
57
+ * ReadonlyURL インターフェースの **`pathname`** プロパティーは、階層構造における場所を表します。
58
+ *
59
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/pathname)
60
+ */
61
+ readonly pathname: string;
62
+
63
+ /**
64
+ * ReadonlyURL インターフェースの **`port`** プロパティーは、URL のポート番号を含む文字列です。
65
+ *
66
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/port)
67
+ */
68
+ readonly port: string;
69
+
70
+ /**
71
+ * ReadonlyURL インターフェースの **`protocol`** プロパティーは、末尾の ":" を含む、URL のプロトコルまたはスキームを示す文字列です。
72
+ *
73
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/protocol)
74
+ */
75
+ readonly protocol: string;
76
+
77
+ /**
78
+ * ReadonlyURL インターフェースの **`search`** プロパティーは、検索文字列(またはクエリー文字列)です。これは、"?" とそれに続く ReadonlyURL のパラメーターを含む文字列です。
79
+ *
80
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/search)
81
+ */
82
+ readonly search: string;
83
+
84
+ /**
85
+ * ReadonlyURL インターフェースの **`searchParams`** プロパティーは、URL に含まれるクエリー引数をデコードして扱うための `ReadonlyURLSearchParams` オブジェクトへのアクセスを提供します。
86
+ *
87
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/searchParams)
88
+ */
89
+ readonly searchParams: ReadonlyURLSearchParams;
90
+
91
+ /**
92
+ * ReadonlyURL インターフェースの **`username`** プロパティーは、URL のユーザー名成分を含む文字列です。
93
+ *
94
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/username)
95
+ */
96
+ readonly username: string;
97
+
98
+ /**
99
+ * ReadonlyURL インターフェースの **`toJSON()`** メソッドは、URL をシリアライズした文字列を返します。実際には `ReadonlyURL.href` と同じ値を返します。
100
+ *
101
+ * [MDN リファレンス](https://developer.mozilla.org/docs/Web/API/URL/toJSON)
102
+ */
103
+ toJSON(): string;
104
+ }
105
+
106
+ /**
107
+ * **`ReadonlyURLSearchParams`** インターフェースは、URLのクエリー文字列を操作するための便利なメソッドを定義します。
108
+ *
109
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams)
110
+ */
111
+ export interface ReadonlyURLSearchParams {
112
+ /**
113
+ * ReadonlyURLSearchParams インターフェースの **`size`** プロパティーは、検索パラメーターのエントリーの総数を示します。
114
+ *
115
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams/size)
116
+ */
117
+ readonly size: number;
118
+
119
+ /**
120
+ * ReadonlyURLSearchParams インターフェースの **`get()`** メソッドは、指定された検索パラメーターに関連付けられた最初の値を返します。
121
+ *
122
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams/get)
123
+ */
124
+ get(name: string): string | null;
125
+
126
+ /**
127
+ * ReadonlyURLSearchParams インターフェースの **`getAll()`** メソッドは、指定された検索パラメーターに関連付けられたすべての値を配列として返します。
128
+ *
129
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams/getAll)
130
+ */
131
+ getAll(name: string): string[];
132
+
133
+ /**
134
+ * ReadonlyURLSearchParams インターフェースの **`has()`** メソッドは、指定されたパラメーターが検索パラメーターに含まれているかどうかを示す論理値を返します。
135
+ *
136
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams/has)
137
+ */
138
+ has(name: string, value?: string): boolean;
139
+
140
+ /**
141
+ * ReadonlyURLSearchParams インターフェースの **`toString()`** メソッドは、URL で使用できるクエリー文字列(先頭の "?" を除く)を返します。
142
+ *
143
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams/toString)
144
+ */
145
+ toString(): string;
146
+
147
+ /**
148
+ * ReadonlyURLSearchParams インターフェースの **`forEach()`** メソッドは、このオブジェクト内に存在する各値に対して、渡されたコールバック関数を一度ずつ実行します。
149
+ *
150
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/URLSearchParams/forEach)
151
+ */
152
+ forEach(
153
+ callbackfn: (value: string, key: string, parent: ReadonlyURLSearchParams) => void,
154
+ thisArg?: any,
155
+ ): void;
156
+ }
@@ -0,0 +1,36 @@
1
+ import encodePathname from "./_encode-pathname.js";
2
+
3
+ /**
4
+ * リダイレクトの識別子として使用されるユニークなシンボルです。
5
+ */
6
+ declare const ID: unique symbol;
7
+
8
+ /**
9
+ * リダイレクトレスポンスを表現するクラスです。
10
+ *
11
+ * 指定されたパス名をエンコードして保持します。
12
+ */
13
+ export default class RedirectResponse {
14
+ /**
15
+ * クラスを識別するためのユニークな ID です。
16
+ *
17
+ * @internal
18
+ */
19
+ // @ts-expect-error
20
+ public readonly ID: typeof ID;
21
+
22
+ /**
23
+ * エンコード済みのリダイレクト先パス名です。
24
+ */
25
+ public readonly pathname: string;
26
+
27
+ /**
28
+ * RedirectResponse クラスの新しいインスタンスを初期化します。
29
+ *
30
+ * @param pathname リダイレクト先のパス名です。
31
+ */
32
+ public constructor(pathname: string) {
33
+ // パス名を適切な形式にエンコードして格納します。
34
+ this.pathname = encodePathname(pathname);
35
+ }
36
+ }
@@ -0,0 +1,92 @@
1
+ import type { ReadonlyFormData } from "./readonly-form-data.types.js";
2
+ import type { ReadonlyURL } from "./readonly-url.types.js";
3
+
4
+ /**
5
+ * ルーティングのリクエスト情報を管理するクラスです。
6
+ */
7
+ export default class RouteRequest {
8
+ /**
9
+ * HTTP メソッドです。 "GET" または "POST" のいずれかとなります。
10
+ */
11
+ public readonly method: "GET" | "POST";
12
+
13
+ /**
14
+ * リクエスト先の URL です。
15
+ *
16
+ * インスタンス化の際に検索パラメーターがソートされた状態で保持されます。
17
+ */
18
+ public readonly url: ReadonlyURL;
19
+
20
+ /**
21
+ * リクエストのキャンセルや中断を監視するための信号です。
22
+ */
23
+ public readonly signal: AbortSignal;
24
+
25
+ /**
26
+ * 送信されたフォームデータです。
27
+ *
28
+ * データが存在しない場合は `null` となります。
29
+ */
30
+ public readonly formData: ReadonlyFormData | null;
31
+
32
+ /**
33
+ * RouteRequest クラスの新しいインスタンスを初期化します。
34
+ *
35
+ * @param method 使用する HTTP メソッドです。
36
+ * @param url リクエスト対象の URL オブジェクトです。
37
+ * @param signal 処理を中断するための AbortSignal オブジェクトです。
38
+ */
39
+ public constructor(
40
+ method: "GET",
41
+ url: ReadonlyURL,
42
+ signal: AbortSignal,
43
+ );
44
+
45
+ /**
46
+ * RouteRequest クラスの新しいインスタンスを初期化します。
47
+ *
48
+ * @param method 使用する HTTP メソッドです。
49
+ * @param url リクエスト対象の URL オブジェクトです。
50
+ * @param signal 処理を中断するための AbortSignal オブジェクトです。
51
+ * @param formData 送信するフォームデータです。
52
+ */
53
+ public constructor(
54
+ method: "POST",
55
+ url: ReadonlyURL,
56
+ signal: AbortSignal,
57
+ formData: ReadonlyFormData,
58
+ );
59
+
60
+ public constructor(
61
+ method: "GET" | "POST",
62
+ url: ReadonlyURL,
63
+ signal: AbortSignal,
64
+ formData?: ReadonlyFormData,
65
+ ) {
66
+ this.url = url;
67
+ this.method = method;
68
+ this.signal = signal;
69
+ this.formData = formData || null;
70
+ }
71
+
72
+ /**
73
+ * 現在のプロパティーを基に、標準の Request オブジェクトを生成して返します。
74
+ *
75
+ * @param init リクエストに適用したいカスタム設定です。
76
+ * @returns fetch API などで使用可能な Request オブジェクトを返します。
77
+ */
78
+ public toRequest(init: RequestInit | undefined = {}): Request {
79
+ const {
80
+ body = this.formData as FormData | null,
81
+ method = this.method,
82
+ signal = this.signal,
83
+ ...other
84
+ } = init;
85
+ return new Request(this.url.href, {
86
+ body,
87
+ method,
88
+ signal,
89
+ ...other,
90
+ });
91
+ }
92
+ }