@richie-router/react 0.1.4 → 0.1.6
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/dist/cjs/router.cjs +2 -2
- package/dist/cjs/router.test.cjs +75 -0
- package/dist/esm/router.mjs +4 -3
- package/dist/esm/router.test.mjs +75 -0
- package/dist/types/router.d.ts +0 -1
- package/package.json +2 -2
package/dist/cjs/router.cjs
CHANGED
|
@@ -541,7 +541,7 @@ class Router {
|
|
|
541
541
|
return response.head;
|
|
542
542
|
}
|
|
543
543
|
async fetchRouteHead(route, params, search) {
|
|
544
|
-
const basePath = this.
|
|
544
|
+
const basePath = prependBasePathToHref(import_core.resolveHostedRoutingConfig(this.routeTree.hostedRouting).headBasePath, this.basePath);
|
|
545
545
|
const searchParams = new URLSearchParams({
|
|
546
546
|
routeId: route.fullPath,
|
|
547
547
|
params: JSON.stringify(params),
|
|
@@ -557,7 +557,7 @@ class Router {
|
|
|
557
557
|
return await response.json();
|
|
558
558
|
}
|
|
559
559
|
async fetchDocumentHead(location) {
|
|
560
|
-
const basePath = this.
|
|
560
|
+
const basePath = prependBasePathToHref(import_core.resolveHostedRoutingConfig(this.routeTree.hostedRouting).headBasePath, this.basePath);
|
|
561
561
|
const searchParams = new URLSearchParams({
|
|
562
562
|
href: prependBasePathToHref(location.href, this.basePath)
|
|
563
563
|
});
|
package/dist/cjs/router.test.cjs
CHANGED
|
@@ -45,6 +45,12 @@ function createTestRouteTree(options) {
|
|
|
45
45
|
component: () => null
|
|
46
46
|
});
|
|
47
47
|
aboutRoute._setServerHead(options?.serverHead);
|
|
48
|
+
if (options?.headBasePath) {
|
|
49
|
+
rootRoute._setHostedRouting({
|
|
50
|
+
headBasePath: options.headBasePath,
|
|
51
|
+
passthrough: [options.headBasePath]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
48
54
|
return rootRoute._addFileChildren({
|
|
49
55
|
index: indexRoute,
|
|
50
56
|
about: aboutRoute
|
|
@@ -129,6 +135,21 @@ function createLinkTestRouteTree(component) {
|
|
|
129
135
|
posts: postsRoute
|
|
130
136
|
});
|
|
131
137
|
}
|
|
138
|
+
function createStaticAndDynamicSiblingRouteTree() {
|
|
139
|
+
const rootRoute = import_router.createRootRoute({
|
|
140
|
+
component: () => null
|
|
141
|
+
});
|
|
142
|
+
const registerRoute = import_router.createFileRoute("/register")({
|
|
143
|
+
component: () => null
|
|
144
|
+
});
|
|
145
|
+
const usernameRoute = import_router.createFileRoute("/$username")({
|
|
146
|
+
component: () => null
|
|
147
|
+
});
|
|
148
|
+
return rootRoute._addFileChildren({
|
|
149
|
+
register: registerRoute,
|
|
150
|
+
username: usernameRoute
|
|
151
|
+
});
|
|
152
|
+
}
|
|
132
153
|
function renderLinkMarkup(initialEntry, component) {
|
|
133
154
|
const history = import_router.createMemoryHistory({
|
|
134
155
|
initialEntries: [initialEntry]
|
|
@@ -234,6 +255,38 @@ import_bun_test.describe("createRouter basePath", () => {
|
|
|
234
255
|
globalThis.fetch = originalFetch;
|
|
235
256
|
}
|
|
236
257
|
});
|
|
258
|
+
import_bun_test.test("uses the route tree headBasePath for document head requests", async () => {
|
|
259
|
+
const history = import_router.createMemoryHistory({
|
|
260
|
+
initialEntries: ["/project/about"]
|
|
261
|
+
});
|
|
262
|
+
const fetchCalls = [];
|
|
263
|
+
const originalFetch = globalThis.fetch;
|
|
264
|
+
globalThis.fetch = async (input) => {
|
|
265
|
+
fetchCalls.push(typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url);
|
|
266
|
+
return new Response(JSON.stringify({
|
|
267
|
+
head: [],
|
|
268
|
+
routeHeads: [
|
|
269
|
+
{ routeId: "/about", head: [] }
|
|
270
|
+
]
|
|
271
|
+
}), {
|
|
272
|
+
status: 200,
|
|
273
|
+
headers: {
|
|
274
|
+
"content-type": "application/json"
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
try {
|
|
279
|
+
const router = import_router.createRouter({
|
|
280
|
+
routeTree: createTestRouteTree({ serverHead: true, headBasePath: "/meta" }),
|
|
281
|
+
history,
|
|
282
|
+
basePath: "/project"
|
|
283
|
+
});
|
|
284
|
+
await router.load();
|
|
285
|
+
import_bun_test.expect(fetchCalls).toEqual(["/project/meta?href=%2Fproject%2Fabout"]);
|
|
286
|
+
} finally {
|
|
287
|
+
globalThis.fetch = originalFetch;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
237
290
|
import_bun_test.test("uses one document head request and preserves inline head precedence", async () => {
|
|
238
291
|
const history = import_router.createMemoryHistory({
|
|
239
292
|
initialEntries: ["/posts/alpha"]
|
|
@@ -534,6 +587,28 @@ import_bun_test.describe("Link active state", () => {
|
|
|
534
587
|
import_bun_test.expect(markup).not.toContain('class="active"');
|
|
535
588
|
});
|
|
536
589
|
});
|
|
590
|
+
import_bun_test.describe("route matching precedence", () => {
|
|
591
|
+
import_bun_test.test("prefers a static sibling over a dynamic sibling", () => {
|
|
592
|
+
const router = import_router.createRouter({
|
|
593
|
+
routeTree: createStaticAndDynamicSiblingRouteTree(),
|
|
594
|
+
history: import_router.createMemoryHistory({
|
|
595
|
+
initialEntries: ["/register"]
|
|
596
|
+
})
|
|
597
|
+
});
|
|
598
|
+
import_bun_test.expect(router.state.matches.at(-1)?.route.fullPath).toBe("/register");
|
|
599
|
+
import_bun_test.expect(router.state.matches.at(-1)?.params).toEqual({});
|
|
600
|
+
});
|
|
601
|
+
import_bun_test.test("falls back to the dynamic sibling when no static sibling matches", () => {
|
|
602
|
+
const router = import_router.createRouter({
|
|
603
|
+
routeTree: createStaticAndDynamicSiblingRouteTree(),
|
|
604
|
+
history: import_router.createMemoryHistory({
|
|
605
|
+
initialEntries: ["/richie"]
|
|
606
|
+
})
|
|
607
|
+
});
|
|
608
|
+
import_bun_test.expect(router.state.matches.at(-1)?.route.fullPath).toBe("/$username");
|
|
609
|
+
import_bun_test.expect(router.state.matches.at(-1)?.params).toEqual({ username: "richie" });
|
|
610
|
+
});
|
|
611
|
+
});
|
|
537
612
|
import_bun_test.describe("useMatchRoute", () => {
|
|
538
613
|
import_bun_test.test("returns matched params for exact matches", () => {
|
|
539
614
|
const markup = renderLinkMarkup("/posts/alpha", () => {
|
package/dist/esm/router.mjs
CHANGED
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
matchRouteTree,
|
|
15
15
|
notFound,
|
|
16
16
|
redirect,
|
|
17
|
-
resolveHeadConfig
|
|
17
|
+
resolveHeadConfig,
|
|
18
|
+
resolveHostedRoutingConfig
|
|
18
19
|
} from "@richie-router/core";
|
|
19
20
|
import {
|
|
20
21
|
createBrowserHistory,
|
|
@@ -464,7 +465,7 @@ class Router {
|
|
|
464
465
|
return response.head;
|
|
465
466
|
}
|
|
466
467
|
async fetchRouteHead(route, params, search) {
|
|
467
|
-
const basePath = this.
|
|
468
|
+
const basePath = prependBasePathToHref(resolveHostedRoutingConfig(this.routeTree.hostedRouting).headBasePath, this.basePath);
|
|
468
469
|
const searchParams = new URLSearchParams({
|
|
469
470
|
routeId: route.fullPath,
|
|
470
471
|
params: JSON.stringify(params),
|
|
@@ -480,7 +481,7 @@ class Router {
|
|
|
480
481
|
return await response.json();
|
|
481
482
|
}
|
|
482
483
|
async fetchDocumentHead(location) {
|
|
483
|
-
const basePath = this.
|
|
484
|
+
const basePath = prependBasePathToHref(resolveHostedRoutingConfig(this.routeTree.hostedRouting).headBasePath, this.basePath);
|
|
484
485
|
const searchParams = new URLSearchParams({
|
|
485
486
|
href: prependBasePathToHref(location.href, this.basePath)
|
|
486
487
|
});
|
package/dist/esm/router.test.mjs
CHANGED
|
@@ -23,6 +23,12 @@ function createTestRouteTree(options) {
|
|
|
23
23
|
component: () => null
|
|
24
24
|
});
|
|
25
25
|
aboutRoute._setServerHead(options?.serverHead);
|
|
26
|
+
if (options?.headBasePath) {
|
|
27
|
+
rootRoute._setHostedRouting({
|
|
28
|
+
headBasePath: options.headBasePath,
|
|
29
|
+
passthrough: [options.headBasePath]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
26
32
|
return rootRoute._addFileChildren({
|
|
27
33
|
index: indexRoute,
|
|
28
34
|
about: aboutRoute
|
|
@@ -107,6 +113,21 @@ function createLinkTestRouteTree(component) {
|
|
|
107
113
|
posts: postsRoute
|
|
108
114
|
});
|
|
109
115
|
}
|
|
116
|
+
function createStaticAndDynamicSiblingRouteTree() {
|
|
117
|
+
const rootRoute = createRootRoute({
|
|
118
|
+
component: () => null
|
|
119
|
+
});
|
|
120
|
+
const registerRoute = createFileRoute("/register")({
|
|
121
|
+
component: () => null
|
|
122
|
+
});
|
|
123
|
+
const usernameRoute = createFileRoute("/$username")({
|
|
124
|
+
component: () => null
|
|
125
|
+
});
|
|
126
|
+
return rootRoute._addFileChildren({
|
|
127
|
+
register: registerRoute,
|
|
128
|
+
username: usernameRoute
|
|
129
|
+
});
|
|
130
|
+
}
|
|
110
131
|
function renderLinkMarkup(initialEntry, component) {
|
|
111
132
|
const history = createMemoryHistory({
|
|
112
133
|
initialEntries: [initialEntry]
|
|
@@ -212,6 +233,38 @@ describe("createRouter basePath", () => {
|
|
|
212
233
|
globalThis.fetch = originalFetch;
|
|
213
234
|
}
|
|
214
235
|
});
|
|
236
|
+
test("uses the route tree headBasePath for document head requests", async () => {
|
|
237
|
+
const history = createMemoryHistory({
|
|
238
|
+
initialEntries: ["/project/about"]
|
|
239
|
+
});
|
|
240
|
+
const fetchCalls = [];
|
|
241
|
+
const originalFetch = globalThis.fetch;
|
|
242
|
+
globalThis.fetch = async (input) => {
|
|
243
|
+
fetchCalls.push(typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url);
|
|
244
|
+
return new Response(JSON.stringify({
|
|
245
|
+
head: [],
|
|
246
|
+
routeHeads: [
|
|
247
|
+
{ routeId: "/about", head: [] }
|
|
248
|
+
]
|
|
249
|
+
}), {
|
|
250
|
+
status: 200,
|
|
251
|
+
headers: {
|
|
252
|
+
"content-type": "application/json"
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
try {
|
|
257
|
+
const router = createRouter({
|
|
258
|
+
routeTree: createTestRouteTree({ serverHead: true, headBasePath: "/meta" }),
|
|
259
|
+
history,
|
|
260
|
+
basePath: "/project"
|
|
261
|
+
});
|
|
262
|
+
await router.load();
|
|
263
|
+
expect(fetchCalls).toEqual(["/project/meta?href=%2Fproject%2Fabout"]);
|
|
264
|
+
} finally {
|
|
265
|
+
globalThis.fetch = originalFetch;
|
|
266
|
+
}
|
|
267
|
+
});
|
|
215
268
|
test("uses one document head request and preserves inline head precedence", async () => {
|
|
216
269
|
const history = createMemoryHistory({
|
|
217
270
|
initialEntries: ["/posts/alpha"]
|
|
@@ -512,6 +565,28 @@ describe("Link active state", () => {
|
|
|
512
565
|
expect(markup).not.toContain('class="active"');
|
|
513
566
|
});
|
|
514
567
|
});
|
|
568
|
+
describe("route matching precedence", () => {
|
|
569
|
+
test("prefers a static sibling over a dynamic sibling", () => {
|
|
570
|
+
const router = createRouter({
|
|
571
|
+
routeTree: createStaticAndDynamicSiblingRouteTree(),
|
|
572
|
+
history: createMemoryHistory({
|
|
573
|
+
initialEntries: ["/register"]
|
|
574
|
+
})
|
|
575
|
+
});
|
|
576
|
+
expect(router.state.matches.at(-1)?.route.fullPath).toBe("/register");
|
|
577
|
+
expect(router.state.matches.at(-1)?.params).toEqual({});
|
|
578
|
+
});
|
|
579
|
+
test("falls back to the dynamic sibling when no static sibling matches", () => {
|
|
580
|
+
const router = createRouter({
|
|
581
|
+
routeTree: createStaticAndDynamicSiblingRouteTree(),
|
|
582
|
+
history: createMemoryHistory({
|
|
583
|
+
initialEntries: ["/richie"]
|
|
584
|
+
})
|
|
585
|
+
});
|
|
586
|
+
expect(router.state.matches.at(-1)?.route.fullPath).toBe("/$username");
|
|
587
|
+
expect(router.state.matches.at(-1)?.params).toEqual({ username: "richie" });
|
|
588
|
+
});
|
|
589
|
+
});
|
|
515
590
|
describe("useMatchRoute", () => {
|
|
516
591
|
test("returns matched params for exact matches", () => {
|
|
517
592
|
const markup = renderLinkMarkup("/posts/alpha", () => {
|
package/dist/types/router.d.ts
CHANGED
|
@@ -150,7 +150,6 @@ export interface RouterOptions<TRouteTree extends AnyRoute> {
|
|
|
150
150
|
defaultErrorComponent?: AnyComponent;
|
|
151
151
|
scrollRestoration?: boolean;
|
|
152
152
|
scrollToTopSelectors?: string[];
|
|
153
|
-
headBasePath?: string;
|
|
154
153
|
trailingSlash?: 'always' | 'never' | 'preserve';
|
|
155
154
|
parseSearch?: (searchStr: string) => Record<string, unknown>;
|
|
156
155
|
stringifySearch?: (search: Record<string, unknown>) => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@richie-router/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "React runtime, components, and hooks for Richie Router",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@richie-router/core": "^0.1.
|
|
16
|
+
"@richie-router/core": "^0.1.5"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"react": "^19"
|