@rangojs/router 0.12.2 → 0.12.4
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/types/client-urls/server-projection.d.ts +8 -0
- package/dist/types/urls/include-provider.d.ts +9 -4
- package/dist/types/urls/path-helper-types.d.ts +5 -3
- package/dist/vite/index.js +1 -1
- package/package.json +5 -5
- package/skills/client-urls/SKILL.md +4 -0
- package/skills/view-transitions/SKILL.md +25 -7
- package/src/client-urls/server-projection.ts +13 -0
- package/src/router.ts +2 -8
- package/src/segment-system.tsx +4 -3
- package/src/urls/include-helper.ts +6 -10
- package/src/urls/include-provider.ts +26 -7
- package/src/urls/path-helper-types.ts +9 -2
|
@@ -54,6 +54,14 @@ export interface ClientUrlProjection {
|
|
|
54
54
|
export declare function serializeClientUrlPatterns(patterns: ClientUrlPatterns): ClientUrlProjection;
|
|
55
55
|
export declare function isClientUrlPatterns(value: unknown): value is ClientUrlPatterns;
|
|
56
56
|
export declare function isClientUrlReference(value: unknown): value is ClientUrlReference;
|
|
57
|
+
/**
|
|
58
|
+
* A clientUrls() definition object or, on the server, its client reference.
|
|
59
|
+
* Run this BEFORE any duck-typing of the value (`typeof === "function"`,
|
|
60
|
+
* `.handler` reads): a client reference is a callable Proxy that throws on
|
|
61
|
+
* unknown property reads, so a later shape check would either invoke it as a
|
|
62
|
+
* thunk or surface React's "cannot dot into a client module" error.
|
|
63
|
+
*/
|
|
64
|
+
export declare function isClientUrlSource(value: unknown): value is ClientUrlDefinitionSource;
|
|
57
65
|
export declare function setClientUrlProjection(reference: string | ClientUrlReference, projection: ClientUrlProjection): void;
|
|
58
66
|
export declare function getClientUrlProjection(reference: string | ClientUrlReference): ClientUrlProjection | undefined;
|
|
59
67
|
export declare function clearClientUrlProjections(): void;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { UrlPatterns } from "./pattern-types.js";
|
|
2
|
+
import type { ClientUrlPatterns } from "../client-urls/types.js";
|
|
2
3
|
/**
|
|
3
4
|
* What an async `include()` provider may resolve to: a `urls()` value directly,
|
|
4
5
|
* or a module namespace whose `default` export is a `urls()` value (the shape
|
|
5
6
|
* produced by `() => import("./routes")` when the route module does
|
|
6
|
-
* `export default urls(...)`).
|
|
7
|
+
* `export default urls(...)`). A `clientUrls()` module resolves the same way
|
|
8
|
+
* (`() => import("./shop.client")`); on the server its `default` is the client
|
|
9
|
+
* reference, adapted exactly as the eager `include(prefix, clientUrlsDefault)`
|
|
10
|
+
* form.
|
|
7
11
|
*/
|
|
8
|
-
export type IncludeModule<TEnv = any> = UrlPatterns<TEnv> | {
|
|
9
|
-
default: UrlPatterns<TEnv
|
|
12
|
+
export type IncludeModule<TEnv = any> = UrlPatterns<TEnv> | ClientUrlPatterns | {
|
|
13
|
+
default: UrlPatterns<TEnv> | ClientUrlPatterns;
|
|
10
14
|
};
|
|
11
15
|
/**
|
|
12
16
|
* An async/lazy include provider: a thunk returning a `urls()` value (or a
|
|
@@ -22,6 +26,7 @@ export type IncludeProvider<TEnv = any> = () => IncludeModule<TEnv> | Promise<In
|
|
|
22
26
|
export declare function isIncludeProvider(value: unknown): value is IncludeProvider;
|
|
23
27
|
/**
|
|
24
28
|
* Normalize an async provider's resolved value to a `UrlPatterns`. Accepts a
|
|
25
|
-
* `urls()` value directly or a module whose `default` export is
|
|
29
|
+
* `urls()`/`clientUrls()` value directly or a module whose `default` export is
|
|
30
|
+
* one.
|
|
26
31
|
*/
|
|
27
32
|
export declare function resolveIncludeModule<TEnv = any>(mod: IncludeModule<TEnv>, id?: string): UrlPatterns<TEnv>;
|
|
@@ -40,10 +40,12 @@ export type TextResponsePathFn<TEnv> = <const TPattern extends string, const TNa
|
|
|
40
40
|
/**
|
|
41
41
|
* What an async include() provider resolves to. Route types (`TRoutes`) are
|
|
42
42
|
* inferred from the resolved `urls()` value so `href()` and named routes stay
|
|
43
|
-
* type-safe through a code-split module (`() => import("./routes")`).
|
|
43
|
+
* type-safe through a code-split module (`() => import("./routes")`). A
|
|
44
|
+
* clientUrls() module's default export types as ClientUrlPatterns, so
|
|
45
|
+
* `() => import("./shop.client")` infers the group's names the same way.
|
|
44
46
|
*/
|
|
45
|
-
type IncludeResolved<TEnv, TRoutes extends Record<string, any>, TResponses extends Record<string, unknown>> = UrlPatterns<TEnv, TRoutes, TResponses> | {
|
|
46
|
-
default: UrlPatterns<TEnv, TRoutes, TResponses>;
|
|
47
|
+
type IncludeResolved<TEnv, TRoutes extends Record<string, any>, TResponses extends Record<string, unknown>> = UrlPatterns<TEnv, TRoutes, TResponses> | ClientUrlPatterns<TRoutes> | {
|
|
48
|
+
default: UrlPatterns<TEnv, TRoutes, TResponses> | ClientUrlPatterns<TRoutes>;
|
|
47
49
|
};
|
|
48
50
|
/** include() argument: an eager `urls()` value or an async provider thunk. */
|
|
49
51
|
export type IncludeArg<TEnv, TRoutes extends Record<string, any>, TResponses extends Record<string, unknown>> = UrlPatterns<TEnv, TRoutes, TResponses> | ClientUrlPatterns<TRoutes> | (() => IncludeResolved<TEnv, TRoutes, TResponses> | Promise<IncludeResolved<TEnv, TRoutes, TResponses>>);
|
package/dist/vite/index.js
CHANGED
|
@@ -3746,7 +3746,7 @@ import { resolve } from "node:path";
|
|
|
3746
3746
|
// package.json
|
|
3747
3747
|
var package_default = {
|
|
3748
3748
|
name: "@rangojs/router",
|
|
3749
|
-
version: "0.12.
|
|
3749
|
+
version: "0.12.4",
|
|
3750
3750
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
3751
3751
|
keywords: [
|
|
3752
3752
|
"react",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rangojs/router",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.4",
|
|
4
4
|
"description": "Django-inspired RSC router with composable URL patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -201,13 +201,13 @@
|
|
|
201
201
|
"@testing-library/dom": "^10.4.1",
|
|
202
202
|
"@testing-library/react": "^16.3.2",
|
|
203
203
|
"@types/node": "^24.10.1",
|
|
204
|
-
"@types/react": "^19.
|
|
205
|
-
"@types/react-dom": "^19.
|
|
204
|
+
"@types/react": "^19.3.0",
|
|
205
|
+
"@types/react-dom": "^19.3.0",
|
|
206
206
|
"esbuild": "^0.28.1",
|
|
207
207
|
"happy-dom": "^20.10.1",
|
|
208
208
|
"jiti": "^2.7.0",
|
|
209
|
-
"react": "^19.
|
|
210
|
-
"react-dom": "^19.
|
|
209
|
+
"react": "^19.3.0",
|
|
210
|
+
"react-dom": "^19.3.0",
|
|
211
211
|
"vitest": "^4.1.9",
|
|
212
212
|
"@shared/e2e": "0.0.1"
|
|
213
213
|
},
|
|
@@ -112,6 +112,10 @@ import shopUrls from "./shop.client.js";
|
|
|
112
112
|
include("/shop", shopUrls, { name: "shop" });
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
The async form works without a server wrapper module too:
|
|
116
|
+
`include("/shop", () => import("./shop.client.js"), { name: "shop" })` — same
|
|
117
|
+
behavior, no startup win, uniform with code-split server groups.
|
|
118
|
+
|
|
115
119
|
Route names compose through the include (`shop.index`, `shop.product`) and
|
|
116
120
|
flow into the generated route map, so `href`/`reverse` and `Handler<"...">`
|
|
117
121
|
typing work exactly as for server routes (`/typesafety`).
|
|
@@ -9,9 +9,9 @@ argument-hint: [layout|route|parallel|intercept]
|
|
|
9
9
|
`transition()` opts a route (or group of routes) into transition-driven navigation. It does two things, and you choose how far to go:
|
|
10
10
|
|
|
11
11
|
1. **`startTransition` (the foundation).** The navigation commit is driven through React's `startTransition`. That holds the previous content across a same-route navigation (stale-while-revalidate — no loading-skeleton flash) and is the **precondition** for any view-transition animation. Works on **all** React versions.
|
|
12
|
-
2. **`<ViewTransition>` (the animation, layered on top).** On experimental
|
|
12
|
+
2. **`<ViewTransition>` (the animation, layered on top).** On React 19.3+ (or an experimental build), rango also wraps the segment content in React's `<ViewTransition>` so the swap cross-fades/morphs. This is the only part that needs 19.3+; pass `viewTransition: false` to keep #1 without it (and place your own `<ViewTransition>` where you want it).
|
|
13
13
|
|
|
14
|
-
> The `<ViewTransition>` layer requires React
|
|
14
|
+
> The `<ViewTransition>` layer requires a React that exports `<ViewTransition>` / `addTransitionType`: stable 19.3+ or an experimental build. Rango feature-detects it; on React 19.2 that layer is a no-op — but the `startTransition` driving (content hold) still applies.
|
|
15
15
|
|
|
16
16
|
## Purpose: `startTransition` vs `<ViewTransition>`
|
|
17
17
|
|
|
@@ -24,11 +24,11 @@ These are two **independent** mechanisms. `startTransition` controls _fallbacks_
|
|
|
24
24
|
|
|
25
25
|
The bottom-left cell is the key constraint: a view transition cannot exist without a `startTransition`. So once you reach for `transition()`, the only real choice is _startTransition_ vs _startTransition + ViewTransition_:
|
|
26
26
|
|
|
27
|
-
| What you want | Config | Effect
|
|
28
|
-
| -------------------------------------- | --------------------------------------------------- |
|
|
29
|
-
| nothing (default nav) | no `transition()` | remount + skeleton on param change
|
|
30
|
-
| `startTransition` only | `transition({ viewTransition: false })` | hold content; place your own `<ViewTransition>` where you want it
|
|
31
|
-
| `startTransition` + `<ViewTransition>` | `transition({})` / `transition({ enter, exit, … })` | hold + router cross-fade (experimental
|
|
27
|
+
| What you want | Config | Effect |
|
|
28
|
+
| -------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
29
|
+
| nothing (default nav) | no `transition()` | remount + skeleton on param change |
|
|
30
|
+
| `startTransition` only | `transition({ viewTransition: false })` | hold content; place your own `<ViewTransition>` where you want it |
|
|
31
|
+
| `startTransition` + `<ViewTransition>` | `transition({})` / `transition({ enter, exit, … })` | hold + router cross-fade (React 19.3+ or experimental; on 19.2 it degrades to the `startTransition`-only row) |
|
|
32
32
|
|
|
33
33
|
`createRouter({ viewTransition: "auto" \| false })` sets the app-wide default for the third row; a per-segment `viewTransition` wins. See [Opting out of the router boundary](#opting-out-of-the-router-boundary-place-your-own-viewtransition) for the full opt-out story.
|
|
34
34
|
|
|
@@ -322,6 +322,24 @@ On stable React the "VT" column is always a no-op (there is no `<ViewTransition>
|
|
|
322
322
|
|
|
323
323
|
> On **stable** React there is no `<ViewTransition>` at all, so `viewTransition: false` is visually a no-op there — but the startTransition driving and content-hold still apply, identical to `transition({})`.
|
|
324
324
|
|
|
325
|
+
## Testing a transition() route
|
|
326
|
+
|
|
327
|
+
On React 19.3+ a transition commit briefly keeps the exiting `<ViewTransition>`
|
|
328
|
+
host in the DOM next to the entering one (hidden, carrying React's `vt-*`
|
|
329
|
+
attributes) for a few hundred milliseconds. A strict Playwright locator on a
|
|
330
|
+
test id that exists in both the old and the new view (same route, different
|
|
331
|
+
params; a hard load followed by a revalidation commit) resolves to two elements
|
|
332
|
+
during that window. Target the entering host, which is appended after the
|
|
333
|
+
exiting one:
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
const page$ = page.getByTestId("feature-page").last();
|
|
337
|
+
await expect(page$).toBeVisible();
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Waiting for `toHaveCount(1)` first is not enough: the count passes through 1
|
|
341
|
+
before the second host is inserted.
|
|
342
|
+
|
|
325
343
|
## Recommendations
|
|
326
344
|
|
|
327
345
|
**Put `<ParallelOutlet />` in layouts, not routes.** A route-level `transition` wraps the route component itself, so a `<ParallelOutlet />` rendered directly inside that route component remains inside the route VT subtree — modal opens on a route with a parallel outlet _will_ trigger the route's VT walker. The narrowing fix only applies at layout boundaries. If you combine intercept modals with route-level transitions, mount the slot one level up in a layout.
|
|
@@ -359,6 +359,19 @@ export function isClientUrlReference(
|
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
+
/**
|
|
363
|
+
* A clientUrls() definition object or, on the server, its client reference.
|
|
364
|
+
* Run this BEFORE any duck-typing of the value (`typeof === "function"`,
|
|
365
|
+
* `.handler` reads): a client reference is a callable Proxy that throws on
|
|
366
|
+
* unknown property reads, so a later shape check would either invoke it as a
|
|
367
|
+
* thunk or surface React's "cannot dot into a client module" error.
|
|
368
|
+
*/
|
|
369
|
+
export function isClientUrlSource(
|
|
370
|
+
value: unknown,
|
|
371
|
+
): value is ClientUrlDefinitionSource {
|
|
372
|
+
return isClientUrlPatterns(value) || isClientUrlReference(value);
|
|
373
|
+
}
|
|
374
|
+
|
|
362
375
|
/**
|
|
363
376
|
* Strip vite's HMR timestamp query from a module id. After an HMR update of
|
|
364
377
|
* a clientUrls module, the RSC graph re-imports it under
|
package/src/router.ts
CHANGED
|
@@ -3,10 +3,7 @@ import { createCacheScope } from "./cache/cache-scope.js";
|
|
|
3
3
|
import { resolveCacheProfiles } from "./cache/profile-registry.js";
|
|
4
4
|
import { isCachedFunction } from "./cache/taint.js";
|
|
5
5
|
import { assertClientComponent } from "./component-utils.js";
|
|
6
|
-
import {
|
|
7
|
-
isClientUrlPatterns,
|
|
8
|
-
isClientUrlReference,
|
|
9
|
-
} from "./client-urls/server-projection.js";
|
|
6
|
+
import { isClientUrlSource } from "./client-urls/server-projection.js";
|
|
10
7
|
import type { ClientUrlPatterns } from "./client-urls/types.js";
|
|
11
8
|
import { DefaultDocument } from "./components/DefaultDocument.js";
|
|
12
9
|
import type { SerializedManifest } from "./debug.js";
|
|
@@ -784,10 +781,7 @@ export function createRouter<TEnv = any>(
|
|
|
784
781
|
// same lazy include materialization, so no ordering, one-definition, or
|
|
785
782
|
// deferral rules exist. Prefixing, wrapping RSC layouts, and middleware
|
|
786
783
|
// scope still come from mounting through include() in urls() yourself.
|
|
787
|
-
if (
|
|
788
|
-
isClientUrlPatterns(patternsOrBuilder) ||
|
|
789
|
-
isClientUrlReference(patternsOrBuilder)
|
|
790
|
-
) {
|
|
784
|
+
if (isClientUrlSource(patternsOrBuilder)) {
|
|
791
785
|
const clientSource = patternsOrBuilder as ClientUrlPatterns;
|
|
792
786
|
patternsOrBuilder = urls(({ include }) => [
|
|
793
787
|
include("/", clientSource, { name: "" }),
|
package/src/segment-system.tsx
CHANGED
|
@@ -40,8 +40,9 @@ function segDebugLog(msg: string, details?: Record<string, unknown>): void {
|
|
|
40
40
|
console.log(prefix);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// ViewTransition
|
|
44
|
-
//
|
|
43
|
+
// ViewTransition ships in React 19.3+ (and experimental builds); older stable
|
|
44
|
+
// releases lack it. Feature-detect via the namespace import so the router
|
|
45
|
+
// compiles against any supported React and degrades to a no-op boundary.
|
|
45
46
|
const ReactViewTransition: any =
|
|
46
47
|
"ViewTransition" in React ? (React as any).ViewTransition : null;
|
|
47
48
|
|
|
@@ -435,7 +436,7 @@ export async function renderSegments(
|
|
|
435
436
|
nodeContent = registerLazyRef(resolvedComponent);
|
|
436
437
|
}
|
|
437
438
|
|
|
438
|
-
// Wrap with <ViewTransition> if transition config exists (React experimental
|
|
439
|
+
// Wrap with <ViewTransition> if transition config exists (React 19.3+ / experimental).
|
|
439
440
|
// An empty config ({}) creates a bare <ViewTransition> boundary that participates
|
|
440
441
|
// in transitions without adding custom animation classes. Named element-level
|
|
441
442
|
// <ViewTransition> components inside (with name/share props) morph independently
|
|
@@ -13,8 +13,7 @@ import type { IncludeProvider } from "./include-provider.js";
|
|
|
13
13
|
import type { IncludeFn } from "./path-helper-types.js";
|
|
14
14
|
import {
|
|
15
15
|
clientUrlIncludePatterns,
|
|
16
|
-
|
|
17
|
-
isClientUrlReference,
|
|
16
|
+
isClientUrlSource,
|
|
18
17
|
} from "../client-urls/server-projection.js";
|
|
19
18
|
import type { ClientUrlPatterns } from "../client-urls/types.js";
|
|
20
19
|
|
|
@@ -77,14 +76,11 @@ export function createIncludeHelper<TEnv>(): IncludeFn<TEnv> {
|
|
|
77
76
|
): IncludeItem => {
|
|
78
77
|
const { ctx } = requireDslContext("include() must be called inside urls()");
|
|
79
78
|
|
|
80
|
-
// clientUrls() sources mount
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
// projection is available; the include machinery then applies URL and
|
|
86
|
-
// route-name prefixes exactly as for server modules.
|
|
87
|
-
if (isClientUrlPatterns(patterns) || isClientUrlReference(patterns)) {
|
|
79
|
+
// clientUrls() sources mount like any urls() module: the adapter defers
|
|
80
|
+
// materialization to evaluation time (projection installed by then) and
|
|
81
|
+
// the include machinery applies URL/name prefixes as for server modules.
|
|
82
|
+
// Ordering: see isClientUrlSource.
|
|
83
|
+
if (isClientUrlSource(patterns)) {
|
|
88
84
|
patterns = clientUrlIncludePatterns(patterns) as UrlPatterns<TEnv>;
|
|
89
85
|
}
|
|
90
86
|
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import type { UrlPatterns } from "./pattern-types.js";
|
|
2
|
+
import type { ClientUrlPatterns } from "../client-urls/types.js";
|
|
3
|
+
import {
|
|
4
|
+
clientUrlIncludePatterns,
|
|
5
|
+
isClientUrlSource,
|
|
6
|
+
} from "../client-urls/server-projection.js";
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
9
|
* What an async `include()` provider may resolve to: a `urls()` value directly,
|
|
5
10
|
* or a module namespace whose `default` export is a `urls()` value (the shape
|
|
6
11
|
* produced by `() => import("./routes")` when the route module does
|
|
7
|
-
* `export default urls(...)`).
|
|
12
|
+
* `export default urls(...)`). A `clientUrls()` module resolves the same way
|
|
13
|
+
* (`() => import("./shop.client")`); on the server its `default` is the client
|
|
14
|
+
* reference, adapted exactly as the eager `include(prefix, clientUrlsDefault)`
|
|
15
|
+
* form.
|
|
8
16
|
*/
|
|
9
17
|
export type IncludeModule<TEnv = any> =
|
|
10
18
|
| UrlPatterns<TEnv>
|
|
11
|
-
|
|
|
19
|
+
| ClientUrlPatterns
|
|
20
|
+
| { default: UrlPatterns<TEnv> | ClientUrlPatterns };
|
|
12
21
|
|
|
13
22
|
/**
|
|
14
23
|
* An async/lazy include provider: a thunk returning a `urls()` value (or a
|
|
@@ -36,9 +45,19 @@ function isUrlPatterns(value: unknown): value is UrlPatterns {
|
|
|
36
45
|
);
|
|
37
46
|
}
|
|
38
47
|
|
|
48
|
+
/**
|
|
49
|
+
* A `urls()` value as is; a `clientUrls()` source through the same adapter the
|
|
50
|
+
* eager include() path applies (ordering: see isClientUrlSource).
|
|
51
|
+
*/
|
|
52
|
+
function toUrlPatterns(value: unknown): UrlPatterns | undefined {
|
|
53
|
+
if (isClientUrlSource(value)) return clientUrlIncludePatterns(value);
|
|
54
|
+
return isUrlPatterns(value) ? value : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
39
57
|
/**
|
|
40
58
|
* Normalize an async provider's resolved value to a `UrlPatterns`. Accepts a
|
|
41
|
-
* `urls()` value directly or a module whose `default` export is
|
|
59
|
+
* `urls()`/`clientUrls()` value directly or a module whose `default` export is
|
|
60
|
+
* one.
|
|
42
61
|
*/
|
|
43
62
|
export function resolveIncludeModule<TEnv = any>(
|
|
44
63
|
mod: IncludeModule<TEnv>,
|
|
@@ -53,8 +72,8 @@ export function resolveIncludeModule<TEnv = any>(
|
|
|
53
72
|
// 404s with a misleading error). A bare `() => urls(...)` provider (no
|
|
54
73
|
// module) has no `default`, so it still resolves via the mod-as-value branch.
|
|
55
74
|
const def = (mod as { default?: unknown })?.default;
|
|
56
|
-
|
|
57
|
-
if (
|
|
75
|
+
const resolved = toUrlPatterns(def) ?? toUrlPatterns(mod);
|
|
76
|
+
if (resolved) return resolved as UrlPatterns<TEnv>;
|
|
58
77
|
// The common failure is a module namespace whose `default` is missing or not a
|
|
59
78
|
// urls() value (e.g. only named exports); `typeof` alone says "object" and
|
|
60
79
|
// hides that, so name the keys present. "provider" (not "async provider") —
|
|
@@ -65,7 +84,7 @@ export function resolveIncludeModule<TEnv = any>(
|
|
|
65
84
|
: typeof mod;
|
|
66
85
|
throw new Error(
|
|
67
86
|
`[@rangojs/router] include() provider${id ? ` for "${id}"` : ""} must ` +
|
|
68
|
-
`resolve to a urls() value — either returned directly or
|
|
69
|
-
|
|
87
|
+
`resolve to a urls() or clientUrls() value — either returned directly or ` +
|
|
88
|
+
`as the module's \`default\` export (e.g. \`export default urls(...)\`). Got ${got}.`,
|
|
70
89
|
);
|
|
71
90
|
}
|
|
@@ -160,7 +160,9 @@ export type TextResponsePathFn<TEnv> = <
|
|
|
160
160
|
/**
|
|
161
161
|
* What an async include() provider resolves to. Route types (`TRoutes`) are
|
|
162
162
|
* inferred from the resolved `urls()` value so `href()` and named routes stay
|
|
163
|
-
* type-safe through a code-split module (`() => import("./routes")`).
|
|
163
|
+
* type-safe through a code-split module (`() => import("./routes")`). A
|
|
164
|
+
* clientUrls() module's default export types as ClientUrlPatterns, so
|
|
165
|
+
* `() => import("./shop.client")` infers the group's names the same way.
|
|
164
166
|
*/
|
|
165
167
|
type IncludeResolved<
|
|
166
168
|
TEnv,
|
|
@@ -168,7 +170,12 @@ type IncludeResolved<
|
|
|
168
170
|
TResponses extends Record<string, unknown>,
|
|
169
171
|
> =
|
|
170
172
|
| UrlPatterns<TEnv, TRoutes, TResponses>
|
|
171
|
-
|
|
|
173
|
+
| ClientUrlPatterns<TRoutes>
|
|
174
|
+
| {
|
|
175
|
+
default:
|
|
176
|
+
| UrlPatterns<TEnv, TRoutes, TResponses>
|
|
177
|
+
| ClientUrlPatterns<TRoutes>;
|
|
178
|
+
};
|
|
172
179
|
|
|
173
180
|
/** include() argument: an eager `urls()` value or an async provider thunk. */
|
|
174
181
|
export type IncludeArg<
|