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,680 @@
1
+ import getTypeName from "type-name";
2
+ import { type BaseIssue, getGlobalConfig } from "valibot";
3
+ import isPromiseLike from "./_is-promise-like.js";
4
+ import singleton from "./_singleton.js";
5
+
6
+ /***************************************************************************************************
7
+ *
8
+ * 型
9
+ *
10
+ **************************************************************************************************/
11
+
12
+ /**
13
+ * エラーのオプションです。
14
+ */
15
+ export type ErrorOptions = Readonly<{
16
+ /**
17
+ * エラーの原因です。
18
+ */
19
+ cause?: unknown;
20
+ }>;
21
+
22
+ /**
23
+ * エラーに紐づくメタデータです。
24
+ */
25
+ export type ErrorMeta = {
26
+ readonly [prop: string]: unknown;
27
+ };
28
+
29
+ /**
30
+ * soseki におけるエラーのコンストラクターです。
31
+ */
32
+ export interface ISosekiErrorConstructor {
33
+ new(...args: any): ErrorBase<ErrorMeta | undefined>;
34
+ }
35
+
36
+ /**
37
+ * 検証エラーの問題点です。
38
+ */
39
+ export type Issue = BaseIssue<unknown>;
40
+
41
+ /***************************************************************************************************
42
+ *
43
+ * ユーティリティー
44
+ *
45
+ **************************************************************************************************/
46
+
47
+ /**
48
+ * エラーコンストラクターと言語ごとのエラーメッセージ作成関数のマップを取得します。
49
+ *
50
+ * @returns エラーコンストラクターと言語ごとのエラーメッセージ作成関数のマップです。
51
+ */
52
+ function getMessage(): WeakMap<Function | object, Map<string, (error: any) => string>> {
53
+ return singleton("errors__message", () => new WeakMap());
54
+ }
55
+
56
+ /**
57
+ * エラーコンストラクター内でメッセージプロパティーを初期化します。
58
+ *
59
+ * @template TInstance エラーオブジェクトの型です。
60
+ * @param instance エラーオブジェクトです。
61
+ * @param message エラーメッセージです。
62
+ */
63
+ function initMessage<TInstance extends Error>(
64
+ instance: TInstance,
65
+ message: (error: TInstance) => string,
66
+ ): void {
67
+ const reference = instance.constructor;
68
+ const { lang = "en" } = getGlobalConfig();
69
+ const msg = getMessage();
70
+ const store = msg.get(reference);
71
+ const genMessage = store?.get(lang) ?? message;
72
+ instance.message = genMessage(instance);
73
+ }
74
+
75
+ /**
76
+ * soseki のエラーに特定の言語でエラーメッセージを設定します。
77
+ *
78
+ * @template TReference soseki のエラーコンストラクターの型です。
79
+ * @param reference soseki のエラーコンストラクターです。
80
+ * @param message エラーメッセージです。
81
+ * @param lang 言語です。
82
+ * @example
83
+ * ```ts
84
+ * setErrorMessage(
85
+ * TypeError,
86
+ * ({ meta }) => `${meta.expected} を期待しましたが、${meta.actual} を得ました`,
87
+ * "ja",
88
+ * );
89
+ * ```
90
+ */
91
+ export function setErrorMessage<TReference extends ISosekiErrorConstructor>(
92
+ reference: TReference,
93
+ message: (error: InstanceType<TReference>) => string,
94
+ lang: string,
95
+ ): void {
96
+ const msg = getMessage();
97
+ let store = msg.get(reference);
98
+ if (store === undefined) {
99
+ store = new Map();
100
+ msg.set(reference, store);
101
+ }
102
+
103
+ store.set(lang, message);
104
+ }
105
+
106
+ /**
107
+ * あらゆる値を文字列に整形します。
108
+ *
109
+ * @param value 文字列に整形する値です。
110
+ * @returns 文字列に整形された値です。
111
+ */
112
+ function formatErrorValue(value: unknown): string {
113
+ try {
114
+ return JSON.stringify(value);
115
+ } catch {
116
+ return String(value);
117
+ }
118
+ }
119
+
120
+ /***************************************************************************************************
121
+ *
122
+ * エラークラス
123
+ *
124
+ **************************************************************************************************/
125
+
126
+ /**
127
+ * soseki エラーの基底クラスです。
128
+ *
129
+ * @template TMeta エラーに紐づくメタデータです。
130
+ */
131
+ export class ErrorBase<TMeta extends ErrorMeta | undefined = undefined> extends Error {
132
+ /**
133
+ * エラーのメタデータです。
134
+ */
135
+ public meta: Readonly<TMeta>;
136
+
137
+ /**
138
+ * @internal
139
+ */
140
+ public constructor(options: ErrorOptions | undefined, meta: TMeta) {
141
+ super("", options);
142
+
143
+ if (!("cause" in this) && options && "cause" in options) {
144
+ this.cause = options.cause;
145
+ }
146
+
147
+ this.meta = meta;
148
+ }
149
+ }
150
+
151
+ /**************************************************************************************************/
152
+
153
+ /**
154
+ * 到達不能なコードに到達した場合に投げられるエラーです。
155
+ */
156
+ export class UnreachableError extends ErrorBase<{
157
+ /**
158
+ * 到達しないはずの値です。
159
+ */
160
+ value?: unknown;
161
+ }> {
162
+ static {
163
+ this.prototype.name = "SosekiUnreachableError";
164
+ }
165
+
166
+ /**
167
+ * `UnreachableError` クラスの新しいインスタンスを初期化します。
168
+ *
169
+ * @param args 到達しないはずの値があれば指定します。
170
+ * @param options エラーのオプションです。
171
+ */
172
+ public constructor(args: [never?], options?: ErrorOptions | undefined) {
173
+ super(options, args.length > 0 ? { value: args[0] } : {});
174
+ initMessage(this, ({ meta }) => (
175
+ "value" in meta
176
+ ? "Encountered impossible value: " + formatErrorValue(meta.value)
177
+ : "Unreachable code reached"
178
+ ));
179
+ }
180
+ }
181
+
182
+ /*#__PURE__*/ setErrorMessage(
183
+ UnreachableError,
184
+ ({ meta }) => (
185
+ "value" in meta
186
+ ? "不可能な値に遭遇しました: " + formatErrorValue(meta.value)
187
+ : "到達できないコードに到達しました"
188
+ ),
189
+ "ja",
190
+ );
191
+
192
+ /**************************************************************************************************/
193
+
194
+ /**
195
+ * 検証エラーの基底クラスです。
196
+ *
197
+ * @template TMeta エラーに紐づくメタデータです。
198
+ */
199
+ export class ValidationErrorBase<TMeta extends ErrorMeta> extends ErrorBase<TMeta> {
200
+ /**
201
+ * @internal
202
+ */
203
+ public constructor(options: ErrorOptions | undefined, meta: TMeta) {
204
+ super(options, meta);
205
+ }
206
+ }
207
+
208
+ /**************************************************************************************************/
209
+
210
+ // /**
211
+ // * 入力値検証エラーの基底クラスです。
212
+ // *
213
+ // * @template TMeta エラーに紐づくメタデータです。
214
+ // */
215
+ // export class InvalidInputErrorBase<TMeta extends ErrorMeta> extends ValidationErrorBase<TMeta> {
216
+ // /**
217
+ // * @internal
218
+ // */
219
+ // public constructor(options: ErrorOptions | undefined, meta: TMeta) {
220
+ // super(options, meta);
221
+ // }
222
+ // }
223
+
224
+ /**************************************************************************************************/
225
+
226
+ // /**
227
+ // * 入力値の検証に失敗した場合に投げられるエラーです。
228
+ // */
229
+ // export class InvalidInputError extends InvalidInputErrorBase<{
230
+ // /**
231
+ // * 検証エラーの問題点です。
232
+ // */
233
+ // issues: [Issue, ...Issue[]];
234
+
235
+ // /**
236
+ // * 検証した入力値です。
237
+ // */
238
+ // input: unknown;
239
+ // }> {
240
+ // static {
241
+ // this.prototype.name = "SosekiInvalidInputError";
242
+ // }
243
+
244
+ // /**
245
+ // * `InvalidInputError` クラスの新しいインスタンスを初期化します。
246
+ // *
247
+ // * @param issues 検証エラーの問題点です。
248
+ // * @param input 検証した入力値です。
249
+ // * @param options エラーのオプションです。
250
+ // */
251
+ // public constructor(
252
+ // issues: [Issue, ...Issue[]],
253
+ // input: unknown,
254
+ // options?: ErrorOptions | undefined,
255
+ // ) {
256
+ // super(options, { issues, input });
257
+ // this.message = issues.map(issue => issue.message).join(": ");
258
+ // }
259
+ // }
260
+
261
+ /**************************************************************************************************/
262
+
263
+ /**
264
+ * 予期しない値に遭遇した場合に投げられるエラーです。
265
+ */
266
+ export class UnexpectedValidationError extends ValidationErrorBase<{
267
+ /**
268
+ * 検証エラーの問題点です。
269
+ */
270
+ issues: [Issue, ...Issue[]];
271
+
272
+ /**
273
+ * 予期しない値です。
274
+ */
275
+ value: unknown;
276
+ }> {
277
+ static {
278
+ this.prototype.name = "SosekiUnexpectedValidationError";
279
+ }
280
+
281
+ /**
282
+ * `UnexpectedValidationError` クラスの新しいインスタンスを初期化します。
283
+ *
284
+ * @param issues 検証エラーの問題点です。
285
+ * @param value 予期しない値です。
286
+ * @param options エラーのオプションです。
287
+ */
288
+ public constructor(
289
+ issues: [Issue, ...Issue[]],
290
+ value: unknown,
291
+ options?: ErrorOptions | undefined,
292
+ ) {
293
+ super(options, { issues, value });
294
+ this.message = issues.map(issue => issue.message).join(": ");
295
+ }
296
+ }
297
+
298
+ /**************************************************************************************************/
299
+
300
+ /**
301
+ * shouldAction が不正な値を返した場合に投げられるエラーです。
302
+ */
303
+ export class ActionConditionError extends ErrorBase<{
304
+ /**
305
+ * ルートの URL です。
306
+ */
307
+ url: string;
308
+
309
+ /**
310
+ * shouldAction 関数です。
311
+ */
312
+ shouldAction: Function;
313
+
314
+ /**
315
+ * shouldAction が返した値です。
316
+ */
317
+ returnValue: unknown;
318
+ }> {
319
+ static {
320
+ this.prototype.name = "SosekiActionConditionError";
321
+ }
322
+
323
+ /**
324
+ * `ActionConditionError` クラスの新しいインスタンスを初期化します。
325
+ *
326
+ * @param url ルートの URL です。
327
+ * @param shouldAction shouldAction 関数です。
328
+ * @param returnValue shouldAction が返した値です。
329
+ * @param options エラーのオプションです。
330
+ */
331
+ public constructor(
332
+ url: string,
333
+ shouldAction: Function,
334
+ returnValue: unknown,
335
+ options?: ErrorOptions | undefined,
336
+ ) {
337
+ super(options, {
338
+ url,
339
+ returnValue,
340
+ shouldAction,
341
+ });
342
+ initMessage(
343
+ this,
344
+ ({ meta }) =>
345
+ isPromiseLike(meta.returnValue)
346
+ ? "shouldAction must return a boolean value synchronously"
347
+ : `Expected boolean, but got ${getTypeName(meta.returnValue) || "unknown"}`,
348
+ );
349
+ }
350
+ }
351
+
352
+ /*#__PURE__*/ setErrorMessage(
353
+ ActionConditionError,
354
+ ({ meta }) =>
355
+ isPromiseLike(meta.returnValue)
356
+ ? "shouldAction は同期的に真偽値を返す必要があります"
357
+ : `真偽値を期待しましたが、${getTypeName(meta.returnValue) || "unknown"} を得ました`,
358
+ "ja",
359
+ );
360
+
361
+ /**************************************************************************************************/
362
+
363
+ /**
364
+ * 1 つ以上のアクションが失敗した際に投げられるエラーです。
365
+ */
366
+ export class ActionExecutionError extends ErrorBase<{
367
+ /**
368
+ * ルートの URL です。
369
+ */
370
+ url: string;
371
+
372
+ /**
373
+ * エラーのリストです。
374
+ */
375
+ errors: readonly {
376
+ /**
377
+ * action 関数です。
378
+ */
379
+ readonly action: Function;
380
+
381
+ /**
382
+ * エラーの原因です。
383
+ */
384
+ readonly reason: unknown;
385
+ }[];
386
+ }> {
387
+ static {
388
+ this.prototype.name = "SosekiActionExecutionError";
389
+ }
390
+
391
+ /**
392
+ * `ActionExecutionError` クラスの新しいインスタンスを初期化します。
393
+ *
394
+ * @param url ルートの URL です。
395
+ * @param errors エラーのリストです。
396
+ * @param options エラーのオプションです。
397
+ */
398
+ public constructor(
399
+ url: string,
400
+ errors: readonly {
401
+ /**
402
+ * action 関数です。
403
+ */
404
+ action: Function;
405
+
406
+ /**
407
+ * エラーの原因です。
408
+ */
409
+ reason: unknown;
410
+ }[],
411
+ options?: ErrorOptions | undefined,
412
+ ) {
413
+ super(options, {
414
+ url,
415
+ errors,
416
+ });
417
+ initMessage(
418
+ this,
419
+ ({ meta }) => `Errors occurred in ${meta.errors.length} action(s)`,
420
+ );
421
+ }
422
+ }
423
+
424
+ /*#__PURE__*/ setErrorMessage(
425
+ ActionExecutionError,
426
+ ({ meta }) => `${meta.errors.length} 個のアクションでエラーが発生しました。`,
427
+ "ja",
428
+ );
429
+
430
+ /**************************************************************************************************/
431
+
432
+ /**
433
+ * 複数のアクションからリダイレクトが返された際に投げられるエラーです。
434
+ */
435
+ export class MultipleRedirectError extends ErrorBase<{
436
+ /**
437
+ * ルートの URL です。
438
+ */
439
+ url: string;
440
+
441
+ /**
442
+ * 検出されたリダイレクト先パスのリストです。
443
+ */
444
+ redirects: readonly string[];
445
+ }> {
446
+ static {
447
+ this.prototype.name = "SosekiMultipleRedirectError";
448
+ }
449
+
450
+ /**
451
+ * `MultipleRedirectError` クラスの新しいインスタンスを初期化します。
452
+ *
453
+ * @param url ルートの URL です。
454
+ * @param redirects リダイレクト先パスのリストです。
455
+ * @param options エラーのオプションです。
456
+ */
457
+ public constructor(
458
+ url: string,
459
+ redirects: readonly string[],
460
+ options?: ErrorOptions | undefined,
461
+ ) {
462
+ super(options, {
463
+ url,
464
+ redirects,
465
+ });
466
+ initMessage(
467
+ this,
468
+ ({ meta }) => `Multiple redirects detected: ${meta.redirects.join(", ")}`,
469
+ );
470
+ }
471
+ }
472
+
473
+ /*#__PURE__*/ setErrorMessage(
474
+ MultipleRedirectError,
475
+ ({ meta }) => `複数のリダイレクトが検出されました: ${meta.redirects.join(", ")}`,
476
+ "ja",
477
+ );
478
+
479
+ /**************************************************************************************************/
480
+
481
+ /**
482
+ * shouldLoader が不正な値を返した場合に投げられるエラーです。
483
+ */
484
+ export class LoaderConditionError extends ErrorBase<{
485
+ /**
486
+ * ルートの URL です。
487
+ */
488
+ url: string;
489
+
490
+ /**
491
+ * shouldLoader 関数です。
492
+ */
493
+ shouldLoader: Function;
494
+
495
+ /**
496
+ * shouldLoader が返した値です。
497
+ */
498
+ returnValue: unknown;
499
+ }> {
500
+ static {
501
+ this.prototype.name = "SosekiLoaderConditionError";
502
+ }
503
+
504
+ /**
505
+ * `LoaderConditionError` クラスの新しいインスタンスを初期化します。
506
+ *
507
+ * @param url ルートの URL です。
508
+ * @param shouldLoader shouldLoader 関数です。
509
+ * @param returnValue shouldLoader が返した値です。
510
+ * @param options エラーのオプションです。
511
+ */
512
+ public constructor(
513
+ url: string,
514
+ shouldLoader: Function,
515
+ returnValue: unknown,
516
+ options?: ErrorOptions | undefined,
517
+ ) {
518
+ super(options, {
519
+ url,
520
+ returnValue,
521
+ shouldLoader,
522
+ });
523
+ initMessage(
524
+ this,
525
+ ({ meta }) =>
526
+ isPromiseLike(meta.returnValue)
527
+ ? "shouldLoader must return a boolean value synchronously"
528
+ : `Expected boolean, but got ${getTypeName(meta.returnValue) || "unknown"}`,
529
+ );
530
+ }
531
+ }
532
+
533
+ /*#__PURE__*/ setErrorMessage(
534
+ LoaderConditionError,
535
+ ({ meta }) =>
536
+ isPromiseLike(meta.returnValue)
537
+ ? "shouldLoader は同期的に真偽値を返す必要があります"
538
+ : `真偽値を期待しましたが、${getTypeName(meta.returnValue) || "unknown"} を得ました`,
539
+ "ja",
540
+ );
541
+
542
+ /**************************************************************************************************/
543
+
544
+ /**
545
+ * Navigation API が現在の環境でサポートされていない場合に投げられるエラーです。
546
+ */
547
+ export class NavigationApiNotSupportedError extends ErrorBase<{
548
+ /**
549
+ * 現在のブラウザの UserAgent です。
550
+ */
551
+ userAgent: string;
552
+ }> {
553
+ static {
554
+ this.prototype.name = "SosekiNavigationApiNotSupportedError";
555
+ }
556
+
557
+ /**
558
+ * `NavigationApiNotSupportedError` クラスの新しいインスタンスを初期化します。
559
+ *
560
+ * @param options エラーのオプションです。
561
+ */
562
+ public constructor(options?: ErrorOptions | undefined) {
563
+ super(options, {
564
+ userAgent: typeof window !== "undefined"
565
+ ? window.navigator.userAgent
566
+ : "unknown",
567
+ });
568
+ initMessage(
569
+ this,
570
+ () => "The Navigation API is not supported in this environment",
571
+ );
572
+ }
573
+ }
574
+
575
+ /*#__PURE__*/ setErrorMessage(
576
+ NavigationApiNotSupportedError,
577
+ () => "現在の環境では Navigation API がサポートされていません",
578
+ "ja",
579
+ );
580
+
581
+ /**************************************************************************************************/
582
+
583
+ /**
584
+ * RouteContext が供給されていない場合に投げられるエラーです。
585
+ */
586
+ export class RouteContextMissingError extends ErrorBase<undefined> {
587
+ static {
588
+ this.prototype.name = "SosekiRouteContextMissingError";
589
+ }
590
+
591
+ /**
592
+ * `RouteContextMissingError` クラスの新しいインスタンスを初期化します。
593
+ *
594
+ * @param options エラーのオプションです。
595
+ */
596
+ public constructor(options?: ErrorOptions | undefined) {
597
+ // メタデータは不要なため undefined を渡す
598
+ super(options, undefined);
599
+ initMessage(
600
+ this,
601
+ () => "RouteContext not found. Did you forget to wrap your app in <Router />?",
602
+ );
603
+ }
604
+ }
605
+
606
+ /*#__PURE__*/ setErrorMessage(
607
+ RouteContextMissingError,
608
+ () => "RouteContext が見つかりません。アプリを <Router /> で囲むのを忘れていませんか?",
609
+ "ja",
610
+ );
611
+
612
+ /**************************************************************************************************/
613
+
614
+ /**
615
+ * RouterContext が供給されていない場合に投げられるエラーです。
616
+ */
617
+ export class RouterContextMissingError extends ErrorBase<undefined> {
618
+ static {
619
+ this.prototype.name = "SosekiRouterContextMissingError";
620
+ }
621
+
622
+ /**
623
+ * `RouterContextMissingError` クラスの新しいインスタンスを初期化します。
624
+ *
625
+ * @param options エラーのオプションです。
626
+ */
627
+ public constructor(options?: ErrorOptions | undefined) {
628
+ // メタデータは不要なため undefined を渡す
629
+ super(options, undefined);
630
+ initMessage(
631
+ this,
632
+ () => "RouterContext not found. Did you forget to wrap your app in <Router />?",
633
+ );
634
+ }
635
+ }
636
+
637
+ /*#__PURE__*/ setErrorMessage(
638
+ RouterContextMissingError,
639
+ () => "RouterContext が見つかりません。アプリを <Router /> で囲むのを忘れていませんか?",
640
+ "ja",
641
+ );
642
+
643
+ /**************************************************************************************************/
644
+
645
+ /**
646
+ * ローダーに紐づくデータが見つからない場合に投げられるエラーです。
647
+ */
648
+ export class LoaderDataNotFoundError extends ErrorBase<{
649
+ /**
650
+ * データが見つからなかった loader 関数です。
651
+ */
652
+ loader: Function;
653
+ }> {
654
+ static {
655
+ this.prototype.name = "SosekiLoaderDataNotFoundError";
656
+ }
657
+
658
+ /**
659
+ * `LoaderDataNotFoundError` クラスの新しいインスタンスを初期化します。
660
+ *
661
+ * @param loader データが見つからなかった loader 関数です。
662
+ * @param options エラーのオプションです。
663
+ */
664
+ public constructor(
665
+ loader: Function,
666
+ options?: ErrorOptions | undefined,
667
+ ) {
668
+ super(options, { loader });
669
+ initMessage(
670
+ this,
671
+ ({ meta }) => `Loader data not found (Loader: ${meta.loader.name || "anonymous"})`,
672
+ );
673
+ }
674
+ }
675
+
676
+ /*#__PURE__*/ setErrorMessage(
677
+ LoaderDataNotFoundError,
678
+ ({ meta }) => `ローダーデータが見つかりません(Loader: ${meta.loader.name || "匿名"})`,
679
+ "ja",
680
+ );