@rangojs/router 0.0.0-experimental.79 → 0.0.0-experimental.7d061845
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 +82 -0
- package/dist/vite/index.js +2138 -841
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +68 -21
- 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 +3 -1
- 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 +26 -4
- package/skills/layout/SKILL.md +6 -7
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +219 -9
- package/skills/middleware/SKILL.md +15 -9
- package/skills/migrate-nextjs/SKILL.md +4 -2
- package/skills/migrate-react-router/SKILL.md +5 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +12 -6
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +242 -24
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +66 -9
- package/skills/route/SKILL.md +33 -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 +816 -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 +65 -9
- package/src/browser/navigation-client.ts +45 -25
- package/src/browser/navigation-store.ts +32 -9
- package/src/browser/navigation-transaction.ts +10 -28
- package/src/browser/partial-update.ts +52 -26
- package/src/browser/prefetch/cache.ts +124 -26
- package/src/browser/prefetch/fetch.ts +114 -38
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +18 -13
- 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-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 +2 -1
- 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 +10 -8
- 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 +16 -6
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +21 -6
- 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 -39
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +253 -265
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +43 -15
- 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 +19 -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 -41
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/lazy-includes.ts +3 -3
- package/src/router/loader-resolution.ts +19 -2
- 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-system.tsx +122 -56
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +118 -51
- 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 +57 -0
- package/src/testing/flight-tree.ts +332 -0
- package/src/testing/flight.entry.ts +46 -0
- package/src/testing/flight.ts +224 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +106 -0
- package/src/testing/internal/context.ts +304 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +42 -0
- package/src/testing/render-handler.ts +267 -0
- package/src/testing/render-route.tsx +565 -0
- package/src/testing/run-loader.ts +341 -0
- package/src/testing/run-middleware.ts +188 -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 +270 -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/segments.ts +35 -1
- package/src/urls/include-helper.ts +10 -53
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper-types.ts +11 -3
- 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 +5 -4
- 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
|
}
|
|
@@ -198,10 +198,10 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
198
198
|
use?: () => UseItems<InterceptUseItem>,
|
|
199
199
|
): InterceptItem;
|
|
200
200
|
// Global: unprefixed, params inferred from global route map
|
|
201
|
-
<K extends keyof
|
|
201
|
+
<K extends keyof Rango.GeneratedRouteMap & string>(
|
|
202
202
|
slotName: `@${string}`,
|
|
203
203
|
routeName: K,
|
|
204
|
-
handler: ReactNode | Handler<K,
|
|
204
|
+
handler: ReactNode | Handler<K, Rango.GeneratedRouteMap, TEnv>,
|
|
205
205
|
use?: () => UseItems<InterceptUseItem>,
|
|
206
206
|
): InterceptItem;
|
|
207
207
|
};
|
|
@@ -250,8 +250,10 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
250
250
|
* )
|
|
251
251
|
*
|
|
252
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.
|
|
253
255
|
* revalidate(({ actionId }) =>
|
|
254
|
-
* actionId?.includes("Cart")
|
|
256
|
+
* actionId?.includes("Cart") || undefined
|
|
255
257
|
* )
|
|
256
258
|
*
|
|
257
259
|
* // Soft decision (suggest but allow override)
|
|
@@ -259,7 +261,12 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
259
261
|
* ({ defaultShouldRevalidate: true })
|
|
260
262
|
* )
|
|
261
263
|
* ```
|
|
262
|
-
* @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).
|
|
263
270
|
*/
|
|
264
271
|
revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
|
|
265
272
|
/**
|
|
@@ -269,7 +276,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
269
276
|
*
|
|
270
277
|
* // With loader-specific revalidation (match by file or export name)
|
|
271
278
|
* loader(CartLoader, () => [
|
|
272
|
-
* revalidate(({ actionId }) => actionId?.includes("Cart")
|
|
279
|
+
* revalidate(({ actionId }) => actionId?.includes("Cart") || undefined),
|
|
273
280
|
* ])
|
|
274
281
|
*
|
|
275
282
|
* // Consume in client components with useLoader()
|
|
@@ -442,10 +449,30 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
442
449
|
): CacheItem;
|
|
443
450
|
};
|
|
444
451
|
/**
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
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.
|
|
449
476
|
*
|
|
450
477
|
* ```typescript
|
|
451
478
|
* // Attach to a single route
|
|
@@ -459,13 +486,14 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
459
486
|
* path("/about", AboutPage),
|
|
460
487
|
* ])
|
|
461
488
|
*
|
|
462
|
-
* //
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* })
|
|
489
|
+
* // Hold content + drive view transitions, but place no router boundary:
|
|
490
|
+
* path("/product/:id", ProductPage, { name: "product" }, () => [
|
|
491
|
+
* transition({ viewTransition: false }),
|
|
492
|
+
* ])
|
|
467
493
|
* ```
|
|
468
|
-
* @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)
|
|
469
497
|
* @param children - Optional callback returning child routes to wrap
|
|
470
498
|
*/
|
|
471
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)
|
|
@@ -184,7 +163,6 @@ export type IncludeItem = {
|
|
|
184
163
|
*/
|
|
185
164
|
includeScope?: string;
|
|
186
165
|
};
|
|
187
|
-
[IncludeBrand]: void;
|
|
188
166
|
};
|
|
189
167
|
|
|
190
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
|
|
|
@@ -18,6 +18,8 @@ import { isInsideCacheScope } from "../server/context.js";
|
|
|
18
18
|
import { NOCACHE_SYMBOL, assertNotInsideCacheExec } from "../cache/taint.js";
|
|
19
19
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
20
20
|
import { PRERENDER_PASSTHROUGH } from "../prerender.js";
|
|
21
|
+
import { substitutePatternParams } from "./substitute-pattern-params.js";
|
|
22
|
+
import { fireAndForgetWaitUntil } from "../types/request-scope.js";
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* Strip internal _rsc* query params from a URL.
|
|
@@ -158,51 +160,14 @@ export function createReverseFunction(
|
|
|
158
160
|
);
|
|
159
161
|
}
|
|
160
162
|
|
|
161
|
-
let result = pattern;
|
|
162
|
-
|
|
163
163
|
// Merge current request params as defaults, explicit params override
|
|
164
164
|
const effectiveParams = currentParams
|
|
165
165
|
? { ...currentParams, ...hrefParams }
|
|
166
166
|
: hrefParams;
|
|
167
167
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let hadOmittedOptional = false;
|
|
172
|
-
// First pass: optional params (trailing ?)
|
|
173
|
-
result = result.replace(
|
|
174
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(\?)/g,
|
|
175
|
-
(_, key) => {
|
|
176
|
-
const value = effectiveParams[key];
|
|
177
|
-
// Empty string is treated as omitted — the trie matcher fills
|
|
178
|
-
// unmatched optional params with "" (not undefined), so reverse
|
|
179
|
-
// must collapse those segments instead of leaving empty slots.
|
|
180
|
-
if (value === undefined || value === "") {
|
|
181
|
-
hadOmittedOptional = true;
|
|
182
|
-
return "";
|
|
183
|
-
}
|
|
184
|
-
return encodeURIComponent(value);
|
|
185
|
-
},
|
|
186
|
-
);
|
|
187
|
-
// Second pass: required params (no trailing ?)
|
|
188
|
-
result = result.replace(
|
|
189
|
-
/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?(?!\?)/g,
|
|
190
|
-
(_, key) => {
|
|
191
|
-
const value = effectiveParams[key];
|
|
192
|
-
if (value === undefined) {
|
|
193
|
-
throw new Error(`Missing param "${key}" for route "${name}"`);
|
|
194
|
-
}
|
|
195
|
-
return encodeURIComponent(value);
|
|
196
|
-
},
|
|
197
|
-
);
|
|
198
|
-
// Clean up slashes only when an optional param was actually omitted,
|
|
199
|
-
// so intentional trailing-slash patterns like "/blog/" are preserved.
|
|
200
|
-
if (hadOmittedOptional) {
|
|
201
|
-
const hadTrailingSlash = pattern.length > 1 && pattern.endsWith("/");
|
|
202
|
-
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
203
|
-
if (hadTrailingSlash && !result.endsWith("/")) result += "/";
|
|
204
|
-
}
|
|
205
|
-
}
|
|
168
|
+
let result = effectiveParams
|
|
169
|
+
? substitutePatternParams(pattern, effectiveParams, name)
|
|
170
|
+
: pattern;
|
|
206
171
|
|
|
207
172
|
// Append search params as query string
|
|
208
173
|
if (search) {
|
|
@@ -281,8 +246,12 @@ export function createHandlerContext<TEnv>(
|
|
|
281
246
|
search: searchSchema ? resolvedSearchParams : {},
|
|
282
247
|
pathname,
|
|
283
248
|
url,
|
|
284
|
-
originalUrl: new URL(request.url),
|
|
249
|
+
originalUrl: requestContext?.originalUrl ?? new URL(request.url),
|
|
285
250
|
env: bindings,
|
|
251
|
+
waitUntil: requestContext
|
|
252
|
+
? requestContext.waitUntil.bind(requestContext)
|
|
253
|
+
: fireAndForgetWaitUntil,
|
|
254
|
+
executionContext: requestContext?.executionContext,
|
|
286
255
|
_variables: variables,
|
|
287
256
|
get: ((keyOrVar: any) => {
|
|
288
257
|
// Read-time guard: non-cacheable var inside cache() → throw.
|
|
@@ -387,6 +356,12 @@ export function createPrerenderContext<TEnv>(
|
|
|
387
356
|
"Configure buildEnv in your rango() plugin options to enable build-time env access.",
|
|
388
357
|
);
|
|
389
358
|
},
|
|
359
|
+
// Build-time prerender has no live request. waitUntil is a true no-op
|
|
360
|
+
// (running fn() here would fire side effects during build, which is
|
|
361
|
+
// incorrect — these are meant to outlive the live response).
|
|
362
|
+
// executionContext is absent for the same reason.
|
|
363
|
+
waitUntil: () => {},
|
|
364
|
+
executionContext: undefined,
|
|
390
365
|
_variables: variables,
|
|
391
366
|
get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
|
|
392
367
|
set: ((keyOrVar: any, value: any) => {
|
|
@@ -476,6 +451,11 @@ export function createStaticContext<TEnv>(
|
|
|
476
451
|
"Configure buildEnv in your rango() plugin options to enable build-time env access.",
|
|
477
452
|
);
|
|
478
453
|
},
|
|
454
|
+
// Static() handlers have no live request. waitUntil is a true no-op
|
|
455
|
+
// (running fn() here would fire side effects during build, which is
|
|
456
|
+
// incorrect). executionContext is absent for the same reason.
|
|
457
|
+
waitUntil: () => {},
|
|
458
|
+
executionContext: undefined,
|
|
479
459
|
_variables: variables,
|
|
480
460
|
get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
|
|
481
461
|
set: ((keyOrVar: any, value: any) => {
|