@rangojs/router 0.0.0-experimental.98 → 0.0.0-experimental.98914650
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 +24 -9
- package/dist/bin/rango.js +157 -63
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +1584 -639
- package/package.json +60 -11
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +60 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +222 -30
- package/skills/caching/SKILL.md +263 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +3 -1
- package/skills/hooks/SKILL.md +235 -28
- package/skills/host-router/SKILL.md +122 -22
- package/skills/intercept/SKILL.md +29 -5
- package/skills/layout/SKILL.md +13 -9
- package/skills/links/SKILL.md +173 -17
- package/skills/loader/SKILL.md +170 -23
- package/skills/middleware/SKILL.md +16 -10
- package/skills/migrate-nextjs/SKILL.md +38 -16
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +11 -7
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +250 -26
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +114 -47
- package/skills/route/SKILL.md +22 -5
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +78 -42
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +124 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +92 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +121 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +84 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +120 -0
- package/skills/typesafety/SKILL.md +310 -26
- package/skills/use-cache/SKILL.md +36 -5
- package/skills/vercel/SKILL.md +107 -0
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +37 -143
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/navigation-bridge.ts +30 -59
- package/src/browser/navigation-client.ts +96 -84
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +32 -82
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/partial-update.ts +60 -127
- package/src/browser/prefetch/cache.ts +82 -72
- package/src/browser/prefetch/fetch.ts +108 -33
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +157 -115
- package/src/browser/react/Link.tsx +0 -2
- package/src/browser/react/NavigationProvider.tsx +41 -48
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +0 -2
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +166 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +17 -14
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +0 -3
- package/src/browser/react/use-params.ts +3 -6
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +20 -5
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/response-adapter.ts +52 -1
- package/src/browser/rsc-router.tsx +70 -34
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +168 -44
- package/src/browser/types.ts +36 -21
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +89 -11
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +122 -22
- 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-error.ts +104 -0
- package/src/cache/cache-policy.ts +68 -28
- package/src/cache/cache-runtime.ts +134 -32
- package/src/cache/cache-scope.ts +100 -74
- package/src/cache/cache-tag.ts +98 -0
- package/src/cache/cf/cf-cache-store.ts +2255 -238
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +61 -20
- package/src/cache/handle-snapshot.ts +63 -0
- package/src/cache/index.ts +22 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +6 -30
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +33 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +799 -0
- package/src/client.rsc.tsx +6 -21
- package/src/client.tsx +25 -61
- package/src/component-utils.ts +19 -0
- package/src/context-var.ts +17 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/errors.ts +30 -4
- package/src/handle.ts +31 -23
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/breadcrumbs.ts +16 -5
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +7 -50
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +63 -9
- package/src/index.ts +64 -9
- package/src/internal-debug.ts +2 -4
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/network-error-thrower.tsx +1 -6
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +61 -6
- package/src/redirect-origin.ts +100 -0
- package/src/response-utils.ts +9 -0
- package/src/reverse.ts +65 -41
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +244 -281
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +40 -17
- package/src/route-definition/redirect.ts +43 -9
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +19 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -15
- package/src/router/error-handling.ts +13 -17
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +4 -42
- package/src/router/intercept-resolution.ts +14 -19
- package/src/router/lazy-includes.ts +9 -46
- package/src/router/loader-resolution.ts +91 -46
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +18 -29
- package/src/router/match-api.ts +0 -20
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +57 -58
- package/src/router/match-middleware/background-revalidation.ts +0 -7
- package/src/router/match-middleware/cache-lookup.ts +150 -271
- package/src/router/match-middleware/cache-store.ts +3 -33
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +31 -80
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +0 -116
- package/src/router/middleware.ts +118 -133
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +20 -58
- package/src/router/prerender-match.ts +99 -63
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +28 -62
- package/src/router/revalidation.ts +50 -56
- package/src/router/route-snapshot.ts +0 -1
- package/src/router/router-context.ts +0 -27
- package/src/router/router-interfaces.ts +68 -35
- package/src/router/router-options.ts +55 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +44 -63
- package/src/router/segment-resolution/helpers.ts +34 -0
- package/src/router/segment-resolution/loader-cache.ts +40 -37
- package/src/router/segment-resolution/revalidation.ts +203 -285
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-resolution.ts +4 -1
- package/src/router/segment-wrappers.ts +0 -3
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +87 -47
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +80 -41
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +83 -78
- package/src/rsc/helpers.ts +93 -5
- package/src/rsc/index.ts +1 -1
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +12 -1
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +76 -62
- package/src/rsc/rsc-rendering.ts +41 -60
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +62 -67
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +10 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -20
- package/src/segment-loader-promise.ts +14 -2
- package/src/segment-system.tsx +199 -142
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +150 -51
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +7 -24
- package/src/server/loader-registry.ts +5 -24
- package/src/server/request-context.ts +165 -87
- package/src/ssr/index.tsx +14 -14
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +618 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +232 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +348 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +330 -0
- package/src/testing/render-route.tsx +566 -0
- package/src/testing/run-loader.ts +378 -0
- package/src/testing/run-middleware.ts +205 -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 +305 -0
- package/src/theme/ThemeProvider.tsx +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +97 -22
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +6 -3
- package/src/types/request-scope.ts +0 -19
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +18 -14
- package/src/urls/include-helper.ts +9 -56
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +19 -5
- package/src/urls/path-helper.ts +17 -106
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -18
- package/src/use-loader.tsx +292 -107
- package/src/vite/debug.ts +1 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/discover-routers.ts +95 -82
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/prerender-collection.ts +26 -34
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/state.ts +39 -1
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +4 -0
- package/src/vite/plugin-types.ts +185 -10
- package/src/vite/plugins/cjs-to-esm.ts +3 -18
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +12 -11
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +4 -75
- package/src/vite/plugins/expose-id-utils.ts +3 -54
- package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +6 -74
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +0 -13
- package/src/vite/plugins/expose-internal-ids.ts +57 -67
- package/src/vite/plugins/performance-tracks.ts +9 -16
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +26 -49
- package/src/vite/plugins/vercel-output.ts +258 -0
- package/src/vite/plugins/version-injector.ts +2 -32
- package/src/vite/plugins/version-plugin.ts +32 -23
- package/src/vite/plugins/virtual-entries.ts +35 -17
- package/src/vite/rango.ts +148 -115
- package/src/vite/router-discovery.ts +220 -68
- package/src/vite/utils/ast-handler-extract.ts +15 -31
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +1 -73
- package/src/vite/utils/prerender-utils.ts +0 -35
- package/src/vite/utils/shared-utils.ts +95 -43
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
formatNestedRouterConflictError,
|
|
17
17
|
findNestedRouterConflict,
|
|
18
18
|
findRouterFiles,
|
|
19
|
+
createScanFilter,
|
|
19
20
|
} from "../build/generate-route-types.js";
|
|
21
|
+
import { firstCodeMatchIndex } from "../build/route-types/source-scan.js";
|
|
20
22
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
21
23
|
import { createVirtualStubPlugin } from "./plugins/virtual-stub-plugin.js";
|
|
22
24
|
import {
|
|
@@ -52,6 +54,11 @@ import {
|
|
|
52
54
|
import { postprocessBundle } from "./discovery/bundle-postprocess.js";
|
|
53
55
|
import { createDiscoveryGate } from "./discovery/gate-state.js";
|
|
54
56
|
import { resetStagedBuildAssets } from "./utils/prerender-utils.js";
|
|
57
|
+
import { resolveRscEntryFromConfig } from "./utils/shared-utils.js";
|
|
58
|
+
import {
|
|
59
|
+
pickForwardedRunnerConfig,
|
|
60
|
+
selectForwardableResolvePlugins,
|
|
61
|
+
} from "./utils/forward-user-plugins.js";
|
|
55
62
|
import { createRangoDebugger, timed, timedSync, NS } from "./debug.js";
|
|
56
63
|
|
|
57
64
|
const debugDiscovery = createRangoDebugger(NS.discovery);
|
|
@@ -99,7 +106,7 @@ function ensureCloudflareProtocolLoaderRegistered(): void {
|
|
|
99
106
|
// register() requires Node 18.19+ / 20.6+. Older Node still has the
|
|
100
107
|
// Vite transform as primary defense.
|
|
101
108
|
console.warn(
|
|
102
|
-
`[
|
|
109
|
+
`[rango] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`,
|
|
103
110
|
);
|
|
104
111
|
}
|
|
105
112
|
}
|
|
@@ -129,14 +136,26 @@ async function createTempRscServer(
|
|
|
129
136
|
// instead of crashing Node's native loader.
|
|
130
137
|
ensureCloudflareProtocolLoaderRegistered();
|
|
131
138
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
139
|
+
// Mirror the user's resolution config + plugins so discovery (and the
|
|
140
|
+
// prerender/static rendering that shares this runner) resolves modules the
|
|
141
|
+
// same way the real environment does. Falls back to the legacy alias-only
|
|
142
|
+
// behavior if configResolved hasn't populated the parity slice yet.
|
|
143
|
+
const runnerConfig = state.userRunnerConfig;
|
|
144
|
+
const resolveConfig = runnerConfig?.resolve ?? {
|
|
145
|
+
alias: state.userResolveAlias,
|
|
146
|
+
};
|
|
147
|
+
const oxcConfig = runnerConfig?.oxc ?? {
|
|
148
|
+
jsx: { runtime: "automatic", importSource: "react" },
|
|
149
|
+
};
|
|
132
150
|
return createViteServer({
|
|
133
151
|
root: state.projectRoot,
|
|
134
152
|
configFile: false,
|
|
135
153
|
server: { middlewareMode: true },
|
|
136
154
|
appType: "custom",
|
|
137
155
|
logLevel: "silent",
|
|
138
|
-
resolve:
|
|
139
|
-
|
|
156
|
+
resolve: resolveConfig,
|
|
157
|
+
...(runnerConfig?.define ? { define: runnerConfig.define } : {}),
|
|
158
|
+
oxc: oxcConfig as any,
|
|
140
159
|
...(options.cacheDir && { cacheDir: options.cacheDir }),
|
|
141
160
|
plugins: [
|
|
142
161
|
rsc({
|
|
@@ -155,6 +174,10 @@ async function createTempRscServer(
|
|
|
155
174
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
156
175
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : undefined),
|
|
157
176
|
exposeRouterId(),
|
|
177
|
+
// Forwarded user resolution plugins (e.g. vite-tsconfig-paths). Stripped
|
|
178
|
+
// to resolveId/load and placed last so framework resolution runs first;
|
|
179
|
+
// Vite re-sorts by `enforce`, so `enforce: "pre"` resolvers still lead.
|
|
180
|
+
...state.userResolvePlugins,
|
|
158
181
|
],
|
|
159
182
|
});
|
|
160
183
|
}
|
|
@@ -182,7 +205,7 @@ async function resolveBuildEnv(
|
|
|
182
205
|
if (option === "auto") {
|
|
183
206
|
if (factoryCtx.preset !== "cloudflare") {
|
|
184
207
|
throw new Error(
|
|
185
|
-
'[
|
|
208
|
+
'[rango] buildEnv: "auto" is only supported with preset: "cloudflare". ' +
|
|
186
209
|
"Use a factory function or plain object for other presets.",
|
|
187
210
|
);
|
|
188
211
|
}
|
|
@@ -204,7 +227,7 @@ async function resolveBuildEnv(
|
|
|
204
227
|
};
|
|
205
228
|
} catch (err: any) {
|
|
206
229
|
throw new Error(
|
|
207
|
-
'[
|
|
230
|
+
'[rango] buildEnv: "auto" requires wrangler to be installed.\n' +
|
|
208
231
|
`Install it with: pnpm add -D wrangler\n${err.message}`,
|
|
209
232
|
);
|
|
210
233
|
}
|
|
@@ -256,7 +279,7 @@ async function releaseBuildEnv(s: DiscoveryState): Promise<void> {
|
|
|
256
279
|
try {
|
|
257
280
|
await s.buildEnvDispose();
|
|
258
281
|
} catch (err: any) {
|
|
259
|
-
console.warn(`[
|
|
282
|
+
console.warn(`[rango] buildEnv dispose failed: ${err.message}`);
|
|
260
283
|
}
|
|
261
284
|
s.buildEnvDispose = null;
|
|
262
285
|
}
|
|
@@ -304,28 +327,39 @@ export function createRouterDiscoveryPlugin(
|
|
|
304
327
|
|
|
305
328
|
configResolved(config) {
|
|
306
329
|
s.projectRoot = config.root;
|
|
330
|
+
// Compile the optional discovery scan filter (glob include/exclude) now
|
|
331
|
+
// that the project root is known. findRouterFiles() below — and the
|
|
332
|
+
// build/HMR rediscovery paths — honor s.scanFilter.
|
|
333
|
+
s.scanFilter = opts?.discovery
|
|
334
|
+
? createScanFilter(s.projectRoot, opts.discovery)
|
|
335
|
+
: undefined;
|
|
307
336
|
s.isBuildMode = config.command === "build";
|
|
308
337
|
viteCommand = config.command as "serve" | "build";
|
|
309
338
|
viteMode = config.mode;
|
|
310
339
|
// Capture user's resolve aliases for the temp server
|
|
311
340
|
s.userResolveAlias = config.resolve.alias;
|
|
341
|
+
// Capture the data-only resolution config (resolve.*, define, oxc) and
|
|
342
|
+
// the user's resolution plugins (resolveId/load) so the discovery temp
|
|
343
|
+
// server resolves modules the same way the real environment does.
|
|
344
|
+
// Without this, both flavors of user resolution are absent during
|
|
345
|
+
// discovery/prerender/static rendering even though they apply at request
|
|
346
|
+
// time: third-party resolvers (e.g. vite-tsconfig-paths, forwarded as
|
|
347
|
+
// plugins) and Vite 8's native resolve.tsconfigPaths (forwarded in the
|
|
348
|
+
// data slice). See utils/forward-user-plugins.ts.
|
|
349
|
+
s.userRunnerConfig = pickForwardedRunnerConfig(config);
|
|
350
|
+
s.userResolvePlugins = selectForwardableResolvePlugins(
|
|
351
|
+
config.plugins as any,
|
|
352
|
+
);
|
|
312
353
|
// Node preset: pick up auto-discovered router path from the config() hook.
|
|
313
354
|
// The auto-discover plugin runs in config() using Vite's resolved root,
|
|
314
355
|
// populating the mutable ref before configResolved fires.
|
|
315
356
|
if (!s.resolvedEntryPath && opts?.routerPathRef?.path) {
|
|
316
357
|
s.resolvedEntryPath = opts.routerPathRef.path;
|
|
317
358
|
}
|
|
318
|
-
// Cloudflare preset:
|
|
319
|
-
// The @cloudflare/vite-plugin reads wrangler config (toml/json/jsonc)
|
|
320
|
-
// and sets optimizeDeps.entries on the RSC environment.
|
|
359
|
+
// Cloudflare preset: entry comes from the resolved RSC env config.
|
|
321
360
|
if (!s.resolvedEntryPath) {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
if (typeof entries === "string") {
|
|
325
|
-
s.resolvedEntryPath = entries;
|
|
326
|
-
} else if (Array.isArray(entries) && entries.length > 0) {
|
|
327
|
-
s.resolvedEntryPath = entries[0];
|
|
328
|
-
}
|
|
361
|
+
const entry = resolveRscEntryFromConfig(config);
|
|
362
|
+
if (entry) s.resolvedEntryPath = entry;
|
|
329
363
|
}
|
|
330
364
|
// Generate combined named-routes.gen.ts from static source parsing.
|
|
331
365
|
// Runs before the dev server starts so the gen file exists immediately for IDE.
|
|
@@ -397,7 +431,8 @@ export function createRouterDiscoveryPlugin(
|
|
|
397
431
|
releaseBuildEnv(s).catch(() => {});
|
|
398
432
|
});
|
|
399
433
|
|
|
400
|
-
// Mirror the build-path contract (
|
|
434
|
+
// Mirror the build-path contract (the buildStart hook below, which sets
|
|
435
|
+
// __rscRouterDiscoveryActive before running user modules):
|
|
401
436
|
// set __rscRouterDiscoveryActive before running user modules so any
|
|
402
437
|
// module-level router.reverse() calls return a placeholder instead
|
|
403
438
|
// of throwing. The temp Vite server's module runner has its own
|
|
@@ -512,9 +547,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
512
547
|
"getOrCreateTempServer: FAILED message=%s",
|
|
513
548
|
err.message,
|
|
514
549
|
);
|
|
515
|
-
console.warn(
|
|
516
|
-
`[rsc-router] Failed to create temp runner: ${err.message}`,
|
|
517
|
-
);
|
|
550
|
+
console.warn(`[rango] Failed to create temp runner: ${err.message}`);
|
|
518
551
|
}
|
|
519
552
|
return null;
|
|
520
553
|
}
|
|
@@ -653,7 +686,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
653
686
|
}
|
|
654
687
|
} catch (err: any) {
|
|
655
688
|
console.warn(
|
|
656
|
-
`[
|
|
689
|
+
`[rango] Cloudflare dev discovery failed: ${err.message}\n${err.stack}`,
|
|
657
690
|
);
|
|
658
691
|
}
|
|
659
692
|
|
|
@@ -705,7 +738,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
705
738
|
);
|
|
706
739
|
} catch (err: any) {
|
|
707
740
|
console.warn(
|
|
708
|
-
`[
|
|
741
|
+
`[rango] Router discovery failed: ${err.message}\n${err.stack}`,
|
|
709
742
|
);
|
|
710
743
|
} finally {
|
|
711
744
|
debugDiscovery?.(
|
|
@@ -764,20 +797,15 @@ export function createRouterDiscoveryPlugin(
|
|
|
764
797
|
if (s.mergedRouteTrie && serverMod.setRouteTrie) {
|
|
765
798
|
serverMod.setRouteTrie(s.mergedRouteTrie);
|
|
766
799
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
if (serverMod.setRouterPrecomputedEntries) {
|
|
778
|
-
for (const [routerId, entries] of s.perRouterPrecomputedMap) {
|
|
779
|
-
serverMod.setRouterPrecomputedEntries(routerId, entries);
|
|
780
|
-
}
|
|
800
|
+
const perRouterSetters: Array<[Map<string, any>, string]> = [
|
|
801
|
+
[s.perRouterManifestDataMap, "setRouterManifest"],
|
|
802
|
+
[s.perRouterTrieMap, "setRouterTrie"],
|
|
803
|
+
[s.perRouterPrecomputedMap, "setRouterPrecomputedEntries"],
|
|
804
|
+
];
|
|
805
|
+
for (const [map, fn] of perRouterSetters) {
|
|
806
|
+
const setter = serverMod[fn];
|
|
807
|
+
if (typeof setter !== "function") continue;
|
|
808
|
+
for (const [routerId, value] of map) setter(routerId, value);
|
|
781
809
|
}
|
|
782
810
|
};
|
|
783
811
|
|
|
@@ -820,7 +848,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
820
848
|
registry = serverMod.RouterRegistry ?? null;
|
|
821
849
|
} catch (err: any) {
|
|
822
850
|
console.warn(
|
|
823
|
-
`[
|
|
851
|
+
`[rango] Dev prerender module refresh failed: ${err.message}`,
|
|
824
852
|
);
|
|
825
853
|
res.statusCode = 500;
|
|
826
854
|
res.end(`Prerender handler error: ${err.message}`);
|
|
@@ -873,10 +901,9 @@ export function createRouterDiscoveryPlugin(
|
|
|
873
901
|
if (wantIntercept && result.interceptSegments?.length) {
|
|
874
902
|
payload = {
|
|
875
903
|
segments: [...result.segments, ...result.interceptSegments],
|
|
876
|
-
handles
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
},
|
|
904
|
+
// Pre-encoded MERGED handle string from the producer (handles are
|
|
905
|
+
// Flight-encoded so Promise/ReactNode values survive the wire).
|
|
906
|
+
handles: result.interceptHandles ?? "",
|
|
880
907
|
};
|
|
881
908
|
} else {
|
|
882
909
|
payload = { segments: result.segments, handles: result.handles };
|
|
@@ -886,7 +913,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
886
913
|
return;
|
|
887
914
|
} catch (err: any) {
|
|
888
915
|
console.warn(
|
|
889
|
-
`[
|
|
916
|
+
`[rango] Dev prerender failed for ${pathname}: ${err.message}`,
|
|
890
917
|
);
|
|
891
918
|
}
|
|
892
919
|
}
|
|
@@ -987,9 +1014,34 @@ export function createRouterDiscoveryPlugin(
|
|
|
987
1014
|
writeRouteTypesFiles(s),
|
|
988
1015
|
);
|
|
989
1016
|
}
|
|
1017
|
+
if (s.lastDiscoveryError) {
|
|
1018
|
+
debugDiscovery?.(
|
|
1019
|
+
"hmr: cleared lastDiscoveryError (%s) after successful rediscovery",
|
|
1020
|
+
s.lastDiscoveryError.message,
|
|
1021
|
+
);
|
|
1022
|
+
s.lastDiscoveryError = null;
|
|
1023
|
+
}
|
|
1024
|
+
// Cloudflare dev: on a successful cycle drop the workerd runner's
|
|
1025
|
+
// cached worker-entry chain so the next request re-evaluates
|
|
1026
|
+
// createRouter() with the new routes. Fired here in the work path
|
|
1027
|
+
// (not the caller's .then()) so a queued follow-up cycle that
|
|
1028
|
+
// succeeds after an earlier failed cycle still reloads:
|
|
1029
|
+
// runRefreshCycle recurses queued work without awaiting it, so the
|
|
1030
|
+
// original call already resolved on the failed cycle. A failed
|
|
1031
|
+
// cycle throws above and never reaches here, so a broken edit
|
|
1032
|
+
// never reloads the worker onto bad source.
|
|
1033
|
+
if (rscEnv && !rscEnv.runner) forceCloudflareWorkerReload(rscEnv);
|
|
990
1034
|
} catch (err: any) {
|
|
1035
|
+
s.lastDiscoveryError = {
|
|
1036
|
+
message: err?.message ?? String(err),
|
|
1037
|
+
at: Date.now(),
|
|
1038
|
+
};
|
|
991
1039
|
console.warn(
|
|
992
|
-
`[
|
|
1040
|
+
`[rango] Runtime re-discovery failed: ${err.message}`,
|
|
1041
|
+
);
|
|
1042
|
+
debugDiscovery?.(
|
|
1043
|
+
"hmr: lastDiscoveryError set (%s) — manifest preserved at last-good; recovery mode active (any in-scan source change will trigger rediscovery)",
|
|
1044
|
+
err?.message,
|
|
993
1045
|
);
|
|
994
1046
|
} finally {
|
|
995
1047
|
debugDiscovery?.(
|
|
@@ -1000,6 +1052,49 @@ export function createRouterDiscoveryPlugin(
|
|
|
1000
1052
|
});
|
|
1001
1053
|
};
|
|
1002
1054
|
|
|
1055
|
+
// Cloudflare dev only. workerd serves every request through the
|
|
1056
|
+
// runner-worker singleton, which re-resolves the worker entry per
|
|
1057
|
+
// request via runner.import("virtual:cloudflare/worker-entry"). The
|
|
1058
|
+
// route table lives in the user's createRouter() instance, captured
|
|
1059
|
+
// when that entry chain (entry -> router -> urls) was last evaluated
|
|
1060
|
+
// and then cached in the runner's evaluatedModules. The route-file
|
|
1061
|
+
// watcher refreshes discovery + types on the Node side, but the worker
|
|
1062
|
+
// keeps serving the cached (stale) router: route-definition modules
|
|
1063
|
+
// have no import.meta.hot boundary, so Vite never sends the worker an
|
|
1064
|
+
// HMR update for them and the entry chain is never evicted.
|
|
1065
|
+
//
|
|
1066
|
+
// Fix: after discovery completes, (1) invalidate the worker env's
|
|
1067
|
+
// Node-side module graph, then (2) send a full-reload to the worker.
|
|
1068
|
+
// Step (2) alone is insufficient: the full-reload handler clears the
|
|
1069
|
+
// runner's evaluatedModules and re-imports entrypoints, but each
|
|
1070
|
+
// re-import fetches the module back through this Node-side graph, which
|
|
1071
|
+
// still holds the pre-edit transform of urls.tsx — so createRouter()
|
|
1072
|
+
// rebuilds the stale route table and the new route 404s/hits the
|
|
1073
|
+
// catch-all. Invalidating the graph forces a fresh transform on
|
|
1074
|
+
// re-fetch (the same mechanism refreshTempRscEnv uses for discovery),
|
|
1075
|
+
// so the re-import re-runs createRouter() with the new routes. This is
|
|
1076
|
+
// the programmatic equivalent of the dev-server "r + enter" restart,
|
|
1077
|
+
// scoped to the worker environment instead of tearing down the server.
|
|
1078
|
+
const forceCloudflareWorkerReload = (rscEnv: any) => {
|
|
1079
|
+
if (!rscEnv?.hot) return;
|
|
1080
|
+
try {
|
|
1081
|
+
const graph = rscEnv.moduleGraph;
|
|
1082
|
+
if (graph?.invalidateAll) {
|
|
1083
|
+
graph.invalidateAll();
|
|
1084
|
+
debugDiscovery?.("hmr: invalidated workerd rsc module graph");
|
|
1085
|
+
}
|
|
1086
|
+
rscEnv.hot.send({ type: "full-reload" });
|
|
1087
|
+
debugDiscovery?.(
|
|
1088
|
+
"hmr: forced workerd rsc env reload (full-reload)",
|
|
1089
|
+
);
|
|
1090
|
+
} catch (err: any) {
|
|
1091
|
+
debugDiscovery?.(
|
|
1092
|
+
"hmr: workerd reload failed: %s",
|
|
1093
|
+
err?.message ?? err,
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1003
1098
|
const scheduleRouteRegeneration = () => {
|
|
1004
1099
|
clearTimeout(routeChangeTimer);
|
|
1005
1100
|
routeChangeTimer = setTimeout(() => {
|
|
@@ -1028,9 +1123,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
1028
1123
|
}
|
|
1029
1124
|
}
|
|
1030
1125
|
} catch (err: any) {
|
|
1031
|
-
console.error(
|
|
1032
|
-
`[rsc-router] Route regeneration error: ${err.message}`,
|
|
1033
|
-
);
|
|
1126
|
+
console.error(`[rango] Route regeneration error: ${err.message}`);
|
|
1034
1127
|
}
|
|
1035
1128
|
debugDiscovery?.(
|
|
1036
1129
|
"watcher: regenerated gen files (%sms)",
|
|
@@ -1040,12 +1133,15 @@ export function createRouterDiscoveryPlugin(
|
|
|
1040
1133
|
// routes that the static parser cannot resolve. Resolves the
|
|
1041
1134
|
// discovery gate when complete.
|
|
1042
1135
|
if (s.perRouterManifests.length > 0) {
|
|
1136
|
+
// The cloudflare workerd reload fires inside refreshRuntimeDiscovery
|
|
1137
|
+
// on the successful cycle (see forceCloudflareWorkerReload call
|
|
1138
|
+
// there) so queued follow-up cycles also trigger it.
|
|
1043
1139
|
refreshRuntimeDiscovery().catch((err: any) => {
|
|
1044
1140
|
console.warn(
|
|
1045
|
-
`[
|
|
1141
|
+
`[rango] Runtime re-discovery error: ${err.message}`,
|
|
1046
1142
|
);
|
|
1047
|
-
// Even on error, unblock the gate so workerd's reload
|
|
1048
|
-
//
|
|
1143
|
+
// Even on error, unblock the gate so workerd's reload doesn't
|
|
1144
|
+
// hang indefinitely against the previous manifest.
|
|
1049
1145
|
resolveDiscoveryGate();
|
|
1050
1146
|
});
|
|
1051
1147
|
}
|
|
@@ -1059,27 +1155,74 @@ export function createRouterDiscoveryPlugin(
|
|
|
1059
1155
|
!filePath.endsWith(".tsx") &&
|
|
1060
1156
|
!filePath.endsWith(".js") &&
|
|
1061
1157
|
!filePath.endsWith(".jsx")
|
|
1062
|
-
)
|
|
1158
|
+
) {
|
|
1159
|
+
if (s.lastDiscoveryError) {
|
|
1160
|
+
debugDiscovery?.(
|
|
1161
|
+
"watcher: skip non-source %s [LASTERR %s]",
|
|
1162
|
+
filePath,
|
|
1163
|
+
s.lastDiscoveryError.message,
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1063
1166
|
return;
|
|
1167
|
+
}
|
|
1064
1168
|
// Apply scan filter as early-exit before reading file
|
|
1065
|
-
if (s.scanFilter && !s.scanFilter(filePath))
|
|
1169
|
+
if (s.scanFilter && !s.scanFilter(filePath)) {
|
|
1170
|
+
if (s.lastDiscoveryError) {
|
|
1171
|
+
debugDiscovery?.(
|
|
1172
|
+
"watcher: skip scan-filter %s [LASTERR %s]",
|
|
1173
|
+
filePath,
|
|
1174
|
+
s.lastDiscoveryError.message,
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
// Recovery mode: when the previous HMR re-discovery failed, the
|
|
1180
|
+
// import graph is incomplete and the manifest is stuck at the
|
|
1181
|
+
// last-good state. The fix may land in a non-route file (e.g. a
|
|
1182
|
+
// helper imported by the router, a missing module being created,
|
|
1183
|
+
// or a "use client" component) that the narrow content sniff
|
|
1184
|
+
// would otherwise filter out. While in recovery, treat any
|
|
1185
|
+
// in-scan source change as a candidate for rediscovery; the
|
|
1186
|
+
// tighter filter resumes once discovery succeeds again.
|
|
1187
|
+
const inRecoveryMode = !!s.lastDiscoveryError;
|
|
1066
1188
|
try {
|
|
1067
1189
|
const source = readFileSync(filePath, "utf-8");
|
|
1068
1190
|
const trimmed = source.trimStart();
|
|
1069
|
-
|
|
1191
|
+
const isUseClient =
|
|
1070
1192
|
trimmed.startsWith('"use client"') ||
|
|
1071
|
-
trimmed.startsWith("'use client'")
|
|
1072
|
-
)
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
)
|
|
1193
|
+
trimmed.startsWith("'use client'");
|
|
1194
|
+
if (!inRecoveryMode && isUseClient) return;
|
|
1195
|
+
// Cheap raw pre-check first; only when a candidate token is present
|
|
1196
|
+
// do we confirm it occurs in real code (not a comment/string) via a
|
|
1197
|
+
// single allocation-free code-region scan. Most saved files contain
|
|
1198
|
+
// neither token and skip the scan entirely. This avoids a comment or
|
|
1199
|
+
// string mention spuriously marking a file relevant and triggering an
|
|
1200
|
+
// unnecessary re-discovery on save.
|
|
1201
|
+
let hasUrls = source.includes("urls(");
|
|
1202
|
+
let hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
1203
|
+
if (hasUrls) hasUrls = firstCodeMatchIndex(source, /urls\(/g) >= 0;
|
|
1204
|
+
if (hasCreateRouter) {
|
|
1205
|
+
hasCreateRouter =
|
|
1206
|
+
firstCodeMatchIndex(source, /\bcreateRouter\s*[<(]/g) >= 0;
|
|
1207
|
+
}
|
|
1208
|
+
if (!inRecoveryMode && !hasUrls && !hasCreateRouter) return;
|
|
1209
|
+
if (inRecoveryMode) {
|
|
1210
|
+
debugDiscovery?.(
|
|
1211
|
+
"watcher: recovery rediscovery for %s (urls=%s, router=%s, useClient=%s) [LASTERR %s]",
|
|
1212
|
+
filePath,
|
|
1213
|
+
hasUrls,
|
|
1214
|
+
hasCreateRouter,
|
|
1215
|
+
isUseClient,
|
|
1216
|
+
s.lastDiscoveryError!.message,
|
|
1217
|
+
);
|
|
1218
|
+
} else {
|
|
1219
|
+
debugDiscovery?.(
|
|
1220
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
1221
|
+
filePath,
|
|
1222
|
+
hasUrls,
|
|
1223
|
+
hasCreateRouter,
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1083
1226
|
// Invalidate cache when a router file changes (new router added/removed)
|
|
1084
1227
|
if (hasCreateRouter) {
|
|
1085
1228
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
@@ -1106,7 +1249,15 @@ export function createRouterDiscoveryPlugin(
|
|
|
1106
1249
|
gate.noteRouteEvent();
|
|
1107
1250
|
}
|
|
1108
1251
|
scheduleRouteRegeneration();
|
|
1109
|
-
} catch {
|
|
1252
|
+
} catch (readErr: any) {
|
|
1253
|
+
if (s.lastDiscoveryError) {
|
|
1254
|
+
debugDiscovery?.(
|
|
1255
|
+
"watcher: read error %s: %s [LASTERR %s]",
|
|
1256
|
+
filePath,
|
|
1257
|
+
readErr?.message,
|
|
1258
|
+
s.lastDiscoveryError.message,
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1110
1261
|
// Ignore read errors for deleted/moved files
|
|
1111
1262
|
}
|
|
1112
1263
|
};
|
|
@@ -1169,7 +1320,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
1169
1320
|
const rscEnv = (tempServer.environments as any)?.rsc;
|
|
1170
1321
|
if (!rscEnv?.runner) {
|
|
1171
1322
|
console.warn(
|
|
1172
|
-
"[
|
|
1323
|
+
"[rango] RSC environment runner not available during build, skipping manifest generation",
|
|
1173
1324
|
);
|
|
1174
1325
|
return;
|
|
1175
1326
|
}
|
|
@@ -1212,7 +1363,8 @@ export function createRouterDiscoveryPlugin(
|
|
|
1212
1363
|
.filter(Boolean)
|
|
1213
1364
|
.join("\n");
|
|
1214
1365
|
throw new Error(
|
|
1215
|
-
`[
|
|
1366
|
+
`[rango] Build-time router discovery failed:\n${details}`,
|
|
1367
|
+
{ cause: err },
|
|
1216
1368
|
);
|
|
1217
1369
|
} finally {
|
|
1218
1370
|
delete (globalThis as any).__rscRouterDiscoveryActive;
|
|
@@ -1239,7 +1391,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
1239
1391
|
// `consumeSelfGenWrite` inside `maybeHandleGeneratedRouteFileMutation`),
|
|
1240
1392
|
// AND vite's own HMR pipeline (which invalidates the gen file's
|
|
1241
1393
|
// importers and triggers a second workerd full reload — visible to the
|
|
1242
|
-
// user as a duplicate "[
|
|
1394
|
+
// user as a duplicate "[Rango] HMR: version changed" on the client).
|
|
1243
1395
|
//
|
|
1244
1396
|
// `peekSelfGenWrite` is the authoritative filter: its map only contains
|
|
1245
1397
|
// paths that `markSelfGenWrite` has registered, so it natively works
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type MagicString from "magic-string";
|
|
2
2
|
import { hashInlineId, buildExportMap } from "../plugins/expose-id-utils.js";
|
|
3
3
|
|
|
4
|
-
// ---------------------------------------------------------------------------
|
|
5
|
-
// Types
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
|
|
8
4
|
/** Minimal ESTree Program node — avoids importing from `rollup` (not a direct dep). */
|
|
9
5
|
interface ProgramNode {
|
|
10
6
|
type: "Program";
|
|
@@ -48,7 +44,7 @@ function findImportInsertionPos(
|
|
|
48
44
|
): number {
|
|
49
45
|
let program: ProgramNode;
|
|
50
46
|
try {
|
|
51
|
-
program = parseAst(code, {
|
|
47
|
+
program = parseAst(code, { lang: "tsx" });
|
|
52
48
|
} catch {
|
|
53
49
|
return 0;
|
|
54
50
|
}
|
|
@@ -70,10 +66,6 @@ function findImportInsertionPos(
|
|
|
70
66
|
return insertionPos;
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
// AST walking helper
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
|
|
77
69
|
/**
|
|
78
70
|
* Recursively walk an ESTree AST node, calling `enter` on each node.
|
|
79
71
|
* Parent is passed for context.
|
|
@@ -111,10 +103,6 @@ function walkNode(
|
|
|
111
103
|
ancestors.pop();
|
|
112
104
|
}
|
|
113
105
|
|
|
114
|
-
// ---------------------------------------------------------------------------
|
|
115
|
-
// AST analysis
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
|
|
118
106
|
/**
|
|
119
107
|
* Parse the file with Vite's parseAst and find all calls to `fnName`.
|
|
120
108
|
* Distinguishes between `export const X = fnName(...)` (exportInfo set)
|
|
@@ -127,7 +115,7 @@ export function findHandlerCalls(
|
|
|
127
115
|
): HandlerCallSite[] {
|
|
128
116
|
let program: ProgramNode;
|
|
129
117
|
try {
|
|
130
|
-
program = parseAst(code, {
|
|
118
|
+
program = parseAst(code, { lang: "tsx" });
|
|
131
119
|
} catch {
|
|
132
120
|
return [];
|
|
133
121
|
}
|
|
@@ -239,7 +227,7 @@ export function getImportedLocalNames(
|
|
|
239
227
|
parseAst: (code: string, options?: any) => ProgramNode,
|
|
240
228
|
): Set<string> {
|
|
241
229
|
try {
|
|
242
|
-
const program = parseAst(code, {
|
|
230
|
+
const program = parseAst(code, { lang: "tsx" });
|
|
243
231
|
return getImportedLocalNamesFromProgram(program, importedName);
|
|
244
232
|
} catch {
|
|
245
233
|
return new Set<string>();
|
|
@@ -256,7 +244,7 @@ export function extractImportDeclarations(
|
|
|
256
244
|
): string[] {
|
|
257
245
|
let program: ProgramNode;
|
|
258
246
|
try {
|
|
259
|
-
program = parseAst(code, {
|
|
247
|
+
program = parseAst(code, { lang: "tsx" });
|
|
260
248
|
} catch {
|
|
261
249
|
return [];
|
|
262
250
|
}
|
|
@@ -380,7 +368,7 @@ export function extractModuleLevelDeclarations(
|
|
|
380
368
|
): string[] {
|
|
381
369
|
let program: ProgramNode;
|
|
382
370
|
try {
|
|
383
|
-
program = parseAst(code, {
|
|
371
|
+
program = parseAst(code, { lang: "tsx" });
|
|
384
372
|
} catch {
|
|
385
373
|
return [];
|
|
386
374
|
}
|
|
@@ -426,10 +414,6 @@ export function extractModuleLevelDeclarations(
|
|
|
426
414
|
return declarations;
|
|
427
415
|
}
|
|
428
416
|
|
|
429
|
-
// ---------------------------------------------------------------------------
|
|
430
|
-
// Transform
|
|
431
|
-
// ---------------------------------------------------------------------------
|
|
432
|
-
|
|
433
417
|
/**
|
|
434
418
|
* Transform inline handler calls by extracting them into virtual modules.
|
|
435
419
|
* Only processes inline calls (exportInfo === null); export const calls are
|
|
@@ -468,19 +452,19 @@ export function transformInlineHandlers(
|
|
|
468
452
|
handlerNames,
|
|
469
453
|
);
|
|
470
454
|
|
|
471
|
-
// Track line occurrences for same-line collision handling
|
|
472
|
-
const lineCounts = new Map<number, number>();
|
|
473
|
-
|
|
474
455
|
// Collect all import statements to prepend
|
|
475
456
|
const importStatements: string[] = [];
|
|
476
457
|
|
|
477
|
-
for (const site of inlineSites) {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
458
|
+
for (const [siteIndex, site] of inlineSites.entries()) {
|
|
459
|
+
// Key the extracted handler on its source-order index (per fnName), NOT its
|
|
460
|
+
// line number. The id flows into BOTH the export name and the virtual module
|
|
461
|
+
// path (which hashId hashes for the runtime $$id), and line numbers shift
|
|
462
|
+
// between the prerender and production build contexts. The index is invariant
|
|
463
|
+
// to those shifts, keeping the prerender manifest key == the runtime id.
|
|
464
|
+
const hash = hashInlineId(filePath, fnName, siteIndex);
|
|
482
465
|
const exportName = `__sh_${hash}`;
|
|
483
|
-
const
|
|
466
|
+
const idSuffix = `${filePath}:${fnName}:${siteIndex}`;
|
|
467
|
+
const virtualId = `\0${virtualPrefix}${idSuffix}`;
|
|
484
468
|
|
|
485
469
|
// Extract the full handler call expression text
|
|
486
470
|
const handlerCode = code.slice(site.callStart, site.callEnd);
|
|
@@ -498,7 +482,7 @@ export function transformInlineHandlers(
|
|
|
498
482
|
s.overwrite(site.callStart, site.callEnd, exportName);
|
|
499
483
|
|
|
500
484
|
// Build the import specifier for this virtual module
|
|
501
|
-
const importId = `${virtualPrefix}${
|
|
485
|
+
const importId = `${virtualPrefix}${idSuffix}`;
|
|
502
486
|
importStatements.push(`import { ${exportName} } from "${importId}";`);
|
|
503
487
|
}
|
|
504
488
|
|