@uniflowed/router 0.34.0 → 0.36.0
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/action.js +5 -5
- package/client.js +20 -20
- package/handler.js +6 -6
- package/http-client.js +10 -10
- package/index.js +3 -3
- package/instrumentation.js +5 -5
- package/internal/action-endpoint.js +7 -7
- package/internal/action-wire.js +3 -3
- package/internal/base-path.js +3 -3
- package/internal/boundaries.js +8 -8
- package/internal/boundary-data.js +12 -12
- package/internal/compose.js +4 -4
- package/internal/devtools.js +1 -1
- package/internal/diagnostics.js +8 -8
- package/internal/error-view.js +6 -6
- package/internal/flight-browser.js +6 -6
- package/internal/flight-rows.js +4 -4
- package/internal/flight-ssr.js +3 -3
- package/internal/flight.js +26 -26
- package/internal/form-action.js +11 -11
- package/internal/hydrate-options.js +1 -1
- package/internal/hydration.js +37 -37
- package/internal/inspector.js +15 -15
- package/internal/native-links.js +3 -3
- package/internal/native-tree.js +11 -11
- package/internal/navigation-cache.js +12 -12
- package/internal/payload-rows.js +2 -2
- package/internal/payload.js +10 -10
- package/internal/resolve.js +103 -103
- package/internal/resolved-summary.js +76 -76
- package/internal/routing.js +52 -52
- package/internal/runtime.js +47 -47
- package/internal/search-params.js +1 -1
- package/internal/shell.js +8 -8
- package/internal/stream.js +44 -44
- package/middleware.js +11 -11
- package/native-navigation.js +21 -21
- package/native.js +45 -45
- package/package.json +4 -4
- package/rsc-client.js +5 -5
- package/rsc-ssr.js +31 -31
- package/rsc.js +17 -17
- package/server-components.js +5 -5
- package/server.js +33 -33
- package/testing.js +62 -62
package/internal/resolve.js
CHANGED
|
@@ -93,7 +93,7 @@ export type PageRenderProps = {|
|
|
|
93
93
|
readonly params: RouteParams,
|
|
94
94
|
/** The string map, or the output of the page's `searchParams` schema. */
|
|
95
95
|
readonly searchParams: mixed,
|
|
96
|
-
readonly data: mixed,
|
|
96
|
+
readonly data : mixed,
|
|
97
97
|
|};
|
|
98
98
|
|
|
99
99
|
/**
|
|
@@ -110,7 +110,7 @@ export type PageRenderProps = {|
|
|
|
110
110
|
* where a typo in a slot name shows up.
|
|
111
111
|
*/
|
|
112
112
|
export type LayoutRenderProps = {
|
|
113
|
-
readonly params: RouteParams,
|
|
113
|
+
readonly params : RouteParams,
|
|
114
114
|
readonly children: React.Node,
|
|
115
115
|
...
|
|
116
116
|
};
|
|
@@ -118,16 +118,16 @@ export type LayoutRenderProps = {
|
|
|
118
118
|
/** What a page module may export. The component is `default` or `Page`. */
|
|
119
119
|
export type PageModule = {
|
|
120
120
|
readonly default?: RouteComponent,
|
|
121
|
-
readonly Page
|
|
122
|
-
readonly loader
|
|
121
|
+
readonly Page? : RouteComponent,
|
|
122
|
+
readonly loader? : (args: LoaderArgs) => mixed | Promise<mixed>,
|
|
123
123
|
/**
|
|
124
124
|
* A `@uniflowed/validator` schema for the query string. The page is then
|
|
125
125
|
* given its output as `searchParams` rather than the string map, and a
|
|
126
126
|
* query that does not fit it is the error boundary with a `400`. See
|
|
127
127
|
* `./search-params.js`.
|
|
128
128
|
*/
|
|
129
|
-
readonly searchParams
|
|
130
|
-
readonly metadata
|
|
129
|
+
readonly searchParams? : Schema<mixed, mixed>,
|
|
130
|
+
readonly metadata? : Metadata,
|
|
131
131
|
readonly generateMetadata?: (args: MetadataArgs) => Metadata | Promise<Metadata>,
|
|
132
132
|
readonly generateStaticParams?: () =>
|
|
133
133
|
| $ReadOnlyArray<RouteParams>
|
|
@@ -154,8 +154,8 @@ export type PageModule = {
|
|
|
154
154
|
|
|
155
155
|
/** What a layout module may export. The component is `default` or `Layout`. */
|
|
156
156
|
export type LayoutModule = {
|
|
157
|
-
readonly default
|
|
158
|
-
readonly Layout
|
|
157
|
+
readonly default? : RouteComponent,
|
|
158
|
+
readonly Layout? : RouteComponent,
|
|
159
159
|
readonly metadata?: Metadata,
|
|
160
160
|
/** A transition name for every route under this layout; see [`PageModule`]. */
|
|
161
161
|
readonly viewTransition?: string,
|
|
@@ -172,7 +172,7 @@ export type LayoutModule = {
|
|
|
172
172
|
* about nothing. Titles come from the page and the layouts above it.
|
|
173
173
|
*/
|
|
174
174
|
export type TemplateModule = {
|
|
175
|
-
readonly default
|
|
175
|
+
readonly default? : RouteComponent,
|
|
176
176
|
readonly Template?: RouteComponent,
|
|
177
177
|
...
|
|
178
178
|
};
|
|
@@ -187,8 +187,8 @@ export type TemplateModule = {
|
|
|
187
187
|
* whose whole job is already in its name.
|
|
188
188
|
*/
|
|
189
189
|
export type ErrorModule = {
|
|
190
|
-
readonly default
|
|
191
|
-
readonly Error
|
|
190
|
+
readonly default? : RouteComponent,
|
|
191
|
+
readonly Error? : RouteComponent,
|
|
192
192
|
readonly metadata?: Metadata,
|
|
193
193
|
...
|
|
194
194
|
};
|
|
@@ -233,10 +233,10 @@ export type TwitterCard = "summary" | "summary_large_image" | "app" | "player";
|
|
|
233
233
|
* says — the tag exists to say something else.
|
|
234
234
|
*/
|
|
235
235
|
export type Robots = {
|
|
236
|
-
readonly index
|
|
236
|
+
readonly index? : boolean,
|
|
237
237
|
readonly follow?: boolean,
|
|
238
238
|
/** The longest snippet a result may quote; `0` is none, `-1` is no limit. */
|
|
239
|
-
readonly maxSnippet
|
|
239
|
+
readonly maxSnippet? : number,
|
|
240
240
|
readonly maxImagePreview?: "none" | "standard" | "large",
|
|
241
241
|
};
|
|
242
242
|
|
|
@@ -254,7 +254,7 @@ export type JsonLd = { readonly [string]: mixed };
|
|
|
254
254
|
|
|
255
255
|
/** Document metadata a page or layout declares. */
|
|
256
256
|
export type Metadata = {
|
|
257
|
-
readonly title
|
|
257
|
+
readonly title? : string,
|
|
258
258
|
readonly description?: string,
|
|
259
259
|
/**
|
|
260
260
|
* The absolute URL every other URL here is resolved against.
|
|
@@ -366,7 +366,7 @@ export type Metadata = {
|
|
|
366
366
|
* title. Declared once on the root layout.
|
|
367
367
|
*/
|
|
368
368
|
readonly siteName?: string,
|
|
369
|
-
readonly images
|
|
369
|
+
readonly images? : $ReadOnlyArray<string>,
|
|
370
370
|
/**
|
|
371
371
|
* What the card's image shows, for a reader who cannot see it.
|
|
372
372
|
*
|
|
@@ -377,14 +377,14 @@ export type Metadata = {
|
|
|
377
377
|
readonly imageAlt?: string,
|
|
378
378
|
},
|
|
379
379
|
readonly twitter?: {
|
|
380
|
-
readonly card
|
|
381
|
-
readonly site
|
|
380
|
+
readonly card? : TwitterCard,
|
|
381
|
+
readonly site? : string,
|
|
382
382
|
readonly creator?: string,
|
|
383
383
|
/** Falls back to `openGraph.title`, and then to `title`. */
|
|
384
384
|
readonly title?: string,
|
|
385
385
|
/** Falls back to `openGraph.description`, and then to `description`. */
|
|
386
386
|
readonly description?: string,
|
|
387
|
-
readonly images
|
|
387
|
+
readonly images? : $ReadOnlyArray<string>,
|
|
388
388
|
/** Falls back to `openGraph.imageAlt`. */
|
|
389
389
|
readonly imageAlt?: string,
|
|
390
390
|
},
|
|
@@ -392,16 +392,16 @@ export type Metadata = {
|
|
|
392
392
|
|
|
393
393
|
/** Arguments a loader receives. */
|
|
394
394
|
export type LoaderArgs = {|
|
|
395
|
-
readonly params: RouteParams,
|
|
395
|
+
readonly params : RouteParams,
|
|
396
396
|
readonly searchParams: SearchParams,
|
|
397
|
-
readonly pathname: string,
|
|
397
|
+
readonly pathname : string,
|
|
398
398
|
|};
|
|
399
399
|
|
|
400
400
|
/** Arguments `generateMetadata` receives. */
|
|
401
401
|
export type MetadataArgs = {|
|
|
402
|
-
readonly params: RouteParams,
|
|
402
|
+
readonly params : RouteParams,
|
|
403
403
|
readonly searchParams: SearchParams,
|
|
404
|
-
readonly data: mixed,
|
|
404
|
+
readonly data : mixed,
|
|
405
405
|
|};
|
|
406
406
|
|
|
407
407
|
export type RouteRecord = RoutingRouteRecord<
|
|
@@ -447,17 +447,17 @@ export type RouteTable = RoutingRouteTable<
|
|
|
447
447
|
export type RouteMatch = RoutingRouteMatch<RouteRecord>;
|
|
448
448
|
|
|
449
449
|
export type ResolvedTemplate = {|
|
|
450
|
-
readonly above: number,
|
|
450
|
+
readonly above : number,
|
|
451
451
|
readonly module: TemplateModule,
|
|
452
452
|
|};
|
|
453
453
|
|
|
454
454
|
type ResolvedSlotErrorBoundary = {|
|
|
455
|
-
readonly above: number,
|
|
455
|
+
readonly above : number,
|
|
456
456
|
readonly module: ?ErrorModule,
|
|
457
457
|
|};
|
|
458
458
|
|
|
459
459
|
type SlotErrorBoundaryLoader = {|
|
|
460
|
-
readonly above: number,
|
|
460
|
+
readonly above : number,
|
|
461
461
|
readonly module: () => Promise<ErrorModule>,
|
|
462
462
|
|};
|
|
463
463
|
|
|
@@ -466,18 +466,18 @@ type SlotErrorBoundaryLoader = {|
|
|
|
466
466
|
* when `error` is set, the error page that stands in for it.
|
|
467
467
|
*/
|
|
468
468
|
export type ResolvedRoute = {|
|
|
469
|
-
readonly pathname: string,
|
|
470
|
-
readonly search: string,
|
|
471
|
-
readonly path: string,
|
|
472
|
-
readonly params: RouteParams,
|
|
469
|
+
readonly pathname : string,
|
|
470
|
+
readonly search : string,
|
|
471
|
+
readonly path : string,
|
|
472
|
+
readonly params : RouteParams,
|
|
473
473
|
readonly searchParams: SearchParams,
|
|
474
474
|
/**
|
|
475
475
|
* What the page's `searchParams` schema made of the query, when it exports
|
|
476
476
|
* one; absent otherwise. [`pageSearchParams`] is what the page is given.
|
|
477
477
|
*/
|
|
478
478
|
readonly parsedSearchParams?: mixed,
|
|
479
|
-
readonly page: PageModule,
|
|
480
|
-
readonly layouts: $ReadOnlyArray<LayoutModule>,
|
|
479
|
+
readonly page : PageModule,
|
|
480
|
+
readonly layouts : $ReadOnlyArray<LayoutModule>,
|
|
481
481
|
/** What the loader returned, once it has. `undefined` while `deferred` is set. */
|
|
482
482
|
readonly data: mixed,
|
|
483
483
|
/**
|
|
@@ -506,7 +506,7 @@ export type ResolvedRoute = {|
|
|
|
506
506
|
* carries it and never reads it; see "View transitions".
|
|
507
507
|
*/
|
|
508
508
|
readonly viewTransition: ?string,
|
|
509
|
-
readonly status: 200 | 400 | 401 | 403 | 404 | 500,
|
|
509
|
+
readonly status : 200 | 400 | 401 | 403 | 404 | 500,
|
|
510
510
|
/**
|
|
511
511
|
* Set when this resolution *is* the error page: the loader threw, or the
|
|
512
512
|
* server render did and the renderer resolved again. `null` on the ordinary
|
|
@@ -524,7 +524,7 @@ export type ResolvedRoute = {|
|
|
|
524
524
|
*/
|
|
525
525
|
readonly errorBoundary: {|
|
|
526
526
|
readonly module: ?ErrorModule,
|
|
527
|
-
readonly above: number,
|
|
527
|
+
readonly above : number,
|
|
528
528
|
|},
|
|
529
529
|
/**
|
|
530
530
|
* The loading boundaries around this route, root first, already imported.
|
|
@@ -588,7 +588,7 @@ export type ResolvedRoute = {|
|
|
|
588
588
|
export type Interception = {|
|
|
589
589
|
/** The URL the navigation went to: the one in the address bar. */
|
|
590
590
|
readonly pathname: string,
|
|
591
|
-
readonly search: string,
|
|
591
|
+
readonly search : string,
|
|
592
592
|
/** The route the navigation came from, as it was before it was intercepted. */
|
|
593
593
|
readonly base: ResolvedRoute,
|
|
594
594
|
|};
|
|
@@ -639,7 +639,7 @@ export type ResolvedSlot = {|
|
|
|
639
639
|
|
|
640
640
|
/** The URL an intercepting route was matched against. */
|
|
641
641
|
type InterceptedUrl = {|
|
|
642
|
-
readonly pathname: string,
|
|
642
|
+
readonly pathname : string,
|
|
643
643
|
readonly searchParams: SearchParams,
|
|
644
644
|
|};
|
|
645
645
|
|
|
@@ -739,8 +739,8 @@ export function loadOnce<T>(load: () => Promise<T>): Promise<T> {
|
|
|
739
739
|
* them needs it *early*. The browser passes nothing and pays nothing.
|
|
740
740
|
*/
|
|
741
741
|
export async function resolveMatch(
|
|
742
|
-
table: RouteTable,
|
|
743
|
-
url: string,
|
|
742
|
+
table : RouteTable,
|
|
743
|
+
url : string,
|
|
744
744
|
options?: ResolveOptions,
|
|
745
745
|
): Promise<ResolvedRoute> {
|
|
746
746
|
try {
|
|
@@ -789,8 +789,8 @@ export type ResolveOptions = {|
|
|
|
789
789
|
|};
|
|
790
790
|
|
|
791
791
|
async function resolveRoute(
|
|
792
|
-
table: RouteTable,
|
|
793
|
-
url: string,
|
|
792
|
+
table : RouteTable,
|
|
793
|
+
url : string,
|
|
794
794
|
options?: ResolveOptions,
|
|
795
795
|
): Promise<ResolvedRoute> {
|
|
796
796
|
const { pathname, search } = splitUrl(url);
|
|
@@ -897,7 +897,7 @@ async function resolveRoute(
|
|
|
897
897
|
return {
|
|
898
898
|
pathname,
|
|
899
899
|
search,
|
|
900
|
-
path: matched.route.path,
|
|
900
|
+
path : matched.route.path,
|
|
901
901
|
params: matched.params,
|
|
902
902
|
searchParams,
|
|
903
903
|
...(parsed == null ? {} : { parsedSearchParams: parsed.value }),
|
|
@@ -907,12 +907,12 @@ async function resolveRoute(
|
|
|
907
907
|
deferred,
|
|
908
908
|
metadata,
|
|
909
909
|
viewTransition: resolveViewTransition(page, layouts),
|
|
910
|
-
status: 200,
|
|
911
|
-
error: null,
|
|
912
|
-
errorBoundary: await boundary,
|
|
913
|
-
loading: await loading,
|
|
914
|
-
templates: await templates,
|
|
915
|
-
slots: await slots,
|
|
910
|
+
status : 200,
|
|
911
|
+
error : null,
|
|
912
|
+
errorBoundary : await boundary,
|
|
913
|
+
loading : await loading,
|
|
914
|
+
templates : await templates,
|
|
915
|
+
slots : await slots,
|
|
916
916
|
};
|
|
917
917
|
}
|
|
918
918
|
|
|
@@ -931,11 +931,11 @@ async function resolveRoute(
|
|
|
931
931
|
* null`, so the layout still receives the prop it declares.
|
|
932
932
|
*/
|
|
933
933
|
async function resolveSlots(
|
|
934
|
-
records: $ReadOnlyArray<SlotRecord>,
|
|
935
|
-
pathname: string,
|
|
936
|
-
layoutCount: number,
|
|
934
|
+
records : $ReadOnlyArray<SlotRecord>,
|
|
935
|
+
pathname : string,
|
|
936
|
+
layoutCount : number,
|
|
937
937
|
fallbackParams: RouteParams,
|
|
938
|
-
intercepted
|
|
938
|
+
intercepted? : ?InterceptedUrl,
|
|
939
939
|
): Promise<$ReadOnlyArray<ResolvedSlot>> {
|
|
940
940
|
if (records.length === 0) {
|
|
941
941
|
return [];
|
|
@@ -948,11 +948,11 @@ async function resolveSlots(
|
|
|
948
948
|
}
|
|
949
949
|
|
|
950
950
|
async function resolveSlot(
|
|
951
|
-
record: SlotRecord,
|
|
952
|
-
pathname: string,
|
|
953
|
-
layoutCount: number,
|
|
951
|
+
record : SlotRecord,
|
|
952
|
+
pathname : string,
|
|
953
|
+
layoutCount : number,
|
|
954
954
|
fallbackParams: RouteParams,
|
|
955
|
-
intercepted
|
|
955
|
+
intercepted? : ?InterceptedUrl,
|
|
956
956
|
): Promise<ResolvedSlot> {
|
|
957
957
|
// Clamped exactly as a template's `above` is, and for the same reason: a
|
|
958
958
|
// hand-written table, or a `(group)` between the layout and the route, can
|
|
@@ -961,13 +961,13 @@ async function resolveSlot(
|
|
|
961
961
|
const empty: ResolvedSlot = {
|
|
962
962
|
name: record.name,
|
|
963
963
|
above,
|
|
964
|
-
page: null,
|
|
965
|
-
params: fallbackParams,
|
|
966
|
-
layouts: [],
|
|
967
|
-
loading: [],
|
|
968
|
-
templates: [],
|
|
964
|
+
page : null,
|
|
965
|
+
params : fallbackParams,
|
|
966
|
+
layouts : [],
|
|
967
|
+
loading : [],
|
|
968
|
+
templates : [],
|
|
969
969
|
errorBoundary: null,
|
|
970
|
-
slots: [],
|
|
970
|
+
slots : [],
|
|
971
971
|
record,
|
|
972
972
|
intercepted,
|
|
973
973
|
};
|
|
@@ -986,7 +986,7 @@ async function resolveSlot(
|
|
|
986
986
|
}
|
|
987
987
|
return {
|
|
988
988
|
...empty,
|
|
989
|
-
page: withoutLoader(module, record.defaultFile ?? record.name),
|
|
989
|
+
page : withoutLoader(module, record.defaultFile ?? record.name),
|
|
990
990
|
errorBoundary: await resolveSlotErrorBoundary(record.defaultErrorBoundary ?? null, 0),
|
|
991
991
|
};
|
|
992
992
|
}
|
|
@@ -1010,10 +1010,10 @@ async function resolveSlot(
|
|
|
1010
1010
|
* navigation goes where the URL says instead.
|
|
1011
1011
|
*/
|
|
1012
1012
|
async function resolveSlotRoute(
|
|
1013
|
-
record: SlotRecord,
|
|
1014
|
-
matched: RoutingRouteMatch<SlotRouteRecord>,
|
|
1015
|
-
above: number,
|
|
1016
|
-
pathname: string,
|
|
1013
|
+
record : SlotRecord,
|
|
1014
|
+
matched : RoutingRouteMatch<SlotRouteRecord>,
|
|
1015
|
+
above : number,
|
|
1016
|
+
pathname : string,
|
|
1017
1017
|
intercepted: ?InterceptedUrl,
|
|
1018
1018
|
): Promise<?ResolvedSlot> {
|
|
1019
1019
|
const route = matched.route;
|
|
@@ -1036,8 +1036,8 @@ async function resolveSlotRoute(
|
|
|
1036
1036
|
return {
|
|
1037
1037
|
name: record.name,
|
|
1038
1038
|
above,
|
|
1039
|
-
page: withoutLoader(page, route.file),
|
|
1040
|
-
params: matched.params,
|
|
1039
|
+
page : withoutLoader(page, route.file),
|
|
1040
|
+
params : matched.params,
|
|
1041
1041
|
layouts: loaded,
|
|
1042
1042
|
loading,
|
|
1043
1043
|
templates,
|
|
@@ -1083,7 +1083,7 @@ export function beneath(resolved: ResolvedRoute): ResolvedRoute {
|
|
|
1083
1083
|
* about to be replaced, nested slots and all.
|
|
1084
1084
|
*/
|
|
1085
1085
|
export function interceptingRoutes(
|
|
1086
|
-
slots: $ReadOnlyArray<ResolvedSlot>,
|
|
1086
|
+
slots : $ReadOnlyArray<ResolvedSlot>,
|
|
1087
1087
|
pathname: string,
|
|
1088
1088
|
): $ReadOnlyArray<SlotRouteRecord> {
|
|
1089
1089
|
const found: Array<SlotRouteRecord> = [];
|
|
@@ -1138,8 +1138,8 @@ export function interceptingRoutes(
|
|
|
1138
1138
|
*/
|
|
1139
1139
|
export async function resolveInterception(
|
|
1140
1140
|
table: RouteTable,
|
|
1141
|
-
base: ResolvedRoute,
|
|
1142
|
-
url: string,
|
|
1141
|
+
base : ResolvedRoute,
|
|
1142
|
+
url : string,
|
|
1143
1143
|
): Promise<?ResolvedRoute> {
|
|
1144
1144
|
const { pathname, search } = splitUrl(url);
|
|
1145
1145
|
const intercepted: InterceptedUrl = { pathname, searchParams: parseSearch(search) };
|
|
@@ -1179,12 +1179,12 @@ export async function resolveInterception(
|
|
|
1179
1179
|
// arriving. The page underneath has not moved, so its name would say
|
|
1180
1180
|
// nothing about this arrival.
|
|
1181
1181
|
viewTransition: resolveViewTransition(first.page ?? {}, first.layouts),
|
|
1182
|
-
interception: { pathname, search, base },
|
|
1182
|
+
interception : { pathname, search, base },
|
|
1183
1183
|
};
|
|
1184
1184
|
}
|
|
1185
1185
|
|
|
1186
1186
|
async function resolveSlotErrorBoundary(
|
|
1187
|
-
boundary: ?SlotErrorBoundaryLoader,
|
|
1187
|
+
boundary : ?SlotErrorBoundaryLoader,
|
|
1188
1188
|
layoutCount: number,
|
|
1189
1189
|
): Promise<?ResolvedSlotErrorBoundary> {
|
|
1190
1190
|
if (boundary == null) {
|
|
@@ -1258,14 +1258,14 @@ function withoutLoader(module: PageModule, file: string): PageModule {
|
|
|
1258
1258
|
* belongs, when the module is next asked for.
|
|
1259
1259
|
*/
|
|
1260
1260
|
async function resolveTemplates(
|
|
1261
|
-
route: RouteRecord,
|
|
1261
|
+
route : RouteRecord,
|
|
1262
1262
|
layoutCount: number,
|
|
1263
1263
|
): Promise<$ReadOnlyArray<ResolvedTemplate>> {
|
|
1264
1264
|
return resolveTemplateRecords(route.templates ?? [], layoutCount);
|
|
1265
1265
|
}
|
|
1266
1266
|
|
|
1267
1267
|
async function resolveTemplateRecords(
|
|
1268
|
-
records: $ReadOnlyArray<TemplateRecord>,
|
|
1268
|
+
records : $ReadOnlyArray<TemplateRecord>,
|
|
1269
1269
|
layoutCount: number,
|
|
1270
1270
|
): Promise<$ReadOnlyArray<ResolvedTemplate>> {
|
|
1271
1271
|
if (records.length === 0) {
|
|
@@ -1278,7 +1278,7 @@ async function resolveTemplateRecords(
|
|
|
1278
1278
|
// Clamped exactly as the error and loading boundaries' are: a
|
|
1279
1279
|
// `(group)` directory can leave a route with fewer layouts than the
|
|
1280
1280
|
// template declared above it.
|
|
1281
|
-
above: Math.min(record.above, layoutCount),
|
|
1281
|
+
above : Math.min(record.above, layoutCount),
|
|
1282
1282
|
module: await loadOnce(record.module),
|
|
1283
1283
|
};
|
|
1284
1284
|
} catch {
|
|
@@ -1300,14 +1300,14 @@ async function resolveTemplateRecords(
|
|
|
1300
1300
|
* import error surfaces where it belongs, when the module is next asked for.
|
|
1301
1301
|
*/
|
|
1302
1302
|
async function resolveLoading(
|
|
1303
|
-
route: RouteRecord,
|
|
1303
|
+
route : RouteRecord,
|
|
1304
1304
|
layoutCount: number,
|
|
1305
1305
|
): Promise<$ReadOnlyArray<{| readonly above: number, readonly module: LoadingModule |}>> {
|
|
1306
1306
|
return resolveLoadingRecords(route.loading ?? [], layoutCount);
|
|
1307
1307
|
}
|
|
1308
1308
|
|
|
1309
1309
|
async function resolveLoadingRecords(
|
|
1310
|
-
records: $ReadOnlyArray<LoadingRecord>,
|
|
1310
|
+
records : $ReadOnlyArray<LoadingRecord>,
|
|
1311
1311
|
layoutCount: number,
|
|
1312
1312
|
): Promise<$ReadOnlyArray<{| readonly above: number, readonly module: LoadingModule |}>> {
|
|
1313
1313
|
if (records.length === 0) {
|
|
@@ -1320,7 +1320,7 @@ async function resolveLoadingRecords(
|
|
|
1320
1320
|
// Clamped exactly as the error boundary's is, and for the same
|
|
1321
1321
|
// reason: a `(group)` directory can leave a route with fewer layouts
|
|
1322
1322
|
// than the boundary that covers it.
|
|
1323
|
-
above: Math.min(record.above, layoutCount),
|
|
1323
|
+
above : Math.min(record.above, layoutCount),
|
|
1324
1324
|
module: await loadOnce(record.module),
|
|
1325
1325
|
};
|
|
1326
1326
|
} catch {
|
|
@@ -1341,7 +1341,7 @@ async function resolveLoadingRecords(
|
|
|
1341
1341
|
*/
|
|
1342
1342
|
export async function resolveFailure(
|
|
1343
1343
|
table: RouteTable,
|
|
1344
|
-
url: string,
|
|
1344
|
+
url : string,
|
|
1345
1345
|
error: mixed,
|
|
1346
1346
|
): Promise<ResolvedRoute> {
|
|
1347
1347
|
const { pathname, search } = splitUrl(url);
|
|
@@ -1404,8 +1404,8 @@ export function pageSearchParams(resolved: ResolvedRoute): mixed {
|
|
|
1404
1404
|
* inferred.
|
|
1405
1405
|
*/
|
|
1406
1406
|
async function resolveErrorBoundary(
|
|
1407
|
-
table: RouteTable,
|
|
1408
|
-
pathname: string,
|
|
1407
|
+
table : RouteTable,
|
|
1408
|
+
pathname : string,
|
|
1409
1409
|
layoutCount: number,
|
|
1410
1410
|
): Promise<{| readonly module: ?ErrorModule, readonly above: number |}> {
|
|
1411
1411
|
const boundary = nearestBoundary(table.errors, pathname);
|
|
@@ -1444,11 +1444,11 @@ async function resolveErrorBoundary(
|
|
|
1444
1444
|
* the boundary belong to the subtree that just stopped.
|
|
1445
1445
|
*/
|
|
1446
1446
|
async function resolveError(
|
|
1447
|
-
table: RouteTable,
|
|
1448
|
-
pathname: string,
|
|
1449
|
-
search: string,
|
|
1447
|
+
table : RouteTable,
|
|
1448
|
+
pathname : string,
|
|
1449
|
+
search : string,
|
|
1450
1450
|
searchParams: SearchParams,
|
|
1451
|
-
routeError: RouteError,
|
|
1451
|
+
routeError : RouteError,
|
|
1452
1452
|
): Promise<ResolvedRoute> {
|
|
1453
1453
|
const boundary = nearestBoundary(table.errors, pathname);
|
|
1454
1454
|
let module: ?ErrorModule = null;
|
|
@@ -1478,27 +1478,27 @@ async function resolveError(
|
|
|
1478
1478
|
return {
|
|
1479
1479
|
pathname,
|
|
1480
1480
|
search,
|
|
1481
|
-
path: "*",
|
|
1481
|
+
path : "*",
|
|
1482
1482
|
params: {},
|
|
1483
1483
|
searchParams,
|
|
1484
1484
|
page: { default: ResolvedErrorPage },
|
|
1485
1485
|
layouts,
|
|
1486
|
-
data: undefined,
|
|
1486
|
+
data : undefined,
|
|
1487
1487
|
deferred: null,
|
|
1488
1488
|
metadata: declared.title != null ? declared : { ...declared, title: errorTitle(routeError) },
|
|
1489
1489
|
// The boundary's own layouts may name one; the page cannot, because the
|
|
1490
1490
|
// page here is this module's. An error arriving under the section's
|
|
1491
1491
|
// transition is the same answer as a page arriving under it.
|
|
1492
1492
|
viewTransition: resolveViewTransition({}, layouts),
|
|
1493
|
-
status: routeErrorStatus(routeError),
|
|
1494
|
-
error: routeError,
|
|
1493
|
+
status : routeErrorStatus(routeError),
|
|
1494
|
+
error : routeError,
|
|
1495
1495
|
// All of the boundary's layouts are above it, and no inner boundary is
|
|
1496
1496
|
// inserted around a page that already is one; see `RouteView`.
|
|
1497
1497
|
errorBoundary: { module, above: layouts.length },
|
|
1498
1498
|
// An error page has nothing left to wait for: it renders the value it was
|
|
1499
1499
|
// resolved with. A fallback around it would be a boundary that can never
|
|
1500
1500
|
// show, which is worse than none.
|
|
1501
|
-
loading: [],
|
|
1501
|
+
loading : [],
|
|
1502
1502
|
templates: [],
|
|
1503
1503
|
// And slots for the third time: a slot belongs to the segment the walk went
|
|
1504
1504
|
// through, and an error page is matched rather than walked to. A layout
|
|
@@ -1536,9 +1536,9 @@ async function resolveError(
|
|
|
1536
1536
|
* layout still applies to the 404.
|
|
1537
1537
|
*/
|
|
1538
1538
|
async function resolveNotFound(
|
|
1539
|
-
table: RouteTable,
|
|
1540
|
-
pathname: string,
|
|
1541
|
-
search: string,
|
|
1539
|
+
table : RouteTable,
|
|
1540
|
+
pathname : string,
|
|
1541
|
+
search : string,
|
|
1542
1542
|
searchParams: SearchParams,
|
|
1543
1543
|
): Promise<ResolvedRoute> {
|
|
1544
1544
|
const record = nearestBoundary(table.notFound, pathname);
|
|
@@ -1557,17 +1557,17 @@ async function resolveNotFound(
|
|
|
1557
1557
|
return {
|
|
1558
1558
|
pathname,
|
|
1559
1559
|
search,
|
|
1560
|
-
path: "*",
|
|
1560
|
+
path : "*",
|
|
1561
1561
|
params: {},
|
|
1562
1562
|
searchParams,
|
|
1563
1563
|
page,
|
|
1564
1564
|
layouts,
|
|
1565
|
-
data: undefined,
|
|
1565
|
+
data : undefined,
|
|
1566
1566
|
deferred: null,
|
|
1567
1567
|
metadata,
|
|
1568
1568
|
viewTransition: resolveViewTransition(page, layouts),
|
|
1569
|
-
status: 404,
|
|
1570
|
-
error: null,
|
|
1569
|
+
status : 404,
|
|
1570
|
+
error : null,
|
|
1571
1571
|
// A not-found page is a page: one that throws is contained like any other.
|
|
1572
1572
|
errorBoundary: await resolveErrorBoundary(table, pathname, layouts.length),
|
|
1573
1573
|
// A not-found boundary is matched, not nested: `nearestBoundary` picked one
|
|
@@ -1590,9 +1590,9 @@ async function resolveNotFound(
|
|
|
1590
1590
|
* rather than a correction; [`Metadata`] has the argument.
|
|
1591
1591
|
*/
|
|
1592
1592
|
async function resolveMetadata(
|
|
1593
|
-
page: PageModule,
|
|
1593
|
+
page : PageModule,
|
|
1594
1594
|
layouts: $ReadOnlyArray<LayoutModule>,
|
|
1595
|
-
args: MetadataArgs,
|
|
1595
|
+
args : MetadataArgs,
|
|
1596
1596
|
): Promise<Metadata> {
|
|
1597
1597
|
let merged: Metadata = {};
|
|
1598
1598
|
let structured: $ReadOnlyArray<JsonLd> = [];
|
|
@@ -1646,7 +1646,7 @@ type Transitioning = { readonly viewTransition?: string, ... };
|
|
|
1646
1646
|
* type would be a claim it does not need and cannot use.
|
|
1647
1647
|
*/
|
|
1648
1648
|
function resolveViewTransition(
|
|
1649
|
-
page: Transitioning,
|
|
1649
|
+
page : Transitioning,
|
|
1650
1650
|
layouts: $ReadOnlyArray<Transitioning>,
|
|
1651
1651
|
): ?string {
|
|
1652
1652
|
let name: ?string = null;
|
|
@@ -1672,9 +1672,9 @@ component DefaultNotFound() {
|
|
|
1672
1672
|
export function errorTitle(error: RouteError): string {
|
|
1673
1673
|
return match (error) {
|
|
1674
1674
|
{kind: "badRequest", ...} => "Bad request",
|
|
1675
|
-
{kind: "unauthorized"}
|
|
1676
|
-
{kind: "forbidden"}
|
|
1677
|
-
{kind: "thrown", ...}
|
|
1675
|
+
{kind: "unauthorized"} => "Sign in required",
|
|
1676
|
+
{kind: "forbidden"} => "Not allowed",
|
|
1677
|
+
{kind: "thrown", ...} => "Something went wrong",
|
|
1678
1678
|
};
|
|
1679
1679
|
}
|
|
1680
1680
|
|