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.
- package/.config/_is-debug-mode.ts +9 -0
- package/.config/dependency-cruiser.cjs +408 -0
- package/.config/env.d.ts +8 -0
- package/.config/mise.toml +28 -0
- package/.config/navigation-api.d.ts +18 -0
- package/.config/tsconfig.build.json +28 -0
- package/.config/tsconfig.config.json +21 -0
- package/.config/tsconfig.test.json +26 -0
- package/.config/tsconfig.web.json +26 -0
- package/.config/vitest.client.ts +30 -0
- package/package.json +45 -0
- package/src/components/action-id.tsx +35 -0
- package/src/components/browser-router.tsx +31 -0
- package/src/components/hidden-input.tsx +39 -0
- package/src/components/outlet.tsx +17 -0
- package/src/components/router.tsx +234 -0
- package/src/contexts/route-context.ts +21 -0
- package/src/contexts/router-context.ts +55 -0
- package/src/core/_action-id-registry.ts +11 -0
- package/src/core/_capture-stack-trace.ts +12 -0
- package/src/core/_compare-route-paths.ts +90 -0
- package/src/core/_create-html-form-element-form-form-data.ts +32 -0
- package/src/core/_encode-pathname.ts +17 -0
- package/src/core/_is-error.ts +16 -0
- package/src/core/_is-promise-like.ts +14 -0
- package/src/core/_match-route-path.ts +39 -0
- package/src/core/_process-routes.ts +56 -0
- package/src/core/_singleton.ts +45 -0
- package/src/core/_unreachable.ts +22 -0
- package/src/core/_use-singleton.ts +24 -0
- package/src/core/_valibot.ts +147 -0
- package/src/core/_weak-id-registry.ts +125 -0
- package/src/core/constants.ts +4 -0
- package/src/core/data-map.types.ts +28 -0
- package/src/core/data-store.types.ts +25 -0
- package/src/core/deferred-promise.ts +408 -0
- package/src/core/errors.ts +680 -0
- package/src/core/expect-history-entry.ts +95 -0
- package/src/core/history-entry-id-schema.ts +27 -0
- package/src/core/history-entry-url-schema.ts +35 -0
- package/src/core/init-loaders.ts +79 -0
- package/src/core/match-routes.ts +91 -0
- package/src/core/readonly-form-data.types.ts +63 -0
- package/src/core/readonly-url.types.ts +156 -0
- package/src/core/redirect-response.ts +36 -0
- package/src/core/route-request.ts +92 -0
- package/src/core/route.types.ts +351 -0
- package/src/core/start-actions.ts +274 -0
- package/src/core/start-loaders.ts +254 -0
- package/src/core.ts +43 -0
- package/src/engines/engine.types.ts +216 -0
- package/src/engines/navigation-api-engine.ts +406 -0
- package/src/hooks/_use-route-context.ts +19 -0
- package/src/hooks/_use-router-context.ts +25 -0
- package/src/hooks/use-action-data.ts +37 -0
- package/src/hooks/use-loader-data.ts +28 -0
- package/src/hooks/use-navigate.ts +64 -0
- package/src/hooks/use-params.ts +11 -0
- package/src/hooks/use-pathname.ts +10 -0
- package/src/hooks/use-submit.ts +111 -0
- package/src/soseki.ts +75 -0
- package/src/utils/get-action-id.ts +12 -0
- package/src/utils/href.ts +17 -0
- package/src/utils/redirect.ts +13 -0
- package/src/utils/route-index.ts +70 -0
- package/src/utils/route-route.ts +111 -0
- package/src/utils/set-action-id.ts +14 -0
- package/tests/core/_capture-stack-trace.test.ts +46 -0
- package/tests/core/_compare-route-paths.test.ts +134 -0
- package/tests/core/_encode-pathname.test.ts +77 -0
- package/tests/core/_is-error.test.ts +108 -0
- package/tests/core/_is-promise-like.test.ts +100 -0
- package/tests/core/_match-route-path.test.ts +74 -0
- package/tests/core/_process-routes.test.ts +146 -0
- package/tests/core/_singleton.test.ts +102 -0
- package/tests/core/_unreachable.test.ts +38 -0
- package/tests/core/_use-singleton.test.ts +47 -0
- package/tests/core/_weak-id-registry.test.ts +137 -0
- package/tests/core/deferred-promise.test.ts +218 -0
- package/tests/core/expect-history-entry.test.ts +112 -0
- package/tests/core/init-loaders.test.ts +172 -0
- package/tests/core/match-routes.test.ts +178 -0
- package/tests/core/redirect-response.test.ts +36 -0
- package/tests/core/route-request.test.ts +93 -0
- package/tests/core/start-actions.test.ts +319 -0
- package/tests/core/start-loaders.test.ts +276 -0
- package/tests/engines/navigation-api-engine.test.ts +162 -0
- package/tsconfig.json +7 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import unreachable from "./_unreachable.js";
|
|
2
|
+
import type { IDataMap, IReadonlyDataMap } from "./data-map.types.js";
|
|
3
|
+
import type { IDataStore } from "./data-store.types.js";
|
|
4
|
+
import DeferredPromise from "./deferred-promise.js";
|
|
5
|
+
import { LoaderConditionError } from "./errors.js";
|
|
6
|
+
import type { HistoryEntry } from "./expect-history-entry.js";
|
|
7
|
+
import type { MatchedRoute } from "./match-routes.js";
|
|
8
|
+
import RouteRequest from "./route-request.js";
|
|
9
|
+
import type { IAction, ILoader, ShouldReloadArgs } from "./route.types.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `startLoaders` 関数に渡すパラメーターの型定義です。
|
|
13
|
+
*/
|
|
14
|
+
export type StartLoadersParams =
|
|
15
|
+
& {
|
|
16
|
+
/**
|
|
17
|
+
* 直前のルート情報の配列です。初回遷移時は `null` になります。
|
|
18
|
+
*/
|
|
19
|
+
readonly prevRoutes: readonly Pick<MatchedRoute, "path" | "params">[] | null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 現在の遷移先ルート情報の配列です。
|
|
23
|
+
*/
|
|
24
|
+
readonly currentRoutes: readonly Pick<MatchedRoute, "path" | "params" | "dataFuncs">[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 直前の履歴エントリー情報です。
|
|
28
|
+
*/
|
|
29
|
+
readonly prevEntry: Pick<HistoryEntry, "id" | "url">;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 現在の履歴エントリー情報です。
|
|
33
|
+
*/
|
|
34
|
+
readonly currentEntry: Pick<HistoryEntry, "id" | "url">;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* アクションの実行結果を保持するデータストアーです。
|
|
38
|
+
*/
|
|
39
|
+
readonly actionDataStore: IDataStore<IAction>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* ローダーの実行結果を保持するデータストアーです。
|
|
43
|
+
*/
|
|
44
|
+
readonly loaderDataStore: IDataStore<ILoader>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 非同期処理を中断するためのシグナルです。
|
|
48
|
+
*/
|
|
49
|
+
readonly signal: AbortSignal;
|
|
50
|
+
}
|
|
51
|
+
& ({
|
|
52
|
+
/**
|
|
53
|
+
* 送信されたフォームデータです。
|
|
54
|
+
*/
|
|
55
|
+
readonly formData: FormData;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* アクションの実行結果を格納したマップです。
|
|
59
|
+
*/
|
|
60
|
+
readonly actionResultMap: IReadonlyDataMap<IAction, unknown>;
|
|
61
|
+
} | {
|
|
62
|
+
/**
|
|
63
|
+
* フォームデータが存在しないことを示します。
|
|
64
|
+
*/
|
|
65
|
+
readonly formData?: undefined;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* アクション結果マップが存在しないことを示します。
|
|
69
|
+
*/
|
|
70
|
+
readonly actionResultMap?: undefined;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* ルートに紐付くローダーの実行を開始し、データの同期や再読み込みの判定を行います。
|
|
75
|
+
*
|
|
76
|
+
* @param params ローダーの開始に必要なパラメーターオブジェクトです。
|
|
77
|
+
* @returns すべてのローダーの完了を待機する非同期関数を返します。ローダーが不要な場合は `undefined` を返します。
|
|
78
|
+
*/
|
|
79
|
+
export default function startLoaders(params: StartLoadersParams): undefined | {
|
|
80
|
+
/**
|
|
81
|
+
* 実行中のすべてのローダーが完了するまで待機します。
|
|
82
|
+
*/
|
|
83
|
+
(): Promise<void>;
|
|
84
|
+
} {
|
|
85
|
+
const {
|
|
86
|
+
signal,
|
|
87
|
+
prevEntry,
|
|
88
|
+
prevRoutes,
|
|
89
|
+
currentEntry,
|
|
90
|
+
currentRoutes,
|
|
91
|
+
actionDataStore,
|
|
92
|
+
loaderDataStore,
|
|
93
|
+
...options
|
|
94
|
+
} = params;
|
|
95
|
+
// ローダーの実行前にアクションが実行された場合、その情報を使ってローダーの処理を分岐させます。
|
|
96
|
+
const actionContext = options.formData && {
|
|
97
|
+
formData: options.formData,
|
|
98
|
+
resultMap: options.actionResultMap,
|
|
99
|
+
};
|
|
100
|
+
// prevRoutes は「子ルート」->「親ルート」の順で並んでいるので、最初の要素がすべてのルートのパラメーターを保持しています。
|
|
101
|
+
const prevParams = prevRoutes?.[0]?.params || {};
|
|
102
|
+
const prevRoutePathSet: ReadonlySet<string> = new Set(prevRoutes?.map(r => r.path));
|
|
103
|
+
const prevActionDataMap: IReadonlyDataMap<IAction> | undefined = actionDataStore
|
|
104
|
+
.get(prevEntry.id);
|
|
105
|
+
const prevLoaderDataMap: IReadonlyDataMap<ILoader> | undefined = loaderDataStore
|
|
106
|
+
.get(prevEntry.id);
|
|
107
|
+
const currentActionDataIncMap: IDataMap<IAction> = new Map();
|
|
108
|
+
const currentLoaderDataIncMap: IDataMap<ILoader> = new Map();
|
|
109
|
+
const request = new RouteRequest("GET", currentEntry.url, signal);
|
|
110
|
+
|
|
111
|
+
// 各ルートおよびルートに定義されたデータ関数(action/loader)を走査します。
|
|
112
|
+
for (const currentRoute of currentRoutes) {
|
|
113
|
+
for (const { action, loader, shouldReload } of currentRoute.dataFuncs) {
|
|
114
|
+
if (actionContext && action) {
|
|
115
|
+
const prevActionData = prevActionDataMap?.get(action);
|
|
116
|
+
if (prevActionData) {
|
|
117
|
+
// 遷移前のアクションデータを引き継ぐことで、アクションの結果に応じて変更された描画内容を表示させ続けることができます。
|
|
118
|
+
currentActionDataIncMap.set(action, prevActionData);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!loader) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const prevLoaderData = prevLoaderDataMap?.get(loader);
|
|
127
|
+
if (!prevLoaderData) {
|
|
128
|
+
// 遷移前のローダーデータがない場合、新規ルートの描画と判定して、強制ロードします。
|
|
129
|
+
// ローダーの実行を遅延評価としてラップします。
|
|
130
|
+
const data = DeferredPromise.try(function executeLoader() {
|
|
131
|
+
return loader({
|
|
132
|
+
params: currentRoute.params,
|
|
133
|
+
request,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
// ローダーの結果を待機、エラーハンドリングする処理は、この結果を参照するコンポーネントに任せます。
|
|
137
|
+
currentLoaderDataIncMap.set(loader, data);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// リロードすべきかどうかを判定します。
|
|
142
|
+
const should = DeferredPromise.try(function executeShouldReload() {
|
|
143
|
+
if (!actionContext) {
|
|
144
|
+
// 通常の GET 遷移時の再読み込み判定引数を構築します。
|
|
145
|
+
return shouldReload({
|
|
146
|
+
prevUrl: prevEntry.url,
|
|
147
|
+
currentUrl: currentEntry.url,
|
|
148
|
+
prevParams,
|
|
149
|
+
currentParams: currentRoute.params,
|
|
150
|
+
triggerMethod: "GET",
|
|
151
|
+
defaultShouldReload: !prevRoutePathSet.has(currentRoute.path),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 特定のアクションが実行された後の再読み込み判定引数を構築します。
|
|
156
|
+
const {
|
|
157
|
+
formData,
|
|
158
|
+
resultMap,
|
|
159
|
+
} = actionContext;
|
|
160
|
+
let shouldArgs: ShouldReloadArgs = {
|
|
161
|
+
prevUrl: prevEntry.url,
|
|
162
|
+
formData,
|
|
163
|
+
currentUrl: prevEntry.url,
|
|
164
|
+
prevParams,
|
|
165
|
+
currentParams: currentRoute.params,
|
|
166
|
+
triggerMethod: "POST",
|
|
167
|
+
defaultShouldReload: resultMap.size > 0,
|
|
168
|
+
};
|
|
169
|
+
if (action && resultMap.has(action)) {
|
|
170
|
+
// アクションの結果があるときのみプロパティーを設定します。
|
|
171
|
+
shouldArgs.actionResult = resultMap.get(action);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return shouldReload(shouldArgs);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
let data: DeferredPromise<unknown>;
|
|
178
|
+
switch (should.status) {
|
|
179
|
+
case "pending": {
|
|
180
|
+
// shouldReload は同期的に真偽値を返す必要があるので、pending 状態(つまり非同期)であってはいけません。
|
|
181
|
+
const error = new LoaderConditionError(request.url.href, shouldReload, should);
|
|
182
|
+
// エラーハンドリングは、このローダーデータを参照するコンポーネントに任せます。
|
|
183
|
+
data = DeferredPromise.reject(error);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
case "rejected":
|
|
188
|
+
// エラーハンドリングは、このアクションデータを参照するコンポーネントに任せます。
|
|
189
|
+
data = should;
|
|
190
|
+
break;
|
|
191
|
+
|
|
192
|
+
case "fulfilled": {
|
|
193
|
+
const { value } = should;
|
|
194
|
+
switch (value) {
|
|
195
|
+
case true:
|
|
196
|
+
// 条件を満たす場合のみ、ローダーの実行をスケジュールします。
|
|
197
|
+
data = DeferredPromise.try(function executeLoader() {
|
|
198
|
+
return loader({
|
|
199
|
+
params: currentRoute.params,
|
|
200
|
+
request,
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
break;
|
|
204
|
+
|
|
205
|
+
case false:
|
|
206
|
+
// 再読み込みが不要な場合は、前回のデータを引き継ぎま
|
|
207
|
+
data = prevLoaderData;
|
|
208
|
+
break;
|
|
209
|
+
|
|
210
|
+
default: {
|
|
211
|
+
// shouldReload が真偽値を返さなかった場合、エラーとします。
|
|
212
|
+
const error = new LoaderConditionError(request.url.href, shouldReload, value);
|
|
213
|
+
// エラーハンドリングは、このローダーデータを参照するコンポーネントに任せます。
|
|
214
|
+
data = DeferredPromise.reject(error);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
default:
|
|
222
|
+
unreachable(should);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
currentLoaderDataIncMap.set(loader, data);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// アクションデータの更新処理です。
|
|
230
|
+
if (actionContext) {
|
|
231
|
+
const dataMap = actionDataStore.get(currentEntry.id);
|
|
232
|
+
if (dataMap) {
|
|
233
|
+
for (const [action, data] of currentActionDataIncMap) {
|
|
234
|
+
dataMap.set(action, data);
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
actionDataStore.set(currentEntry.id, currentActionDataIncMap);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// ローダーデータの更新処理です。
|
|
242
|
+
const dataMap = loaderDataStore.get(currentEntry.id);
|
|
243
|
+
if (dataMap) {
|
|
244
|
+
for (const [loader, data] of currentLoaderDataIncMap) {
|
|
245
|
+
dataMap.set(loader, data);
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
loaderDataStore.set(currentEntry.id, currentLoaderDataIncMap);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return async function waitForLoadersComplete() {
|
|
252
|
+
await Promise.allSettled(currentLoaderDataIncMap.values());
|
|
253
|
+
};
|
|
254
|
+
}
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export { default as Router } from "./components/outlet.jsx";
|
|
2
|
+
export type * from "./components/router.jsx";
|
|
3
|
+
|
|
4
|
+
export type * from "./contexts/route-context.js";
|
|
5
|
+
export { default as RouteContext } from "./contexts/route-context.js";
|
|
6
|
+
|
|
7
|
+
export type * from "./contexts/router-context.js";
|
|
8
|
+
export { default as RouterContext } from "./contexts/router-context.js";
|
|
9
|
+
|
|
10
|
+
export { ACTION_ID_FORM_DATA_NAME } from "./core/constants.js";
|
|
11
|
+
|
|
12
|
+
export type * from "./core/data-map.types.js";
|
|
13
|
+
|
|
14
|
+
export type * from "./core/data-store.types.js";
|
|
15
|
+
|
|
16
|
+
export type * from "./core/expect-history-entry.js";
|
|
17
|
+
export { default as expectHistoryEntry } from "./core/expect-history-entry.js";
|
|
18
|
+
|
|
19
|
+
export type * from "./core/history-entry-id-schema.js";
|
|
20
|
+
export { default as HistoryEntryIdSchema } from "./core/history-entry-id-schema.js";
|
|
21
|
+
|
|
22
|
+
export type * from "./core/history-entry-url-schema.js";
|
|
23
|
+
export { default as HistoryEntryUrlSchema } from "./core/history-entry-url-schema.js";
|
|
24
|
+
|
|
25
|
+
export type * from "./core/init-loaders.js";
|
|
26
|
+
export { default as initLoaders } from "./core/init-loaders.js";
|
|
27
|
+
|
|
28
|
+
export type * from "./core/match-routes.js";
|
|
29
|
+
export { default as matchRoutes } from "./core/match-routes.js";
|
|
30
|
+
|
|
31
|
+
export type * from "./core/redirect-response.js";
|
|
32
|
+
export { default as RedirectResponse } from "./core/redirect-response.js";
|
|
33
|
+
|
|
34
|
+
export type * from "./core/start-actions.js";
|
|
35
|
+
export { default as startActions } from "./core/start-actions.js";
|
|
36
|
+
|
|
37
|
+
export type * from "./core/start-loaders.js";
|
|
38
|
+
export { default as startLoaders } from "./core/start-loaders.js";
|
|
39
|
+
|
|
40
|
+
export type * from "./engines/engine.types.js";
|
|
41
|
+
|
|
42
|
+
export type * from "./engines/navigation-api-engine.js";
|
|
43
|
+
export { default as NavigationApiEngine } from "./engines/navigation-api-engine.js";
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import type { IDataStore } from "../core/data-store.types.js";
|
|
2
|
+
import type { HistoryEntry } from "../core/expect-history-entry.js";
|
|
3
|
+
import type { MatchedRoute } from "../core/match-routes.js";
|
|
4
|
+
import type { ReadonlyFormData } from "../core/readonly-form-data.types.js";
|
|
5
|
+
import type { ReadonlyURLSearchParams } from "../core/readonly-url.types.js";
|
|
6
|
+
import type { IAction, ILoader, Route } from "../core/route.types.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ルーターの初期状態を生成する際に必要な引数の型定義です。
|
|
10
|
+
*/
|
|
11
|
+
export type InitEngineArgs = {
|
|
12
|
+
/**
|
|
13
|
+
* 前処理済みのルート定義の配列です。
|
|
14
|
+
*/
|
|
15
|
+
readonly routes: readonly Route[];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 現在の非同期処理を中断するためのシグナルを取得する関数です。
|
|
19
|
+
*/
|
|
20
|
+
readonly getSignal: () => AbortSignal;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* ロケーション ID ごとに管理されているローダーデータのマップです。
|
|
24
|
+
*/
|
|
25
|
+
readonly loaderDataStore: IDataStore<ILoader>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* ルーターの現在の状態を表す型定義です。
|
|
30
|
+
*/
|
|
31
|
+
export type RouterState = {
|
|
32
|
+
/**
|
|
33
|
+
* 現在のロケーションエントリー情報です。
|
|
34
|
+
*/
|
|
35
|
+
readonly entry: HistoryEntry;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 現在の URL にマッチしたルートの階層構造です。
|
|
39
|
+
*
|
|
40
|
+
* 最低でも 1 つのマッチしたルートが含まれるタプル形式となります。
|
|
41
|
+
*/
|
|
42
|
+
readonly routes: readonly [MatchedRoute, ...MatchedRoute[]];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* ルーターの状態を更新するための関数インターフェースです。
|
|
47
|
+
*/
|
|
48
|
+
export interface IUpdateRouter {
|
|
49
|
+
/**
|
|
50
|
+
* システムの状態を更新します。
|
|
51
|
+
*/
|
|
52
|
+
(): void;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 新しいルーターの状態を受け取り、システムの状態を更新します。
|
|
56
|
+
*
|
|
57
|
+
* @param state 新しいルーターの状態オブジェクトです。
|
|
58
|
+
*/
|
|
59
|
+
(state: RouterState | null): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* ルーターエンジンを開始する際に必要な引数の型定義です。
|
|
64
|
+
*/
|
|
65
|
+
export type StartEngineArgs = {
|
|
66
|
+
/**
|
|
67
|
+
* 前処理済みのルート定義の配列です。
|
|
68
|
+
*/
|
|
69
|
+
readonly routes: readonly Route[];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 状態を更新するためのセッター関数です。
|
|
73
|
+
*/
|
|
74
|
+
readonly update: IUpdateRouter;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 現在の非同期処理を中断するためのシグナルを取得する関数です。
|
|
78
|
+
*/
|
|
79
|
+
readonly getSignal: () => AbortSignal;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* ロケーション ID ごとに管理されているアクションデータのマップです。
|
|
83
|
+
*/
|
|
84
|
+
readonly actionDataStore: IDataStore<IAction>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* ロケーション ID ごとに管理されているローダーデータのマップです。
|
|
88
|
+
*/
|
|
89
|
+
readonly loaderDataStore: IDataStore<ILoader>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* エンジンの動作を停止するための関数インターフェースです。
|
|
94
|
+
*/
|
|
95
|
+
export interface IStopEngine {
|
|
96
|
+
/**
|
|
97
|
+
* 実行中のエンジンを停止し、イベントリスナーの解除などのクリーンアップを行います。
|
|
98
|
+
*/
|
|
99
|
+
(): void;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 送信処理に渡される引数の型定義です。
|
|
104
|
+
*/
|
|
105
|
+
export type SubmitArgs = {
|
|
106
|
+
/**
|
|
107
|
+
* 送信対象となるフォームデータです。
|
|
108
|
+
*/
|
|
109
|
+
readonly target: ReadonlyFormData;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 送信先のパスです。
|
|
113
|
+
*/
|
|
114
|
+
readonly action: string;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 実行するアクションの定義です。
|
|
118
|
+
*/
|
|
119
|
+
readonly actionId: IAction | undefined;
|
|
120
|
+
} | {
|
|
121
|
+
/**
|
|
122
|
+
* 送信対象となる URL クエリーパラメーターです。
|
|
123
|
+
*/
|
|
124
|
+
readonly target: ReadonlyURLSearchParams;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 送信先のパスです。
|
|
128
|
+
*/
|
|
129
|
+
readonly action: string;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* 履歴の追加方法を指定します。
|
|
133
|
+
*
|
|
134
|
+
* "replace" は現在のエントリーを置き換え、"push" は新しいエントリーを追加します。
|
|
135
|
+
*/
|
|
136
|
+
readonly history: "replace" | "push";
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* ナビゲーションの移動先を示す型定義です。
|
|
141
|
+
*
|
|
142
|
+
* パス文字列または詳細なパス情報のオブジェクトを受け取ります。
|
|
143
|
+
*/
|
|
144
|
+
export type NavigateTo = string | {
|
|
145
|
+
/**
|
|
146
|
+
* URL のパス名を表します。
|
|
147
|
+
*/
|
|
148
|
+
readonly pathname?: string | undefined;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* URL のクエリーパラメーターを表します。
|
|
152
|
+
*/
|
|
153
|
+
readonly search?: string | undefined;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* URL のハッシュフラグメントを表します。
|
|
157
|
+
*/
|
|
158
|
+
readonly hash?: string | undefined;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* エンジンの遷移関数に渡される引数の型定義です。
|
|
163
|
+
*/
|
|
164
|
+
export type NavigateArgs = {
|
|
165
|
+
/**
|
|
166
|
+
* 遷移先です。
|
|
167
|
+
*/
|
|
168
|
+
readonly to: NavigateTo;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 履歴の追加方法を指定します。
|
|
172
|
+
*
|
|
173
|
+
* "replace" は現在のエントリーを置き換え、"push" は新しいエントリーを追加します。
|
|
174
|
+
*/
|
|
175
|
+
readonly history: "replace" | "push";
|
|
176
|
+
} | {
|
|
177
|
+
/**
|
|
178
|
+
* 履歴スタックの相対位置です。
|
|
179
|
+
*/
|
|
180
|
+
readonly delta: number;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* ルーティングの基幹処理を担うエンジンのインターフェースです。
|
|
185
|
+
*/
|
|
186
|
+
export interface IEngine {
|
|
187
|
+
/**
|
|
188
|
+
* 与えられた引数に基づいて、ルーターを初期化します。
|
|
189
|
+
*
|
|
190
|
+
* @param args 状態生成に必要なルート情報やデータマップです。
|
|
191
|
+
* @returns 生成されたルーター状態、またはマッチしなかった場合は `null` を返します。
|
|
192
|
+
*/
|
|
193
|
+
init(args: InitEngineArgs): RouterState | null;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* エンジンの動作を開始します。履歴の変化の監視などを開始します。
|
|
197
|
+
*
|
|
198
|
+
* @param args エンジンの開始に必要な設定とコールバック関数です。
|
|
199
|
+
* @returns エンジンを停止するための関数を返します。停止処理が不要な場合は何も返しません。
|
|
200
|
+
*/
|
|
201
|
+
start(args: StartEngineArgs): IStopEngine | void;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* フォームデータやクエリー パラメーターを送信します。
|
|
205
|
+
*
|
|
206
|
+
* @param args 送信内容と送信先を含む引数です。
|
|
207
|
+
*/
|
|
208
|
+
submit(args: SubmitArgs): void;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 指定されたパスへ遷移します。
|
|
212
|
+
*
|
|
213
|
+
* @param args 遷移先と遷移オプションを含む引数です。
|
|
214
|
+
*/
|
|
215
|
+
navigate(args: NavigateArgs): void;
|
|
216
|
+
}
|