@rangojs/router 0.0.0-experimental.d7eeaa75 → 0.0.0-experimental.dc2bd2b4
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/README.md +120 -25
- package/dist/bin/rango.js +147 -57
- package/dist/testing/vitest.js +48 -0
- package/dist/vite/index.js +2151 -846
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +57 -11
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +220 -30
- package/skills/caching/SKILL.md +116 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +229 -20
- package/skills/host-router/SKILL.md +45 -20
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +46 -4
- package/skills/layout/SKILL.md +28 -7
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +219 -9
- package/skills/middleware/SKILL.md +47 -12
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +71 -6
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +242 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +66 -9
- package/skills/route/SKILL.md +57 -4
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +751 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/testing/SKILL.md +647 -0
- package/skills/typesafety/SKILL.md +319 -27
- package/skills/use-cache/SKILL.md +34 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +117 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/event-controller.ts +86 -70
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/navigation-bridge.ts +84 -11
- package/src/browser/navigation-client.ts +76 -28
- package/src/browser/navigation-store.ts +32 -9
- package/src/browser/navigation-transaction.ts +10 -28
- package/src/browser/partial-update.ts +64 -26
- package/src/browser/prefetch/cache.ts +129 -21
- package/src/browser/prefetch/fetch.ts +148 -16
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +30 -2
- package/src/browser/react/NavigationProvider.tsx +72 -31
- package/src/browser/react/filter-segment-order.ts +51 -7
- package/src/browser/react/index.ts +3 -0
- package/src/browser/react/location-state-shared.ts +175 -4
- package/src/browser/react/location-state.ts +39 -13
- package/src/browser/react/use-handle.ts +17 -9
- package/src/browser/react/use-navigation.ts +22 -2
- package/src/browser/react/use-params.ts +20 -8
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +22 -2
- package/src/browser/react/use-segments.ts +11 -8
- package/src/browser/response-adapter.ts +25 -0
- package/src/browser/rsc-router.tsx +64 -22
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +23 -30
- package/src/browser/types.ts +21 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/index.ts +2 -0
- package/src/build/route-trie.ts +52 -25
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +55 -14
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-scope.ts +28 -42
- package/src/cache/cf/cf-cache-store.ts +54 -13
- package/src/client.rsc.tsx +3 -0
- package/src/client.tsx +92 -182
- package/src/context-var.ts +5 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +30 -1
- package/src/handle.ts +26 -13
- package/src/host/index.ts +2 -2
- package/src/host/router.ts +129 -57
- package/src/host/types.ts +31 -2
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +140 -20
- package/src/index.rsc.ts +9 -4
- package/src/index.ts +53 -15
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +2 -5
- package/src/loader.ts +3 -10
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/prerender.ts +4 -4
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -36
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +384 -257
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +100 -28
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +26 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -2
- package/src/router/error-handling.ts +1 -1
- package/src/router/handler-context.ts +21 -38
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/lazy-includes.ts +8 -8
- package/src/router/loader-resolution.ts +19 -2
- package/src/router/manifest.ts +22 -13
- package/src/router/match-api.ts +4 -3
- package/src/router/match-handlers.ts +63 -20
- package/src/router/match-middleware/cache-lookup.ts +44 -91
- package/src/router/match-middleware/cache-store.ts +3 -2
- package/src/router/match-result.ts +53 -32
- package/src/router/metrics.ts +1 -1
- package/src/router/middleware-types.ts +15 -26
- package/src/router/middleware.ts +99 -84
- package/src/router/pattern-matching.ts +101 -17
- package/src/router/prerender-match.ts +1 -1
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +4 -28
- package/src/router/revalidation.ts +58 -2
- package/src/router/router-interfaces.ts +45 -28
- package/src/router/router-options.ts +40 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +27 -6
- package/src/router/segment-resolution/revalidation.ts +147 -106
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry.ts +99 -0
- package/src/router/trie-matching.ts +18 -13
- package/src/router/types.ts +8 -0
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +38 -23
- package/src/rsc/handler-context.ts +2 -2
- package/src/rsc/handler.ts +28 -69
- package/src/rsc/helpers.ts +91 -43
- package/src/rsc/index.ts +1 -1
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/progressive-enhancement.ts +4 -0
- package/src/rsc/response-route-handler.ts +46 -53
- package/src/rsc/rsc-rendering.ts +35 -51
- package/src/rsc/runtime-warnings.ts +9 -10
- package/src/rsc/server-action.ts +17 -37
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +8 -2
- package/src/search-params.ts +4 -4
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +132 -116
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +143 -53
- package/src/server/cookie-store.ts +28 -4
- package/src/server/request-context.ts +20 -42
- package/src/ssr/index.tsx +5 -1
- package/src/static-handler.ts +1 -1
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +440 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +154 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +306 -0
- package/src/testing/e2e/server.ts +183 -0
- package/src/testing/flight-matchers.ts +104 -0
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +22 -0
- package/src/testing/flight.ts +182 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +193 -0
- package/src/testing/render-route.tsx +536 -0
- package/src/testing/run-loader.ts +296 -0
- package/src/testing/run-middleware.ts +170 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +183 -0
- package/src/types/global-namespace.ts +39 -26
- package/src/types/handler-context.ts +68 -50
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +5 -6
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-entry.ts +11 -0
- package/src/types/segments.ts +35 -2
- package/src/urls/include-helper.ts +34 -67
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper-types.ts +41 -7
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +26 -116
- package/src/urls/urls-function.ts +1 -5
- package/src/use-loader.tsx +413 -42
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +6 -6
- package/src/vite/discovery/discover-routers.ts +101 -51
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +67 -26
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +33 -0
- package/src/vite/discovery/virtual-module-codegen.ts +13 -23
- package/src/vite/index.ts +2 -0
- package/src/vite/plugin-types.ts +67 -0
- package/src/vite/plugins/cjs-to-esm.ts +8 -7
- package/src/vite/plugins/client-ref-dedup.ts +16 -0
- package/src/vite/plugins/client-ref-hashing.ts +28 -5
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/plugins/expose-action-id.ts +54 -30
- package/src/vite/plugins/expose-id-utils.ts +12 -8
- package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
- package/src/vite/plugins/expose-ids/handler-transform.ts +8 -61
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +496 -486
- package/src/vite/plugins/performance-tracks.ts +29 -25
- package/src/vite/plugins/use-cache-transform.ts +65 -50
- package/src/vite/plugins/version-injector.ts +39 -23
- package/src/vite/plugins/version-plugin.ts +59 -2
- package/src/vite/plugins/virtual-entries.ts +2 -2
- package/src/vite/rango.ts +116 -29
- package/src/vite/router-discovery.ts +750 -100
- package/src/vite/utils/ast-handler-extract.ts +15 -15
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +4 -2
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +21 -5
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +21 -6
- package/src/vite/utils/shared-utils.ts +107 -26
- package/src/browser/action-response-classifier.ts +0 -99
|
@@ -11,122 +11,40 @@ import {
|
|
|
11
11
|
when,
|
|
12
12
|
errorBoundary,
|
|
13
13
|
notFoundBoundary,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
route,
|
|
15
|
+
loader,
|
|
16
|
+
loading,
|
|
17
|
+
transition,
|
|
18
18
|
} from "./dsl-helpers.js";
|
|
19
19
|
import RootLayout from "../server/root-layout";
|
|
20
20
|
import { invariant } from "../errors";
|
|
21
21
|
|
|
22
|
-
/*
|
|
23
|
-
* Create revalidate helper
|
|
24
|
-
*/
|
|
25
|
-
const createRevalidateHelper = <TEnv>(): RouteHelpers<
|
|
26
|
-
any,
|
|
27
|
-
TEnv
|
|
28
|
-
>["revalidate"] => {
|
|
29
|
-
return revalidate as RouteHelpers<any, TEnv>["revalidate"];
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Create errorBoundary helper
|
|
34
|
-
*/
|
|
35
|
-
const createErrorBoundaryHelper = <TEnv>(): RouteHelpers<
|
|
36
|
-
any,
|
|
37
|
-
TEnv
|
|
38
|
-
>["errorBoundary"] => {
|
|
39
|
-
return errorBoundary as RouteHelpers<any, TEnv>["errorBoundary"];
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create notFoundBoundary helper
|
|
44
|
-
*/
|
|
45
|
-
const createNotFoundBoundaryHelper = <TEnv>(): RouteHelpers<
|
|
46
|
-
any,
|
|
47
|
-
TEnv
|
|
48
|
-
>["notFoundBoundary"] => {
|
|
49
|
-
return notFoundBoundary as RouteHelpers<any, TEnv>["notFoundBoundary"];
|
|
50
|
-
};
|
|
51
|
-
|
|
52
22
|
/**
|
|
53
|
-
*
|
|
23
|
+
* Assemble the RouteHelpers object. The helpers are the DSL functions
|
|
24
|
+
* themselves; the single cast erases the phantom generics (and the extra
|
|
25
|
+
* `route` key) that the per-router RouteHelpers<T, TEnv> type carries but the
|
|
26
|
+
* runtime functions do not.
|
|
54
27
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
28
|
+
function buildRouteHelpers<T extends RouteDefinition, TEnv>(): RouteHelpers<
|
|
29
|
+
T,
|
|
57
30
|
TEnv
|
|
58
|
-
>
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
>(): RouteHelpers<T, TEnv>["intercept"] => {
|
|
76
|
-
return intercept as RouteHelpers<T, TEnv>["intercept"];
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Create loader helper
|
|
81
|
-
*/
|
|
82
|
-
const createLoaderHelper = <TEnv>(): RouteHelpers<any, TEnv>["loader"] => {
|
|
83
|
-
return loaderFn as RouteHelpers<any, TEnv>["loader"];
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Create loading helper
|
|
88
|
-
*/
|
|
89
|
-
const createLoadingHelper = (): RouteHelpers<any, any>["loading"] => {
|
|
90
|
-
return loadingFn;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Create route helper
|
|
95
|
-
*/
|
|
96
|
-
const createRouteHelper = <
|
|
97
|
-
const T extends RouteDefinition,
|
|
98
|
-
TEnv,
|
|
99
|
-
>(): RouteHelpers<T, TEnv>["route"] => {
|
|
100
|
-
return routeFn as unknown as RouteHelpers<T, TEnv>["route"];
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Create layout helper
|
|
105
|
-
*/
|
|
106
|
-
const createLayoutHelper = <TEnv>(): RouteHelpers<any, TEnv>["layout"] => {
|
|
107
|
-
return layout as RouteHelpers<any, TEnv>["layout"];
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Create when helper for intercept conditions
|
|
112
|
-
*/
|
|
113
|
-
const createWhenHelper = (): RouteHelpers<any, any>["when"] => {
|
|
114
|
-
return when;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Create cache helper for cache configuration
|
|
119
|
-
*/
|
|
120
|
-
const createCacheHelper = (): RouteHelpers<any, any>["cache"] => {
|
|
121
|
-
return cache;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Create transition helper
|
|
126
|
-
*/
|
|
127
|
-
const createTransitionHelper = (): RouteHelpers<any, any>["transition"] => {
|
|
128
|
-
return transitionFn as RouteHelpers<any, any>["transition"];
|
|
129
|
-
};
|
|
31
|
+
> {
|
|
32
|
+
return {
|
|
33
|
+
route,
|
|
34
|
+
layout,
|
|
35
|
+
parallel,
|
|
36
|
+
intercept,
|
|
37
|
+
middleware,
|
|
38
|
+
revalidate,
|
|
39
|
+
loader,
|
|
40
|
+
loading,
|
|
41
|
+
errorBoundary,
|
|
42
|
+
notFoundBoundary,
|
|
43
|
+
when,
|
|
44
|
+
cache,
|
|
45
|
+
transition,
|
|
46
|
+
} as unknown as RouteHelpers<T, TEnv>;
|
|
47
|
+
}
|
|
130
48
|
|
|
131
49
|
/**
|
|
132
50
|
* Branded type for route handlers that carries the route type info.
|
|
@@ -152,21 +70,7 @@ export function map<const T extends RouteDefinition, TEnv = DefaultEnv>(
|
|
|
152
70
|
"map() expects a builder function as its argument",
|
|
153
71
|
);
|
|
154
72
|
// Create helpers
|
|
155
|
-
const helpers
|
|
156
|
-
route: createRouteHelper<T, TEnv>(),
|
|
157
|
-
layout: createLayoutHelper<TEnv>(),
|
|
158
|
-
parallel: createParallelHelper<TEnv>(),
|
|
159
|
-
intercept: createInterceptHelper<T, TEnv>(),
|
|
160
|
-
middleware: createMiddlewareHelper<TEnv>(),
|
|
161
|
-
revalidate: createRevalidateHelper<TEnv>(),
|
|
162
|
-
loader: createLoaderHelper<TEnv>(),
|
|
163
|
-
loading: createLoadingHelper(),
|
|
164
|
-
errorBoundary: createErrorBoundaryHelper<TEnv>(),
|
|
165
|
-
notFoundBoundary: createNotFoundBoundaryHelper<TEnv>(),
|
|
166
|
-
when: createWhenHelper(),
|
|
167
|
-
cache: createCacheHelper(),
|
|
168
|
-
transition: createTransitionHelper(),
|
|
169
|
-
};
|
|
73
|
+
const helpers = buildRouteHelpers<T, TEnv>();
|
|
170
74
|
|
|
171
75
|
return [layout(RootLayout, () => builder(helpers))].flat(3);
|
|
172
76
|
};
|
|
@@ -182,19 +86,5 @@ export function createRouteHelpers<
|
|
|
182
86
|
T extends RouteDefinition,
|
|
183
87
|
TEnv,
|
|
184
88
|
>(): RouteHelpers<T, TEnv> {
|
|
185
|
-
return
|
|
186
|
-
route: createRouteHelper<T, TEnv>(),
|
|
187
|
-
layout: createLayoutHelper<TEnv>(),
|
|
188
|
-
parallel: createParallelHelper<TEnv>(),
|
|
189
|
-
intercept: createInterceptHelper<T, TEnv>(),
|
|
190
|
-
middleware: createMiddlewareHelper<TEnv>(),
|
|
191
|
-
revalidate: createRevalidateHelper<TEnv>(),
|
|
192
|
-
loader: createLoaderHelper<TEnv>(),
|
|
193
|
-
loading: createLoadingHelper(),
|
|
194
|
-
errorBoundary: createErrorBoundaryHelper<TEnv>(),
|
|
195
|
-
notFoundBoundary: createNotFoundBoundaryHelper<TEnv>(),
|
|
196
|
-
when: createWhenHelper(),
|
|
197
|
-
cache: createCacheHelper(),
|
|
198
|
-
transition: createTransitionHelper(),
|
|
199
|
-
};
|
|
89
|
+
return buildRouteHelpers<T, TEnv>();
|
|
200
90
|
}
|
|
@@ -123,7 +123,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
123
123
|
* "@main": async (ctx) => <MainContent data={ctx.use(DataLoader)} />,
|
|
124
124
|
* })
|
|
125
125
|
*
|
|
126
|
-
* // With loaders and loading states
|
|
126
|
+
* // With loaders and loading states (broadcast to every slot)
|
|
127
127
|
* parallel({
|
|
128
128
|
* "@analytics": AnalyticsPanel,
|
|
129
129
|
* "@metrics": MetricsPanel,
|
|
@@ -131,12 +131,36 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
131
131
|
* loader(DashboardLoader),
|
|
132
132
|
* loading(<DashboardSkeleton />),
|
|
133
133
|
* ])
|
|
134
|
+
*
|
|
135
|
+
* // Per-slot scoped use via slot descriptor — for single-assignment items
|
|
136
|
+
* // like loading() that should not broadcast to siblings.
|
|
137
|
+
* parallel({
|
|
138
|
+
* "@meta": MetaSlot,
|
|
139
|
+
* "@sidebar": {
|
|
140
|
+
* handler: SidebarSlot,
|
|
141
|
+
* use: () => [loading(<SidebarSkeleton />)],
|
|
142
|
+
* },
|
|
143
|
+
* })
|
|
134
144
|
* ```
|
|
135
145
|
* @param slots - Object with slot names (prefixed with @) mapped to handlers
|
|
146
|
+
* or `{ handler, use? }` slot descriptors.
|
|
136
147
|
* @param use - Optional callback for loaders, loading, revalidate, etc.
|
|
148
|
+
* Items here apply to every slot in the call (broadcast).
|
|
149
|
+
* For per-slot single-assignment items, use the slot descriptor's
|
|
150
|
+
* own `use` callback — slot-local items run after the broadcast,
|
|
151
|
+
* so they take precedence on `loading()` and other last-write-wins
|
|
152
|
+
* fields.
|
|
137
153
|
*/
|
|
138
154
|
parallel: <
|
|
139
|
-
TSlots extends Record
|
|
155
|
+
TSlots extends Record<
|
|
156
|
+
`@${string}`,
|
|
157
|
+
| Handler<any, any, TEnv>
|
|
158
|
+
| ReactNode
|
|
159
|
+
| {
|
|
160
|
+
handler: Handler<any, any, TEnv> | ReactNode;
|
|
161
|
+
use?: () => UseItems<ParallelUseItem>;
|
|
162
|
+
}
|
|
163
|
+
>,
|
|
140
164
|
>(
|
|
141
165
|
slots: TSlots,
|
|
142
166
|
use?: () => UseItems<ParallelUseItem>,
|
|
@@ -174,29 +198,49 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
174
198
|
use?: () => UseItems<InterceptUseItem>,
|
|
175
199
|
): InterceptItem;
|
|
176
200
|
// Global: unprefixed, params inferred from global route map
|
|
177
|
-
<K extends keyof
|
|
201
|
+
<K extends keyof Rango.GeneratedRouteMap & string>(
|
|
178
202
|
slotName: `@${string}`,
|
|
179
203
|
routeName: K,
|
|
180
|
-
handler: ReactNode | Handler<K,
|
|
204
|
+
handler: ReactNode | Handler<K, Rango.GeneratedRouteMap, TEnv>,
|
|
181
205
|
use?: () => UseItems<InterceptUseItem>,
|
|
182
206
|
): InterceptItem;
|
|
183
207
|
};
|
|
184
208
|
/**
|
|
185
|
-
* Attach middleware to the current route/layout
|
|
209
|
+
* Attach middleware to the current route/layout, or wrap child segments
|
|
210
|
+
*
|
|
211
|
+
* **Sibling mode** — attaches middleware to the parent entry:
|
|
186
212
|
* ```typescript
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
213
|
+
* layout(<DashboardShell />, () => [
|
|
214
|
+
* middleware(authMiddleware),
|
|
215
|
+
* middleware([authMiddleware, loggingMiddleware]),
|
|
216
|
+
* path("/", DashboardPage),
|
|
217
|
+
* ])
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* **Wrapping mode** — scopes middleware to the children only:
|
|
221
|
+
* ```typescript
|
|
222
|
+
* middleware(authMiddleware, () => [
|
|
223
|
+
* path("/dashboard", DashboardPage),
|
|
224
|
+
* path("/settings", SettingsPage),
|
|
225
|
+
* ])
|
|
193
226
|
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
227
|
+
* middleware([authMiddleware, loggingMiddleware], () => [
|
|
228
|
+
* path("/admin", AdminPage),
|
|
229
|
+
* ])
|
|
196
230
|
* ```
|
|
197
|
-
* @param fns - One or more middleware functions to execute in order
|
|
198
231
|
*/
|
|
199
|
-
middleware:
|
|
232
|
+
middleware: {
|
|
233
|
+
(fn: MiddlewareFn<TEnv>): MiddlewareItem;
|
|
234
|
+
(
|
|
235
|
+
fn: MiddlewareFn<TEnv>,
|
|
236
|
+
children: () => UseItems<LayoutUseItem>,
|
|
237
|
+
): MiddlewareItem;
|
|
238
|
+
(fns: MiddlewareFn<TEnv>[]): MiddlewareItem;
|
|
239
|
+
(
|
|
240
|
+
fns: MiddlewareFn<TEnv>[],
|
|
241
|
+
children: () => UseItems<LayoutUseItem>,
|
|
242
|
+
): MiddlewareItem;
|
|
243
|
+
};
|
|
200
244
|
/**
|
|
201
245
|
* Control when a segment should revalidate during navigation
|
|
202
246
|
* ```typescript
|
|
@@ -206,8 +250,10 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
206
250
|
* )
|
|
207
251
|
*
|
|
208
252
|
* // Revalidate after specific actions (actionId format: "path/to/file.ts#exportName")
|
|
253
|
+
* // Use `|| undefined` (defer), not `?? false` (hard short-circuit), so the
|
|
254
|
+
* // chain and the segment default still apply when there is no match.
|
|
209
255
|
* revalidate(({ actionId }) =>
|
|
210
|
-
* actionId?.includes("Cart")
|
|
256
|
+
* actionId?.includes("Cart") || undefined
|
|
211
257
|
* )
|
|
212
258
|
*
|
|
213
259
|
* // Soft decision (suggest but allow override)
|
|
@@ -215,7 +261,12 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
215
261
|
* ({ defaultShouldRevalidate: true })
|
|
216
262
|
* )
|
|
217
263
|
* ```
|
|
218
|
-
* @param fn - Function
|
|
264
|
+
* @param fn - Function returning either:
|
|
265
|
+
* - `boolean` (hard decision — short-circuits the chain),
|
|
266
|
+
* - `{ defaultShouldRevalidate: boolean }` (soft — updates the suggestion
|
|
267
|
+
* for downstream revalidators),
|
|
268
|
+
* - or nothing / `null` / `undefined` (defer — leaves the suggestion
|
|
269
|
+
* unchanged and continues to the next revalidator).
|
|
219
270
|
*/
|
|
220
271
|
revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
|
|
221
272
|
/**
|
|
@@ -225,7 +276,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
225
276
|
*
|
|
226
277
|
* // With loader-specific revalidation (match by file or export name)
|
|
227
278
|
* loader(CartLoader, () => [
|
|
228
|
-
* revalidate(({ actionId }) => actionId?.includes("Cart")
|
|
279
|
+
* revalidate(({ actionId }) => actionId?.includes("Cart") || undefined),
|
|
229
280
|
* ])
|
|
230
281
|
*
|
|
231
282
|
* // Consume in client components with useLoader()
|
|
@@ -398,10 +449,30 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
398
449
|
): CacheItem;
|
|
399
450
|
};
|
|
400
451
|
/**
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
452
|
+
* Opt a route (or group of routes) into transition-driven navigation.
|
|
453
|
+
*
|
|
454
|
+
* `transition()` does two independent things, and you choose how far to go:
|
|
455
|
+
* 1. startTransition (ALL React versions): the navigation commit is driven
|
|
456
|
+
* through React's startTransition, so a same-route nav (same route,
|
|
457
|
+
* different params, e.g. /product/1 -> /product/2) holds the previous
|
|
458
|
+
* content while the new loader resolves instead of flashing the route's
|
|
459
|
+
* loading() skeleton (see segment-system.tsx inTransitionScope). This is
|
|
460
|
+
* also the precondition for any view-transition animation.
|
|
461
|
+
* 2. <ViewTransition> (experimental React only): the segment content is also
|
|
462
|
+
* wrapped in React's <ViewTransition>, so the held swap cross-fades/morphs.
|
|
463
|
+
* Layered on by default; pass { viewTransition: false } to keep #1 without
|
|
464
|
+
* the router boundary (and place your own <ViewTransition> instead).
|
|
465
|
+
*
|
|
466
|
+
* A view transition cannot fire without a startTransition, so the meaningful
|
|
467
|
+
* choices are (see skills/view-transitions for the full matrix):
|
|
468
|
+
* - no transition() -> neither (remount + skeleton)
|
|
469
|
+
* - transition({ viewTransition: false }) -> startTransition only (hold)
|
|
470
|
+
* - transition({}) / transition({ enter… }) -> startTransition + ViewTransition
|
|
471
|
+
*
|
|
472
|
+
* Precedence: a bare transition({}) inherits createRouter({ viewTransition })
|
|
473
|
+
* (default "auto"); an explicit per-route `viewTransition` always wins. So
|
|
474
|
+
* transition({}) is startTransition + ViewTransition under the default and
|
|
475
|
+
* startTransition only when the router sets viewTransition: false.
|
|
405
476
|
*
|
|
406
477
|
* ```typescript
|
|
407
478
|
* // Attach to a single route
|
|
@@ -415,13 +486,14 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
415
486
|
* path("/about", AboutPage),
|
|
416
487
|
* ])
|
|
417
488
|
*
|
|
418
|
-
* //
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* })
|
|
489
|
+
* // Hold content + drive view transitions, but place no router boundary:
|
|
490
|
+
* path("/product/:id", ProductPage, { name: "product" }, () => [
|
|
491
|
+
* transition({ viewTransition: false }),
|
|
492
|
+
* ])
|
|
423
493
|
* ```
|
|
424
|
-
* @param config - ViewTransition configuration (enter, exit, update, share,
|
|
494
|
+
* @param config - ViewTransition configuration (enter, exit, update, share,
|
|
495
|
+
* default, name) plus `viewTransition: "auto" | false` to toggle the router
|
|
496
|
+
* boundary (createRouter({ viewTransition }) sets the app-wide default)
|
|
425
497
|
* @param children - Optional callback returning child routes to wrap
|
|
426
498
|
*/
|
|
427
499
|
transition: {
|
|
@@ -21,6 +21,10 @@ export function resolveHandlerUse(handler: unknown): (() => any[]) | undefined {
|
|
|
21
21
|
if (isStaticHandler(handler)) {
|
|
22
22
|
return (handler as any).use;
|
|
23
23
|
}
|
|
24
|
+
// Loader definitions from createLoader() — branded objects with optional .use
|
|
25
|
+
if (typeof handler === "object" && (handler as any).__brand === "loader") {
|
|
26
|
+
return (handler as any).use;
|
|
27
|
+
}
|
|
24
28
|
// Plain handler function
|
|
25
29
|
if (typeof handler === "function") {
|
|
26
30
|
return (handler as any).use;
|
|
@@ -99,6 +103,8 @@ const MOUNT_SITE_ALLOWED_TYPES: Record<string, Set<string>> = {
|
|
|
99
103
|
"when",
|
|
100
104
|
"transition",
|
|
101
105
|
]),
|
|
106
|
+
// LoaderUseItem — only revalidate + cache can attach to a loader entry
|
|
107
|
+
loader: new Set(["revalidate", "cache"]),
|
|
102
108
|
};
|
|
103
109
|
|
|
104
110
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AllUseItems, WhenItem } from "../route-types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The set of valid use-item `type` discriminants — the single runtime source of
|
|
5
|
+
* truth for "is this a well-formed use item?" shape validation.
|
|
6
|
+
*
|
|
7
|
+
* Declared via a `Record<...>` so that adding a member to the union without
|
|
8
|
+
* updating this map is a compile error. `when` is included because when() items
|
|
9
|
+
* are valid inside intercept() even though WhenItem is not part of AllUseItems
|
|
10
|
+
* (it lives only in InterceptUseItem). This is shape validation only; per-mount-
|
|
11
|
+
* site rules remain the narrower hand-written tables in resolve-handler-use.ts.
|
|
12
|
+
*/
|
|
13
|
+
const USE_ITEM_TYPES: Record<AllUseItems["type"] | WhenItem["type"], true> = {
|
|
14
|
+
layout: true,
|
|
15
|
+
route: true,
|
|
16
|
+
middleware: true,
|
|
17
|
+
revalidate: true,
|
|
18
|
+
parallel: true,
|
|
19
|
+
intercept: true,
|
|
20
|
+
loader: true,
|
|
21
|
+
loading: true,
|
|
22
|
+
errorBoundary: true,
|
|
23
|
+
notFoundBoundary: true,
|
|
24
|
+
when: true,
|
|
25
|
+
cache: true,
|
|
26
|
+
transition: true,
|
|
27
|
+
include: true,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const ALL_USE_ITEM_TYPES: ReadonlySet<string> = new Set(
|
|
31
|
+
Object.keys(USE_ITEM_TYPES),
|
|
32
|
+
);
|
package/src/route-types.ts
CHANGED
|
@@ -5,47 +5,43 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Brand for UrlPatterns nominal typing (see pattern-types.ts). The route-item
|
|
9
|
+
* types below are discriminated by their `type` literal, so they carry no brand.
|
|
9
10
|
*/
|
|
10
|
-
export declare const LayoutBrand: unique symbol;
|
|
11
|
-
export declare const RouteBrand: unique symbol;
|
|
12
|
-
export declare const ParallelBrand: unique symbol;
|
|
13
|
-
export declare const InterceptBrand: unique symbol;
|
|
14
|
-
export declare const MiddlewareBrand: unique symbol;
|
|
15
|
-
export declare const RevalidateBrand: unique symbol;
|
|
16
|
-
export declare const LoaderBrand: unique symbol;
|
|
17
|
-
export declare const LoadingBrand: unique symbol;
|
|
18
|
-
export declare const ErrorBoundaryBrand: unique symbol;
|
|
19
|
-
export declare const NotFoundBoundaryBrand: unique symbol;
|
|
20
|
-
export declare const WhenBrand: unique symbol;
|
|
21
|
-
export declare const CacheBrand: unique symbol;
|
|
22
|
-
export declare const TransitionBrand: unique symbol;
|
|
23
|
-
export declare const IncludeBrand: unique symbol;
|
|
24
11
|
export declare const UrlPatternsBrand: unique symbol;
|
|
25
12
|
|
|
26
13
|
export type LayoutItem = {
|
|
27
14
|
name: string;
|
|
28
15
|
type: "layout";
|
|
29
16
|
uses?: AllUseItems[];
|
|
30
|
-
[LayoutBrand]: void;
|
|
31
17
|
};
|
|
32
18
|
|
|
33
19
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
20
|
+
* Phantom inference fields attached to wrapper items (layout/cache/transition)
|
|
21
|
+
* so the urls() type extractor can read their child routes/responses. The fields
|
|
22
|
+
* never exist at runtime.
|
|
36
23
|
*/
|
|
37
|
-
|
|
24
|
+
type WithChildren<
|
|
25
|
+
TBase,
|
|
38
26
|
TChildRoutes extends Record<string, any> = Record<string, string>,
|
|
39
27
|
TChildResponses extends Record<string, unknown> = Record<string, unknown>,
|
|
40
|
-
> =
|
|
28
|
+
> = TBase & {
|
|
41
29
|
readonly __childRoutes?: TChildRoutes;
|
|
42
30
|
readonly __childResponses?: TChildResponses;
|
|
43
31
|
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Typed layout item that carries child routes as phantom type
|
|
35
|
+
* Used for type inference in urls() API
|
|
36
|
+
*/
|
|
37
|
+
export type TypedLayoutItem<
|
|
38
|
+
TChildRoutes extends Record<string, any> = Record<string, string>,
|
|
39
|
+
TChildResponses extends Record<string, unknown> = Record<string, unknown>,
|
|
40
|
+
> = WithChildren<LayoutItem, TChildRoutes, TChildResponses>;
|
|
44
41
|
export type RouteItem = {
|
|
45
42
|
name: string;
|
|
46
43
|
type: "route";
|
|
47
44
|
uses?: AllUseItems[];
|
|
48
|
-
[RouteBrand]: void;
|
|
49
45
|
};
|
|
50
46
|
|
|
51
47
|
/**
|
|
@@ -67,64 +63,53 @@ export type ParallelItem = {
|
|
|
67
63
|
name: string;
|
|
68
64
|
type: "parallel";
|
|
69
65
|
uses?: ParallelUseItem[];
|
|
70
|
-
[ParallelBrand]: void;
|
|
71
66
|
};
|
|
72
67
|
export type InterceptItem = {
|
|
73
68
|
name: string;
|
|
74
69
|
type: "intercept";
|
|
75
70
|
uses?: InterceptUseItem[];
|
|
76
|
-
[InterceptBrand]: void;
|
|
77
71
|
};
|
|
78
72
|
export type LoaderItem = {
|
|
79
73
|
name: string;
|
|
80
74
|
type: "loader";
|
|
81
75
|
uses?: LoaderUseItem[];
|
|
82
|
-
[LoaderBrand]: void;
|
|
83
76
|
};
|
|
84
77
|
export type MiddlewareItem = {
|
|
85
78
|
name: string;
|
|
86
79
|
type: "middleware";
|
|
87
80
|
uses?: AllUseItems[];
|
|
88
|
-
[MiddlewareBrand]: void;
|
|
89
81
|
};
|
|
90
82
|
export type RevalidateItem = {
|
|
91
83
|
name: string;
|
|
92
84
|
type: "revalidate";
|
|
93
85
|
uses?: AllUseItems[];
|
|
94
|
-
[RevalidateBrand]: void;
|
|
95
86
|
};
|
|
96
87
|
export type LoadingItem = {
|
|
97
88
|
name: string;
|
|
98
89
|
type: "loading";
|
|
99
|
-
[LoadingBrand]: void;
|
|
100
90
|
};
|
|
101
91
|
export type ErrorBoundaryItem = {
|
|
102
92
|
name: string;
|
|
103
93
|
type: "errorBoundary";
|
|
104
94
|
uses?: AllUseItems[];
|
|
105
|
-
[ErrorBoundaryBrand]: void;
|
|
106
95
|
};
|
|
107
96
|
export type NotFoundBoundaryItem = {
|
|
108
97
|
name: string;
|
|
109
98
|
type: "notFoundBoundary";
|
|
110
99
|
uses?: AllUseItems[];
|
|
111
|
-
[NotFoundBoundaryBrand]: void;
|
|
112
100
|
};
|
|
113
101
|
export type WhenItem = {
|
|
114
102
|
name: string;
|
|
115
103
|
type: "when";
|
|
116
|
-
[WhenBrand]: void;
|
|
117
104
|
};
|
|
118
105
|
export type CacheItem = {
|
|
119
106
|
name: string;
|
|
120
107
|
type: "cache";
|
|
121
108
|
uses?: AllUseItems[];
|
|
122
|
-
[CacheBrand]: void;
|
|
123
109
|
};
|
|
124
110
|
export type TransitionItem = {
|
|
125
111
|
name: string;
|
|
126
112
|
type: "transition";
|
|
127
|
-
[TransitionBrand]: void;
|
|
128
113
|
};
|
|
129
114
|
|
|
130
115
|
/**
|
|
@@ -134,10 +119,7 @@ export type TransitionItem = {
|
|
|
134
119
|
export type TypedTransitionItem<
|
|
135
120
|
TChildRoutes extends Record<string, any> = Record<string, string>,
|
|
136
121
|
TChildResponses extends Record<string, unknown> = Record<string, unknown>,
|
|
137
|
-
> = TransitionItem
|
|
138
|
-
readonly __childRoutes?: TChildRoutes;
|
|
139
|
-
readonly __childResponses?: TChildResponses;
|
|
140
|
-
};
|
|
122
|
+
> = WithChildren<TransitionItem, TChildRoutes, TChildResponses>;
|
|
141
123
|
|
|
142
124
|
/**
|
|
143
125
|
* Typed cache item that carries child routes as phantom type
|
|
@@ -146,10 +128,7 @@ export type TypedTransitionItem<
|
|
|
146
128
|
export type TypedCacheItem<
|
|
147
129
|
TChildRoutes extends Record<string, any> = Record<string, string>,
|
|
148
130
|
TChildResponses extends Record<string, unknown> = Record<string, unknown>,
|
|
149
|
-
> = CacheItem
|
|
150
|
-
readonly __childRoutes?: TChildRoutes;
|
|
151
|
-
readonly __childResponses?: TChildResponses;
|
|
152
|
-
};
|
|
131
|
+
> = WithChildren<CacheItem, TChildRoutes, TChildResponses>;
|
|
153
132
|
|
|
154
133
|
/**
|
|
155
134
|
* Include item for URL pattern composition (used by urls() API)
|
|
@@ -176,8 +155,14 @@ export type IncludeItem = {
|
|
|
176
155
|
>;
|
|
177
156
|
/** Root scope flag for dot-local reverse resolution */
|
|
178
157
|
rootScoped?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Positional include scope token composed from the parent scope plus this
|
|
160
|
+
* include's sibling index (`${parentScope}I${idx}`). Applied to direct-
|
|
161
|
+
* descendant shortCodes during lazy evaluation so routes inside the
|
|
162
|
+
* include cannot collide with siblings declared outside it.
|
|
163
|
+
*/
|
|
164
|
+
includeScope?: string;
|
|
179
165
|
};
|
|
180
|
-
[IncludeBrand]: void;
|
|
181
166
|
};
|
|
182
167
|
|
|
183
168
|
/**
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a router basename to its canonical form: a single leading slash,
|
|
3
|
+
* no trailing slash, and `undefined` for an empty or bare-"/" value.
|
|
4
|
+
*
|
|
5
|
+
* This is the single source of truth used by both createRouter() (so the RSC
|
|
6
|
+
* handler stores a canonical basename on the request context) and the testing
|
|
7
|
+
* primitives (so a consumer can pass the same un-normalized string their
|
|
8
|
+
* createRouter() accepts and observe the same redirect() prefixing).
|
|
9
|
+
*/
|
|
10
|
+
export function normalizeBasename(basename?: string): string | undefined {
|
|
11
|
+
if (!basename) return undefined;
|
|
12
|
+
const trimmed = basename.replace(/^\/+|\/+$/g, "");
|
|
13
|
+
return trimmed ? "/" + trimmed : undefined;
|
|
14
|
+
}
|
|
@@ -135,8 +135,8 @@ export interface NegotiationResult {
|
|
|
135
135
|
manifestEntry: EntryData;
|
|
136
136
|
/** Route middleware for the winning variant */
|
|
137
137
|
routeMiddleware: CollectedMiddleware[];
|
|
138
|
-
/**
|
|
139
|
-
negotiated:
|
|
138
|
+
/** True when negotiation selected a variant; false for a plain response route. */
|
|
139
|
+
negotiated: boolean;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
/**
|
|
@@ -155,6 +155,19 @@ export async function negotiateRoute(
|
|
|
155
155
|
): Promise<NegotiationResult | null> {
|
|
156
156
|
const { matched, manifestEntry, routeMiddleware, responseType } = snapshot;
|
|
157
157
|
if (!matched.negotiateVariants || matched.negotiateVariants.length === 0) {
|
|
158
|
+
// No variants: a plain response route still yields a result (negotiated:false)
|
|
159
|
+
// so callers don't re-derive it; RSC routes (no responseType/handler) -> null.
|
|
160
|
+
const handler =
|
|
161
|
+
manifestEntry.type === "route" ? manifestEntry.handler : undefined;
|
|
162
|
+
if (responseType && handler) {
|
|
163
|
+
return {
|
|
164
|
+
responseType,
|
|
165
|
+
handler: handler as Function,
|
|
166
|
+
manifestEntry,
|
|
167
|
+
routeMiddleware,
|
|
168
|
+
negotiated: false,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
158
171
|
return null;
|
|
159
172
|
}
|
|
160
173
|
|