@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1c0bdfad
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/AGENTS.md +17 -0
- package/README.md +291 -61
- package/dist/bin/rango.js +544 -143
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3744 -1329
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +67 -13
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +312 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +247 -23
- package/skills/caching/SKILL.md +322 -19
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +282 -60
- package/skills/host-router/SKILL.md +278 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +50 -6
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +297 -31
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +771 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +203 -7
- package/skills/prerender/SKILL.md +155 -111
- package/skills/rango/SKILL.md +251 -23
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +104 -9
- package/skills/router-setup/SKILL.md +124 -11
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +125 -222
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -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 +123 -0
- package/skills/typesafety/SKILL.md +357 -52
- package/skills/use-cache/SKILL.md +46 -14
- 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 +67 -40
- package/src/bin/rango.ts +18 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +197 -150
- 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/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +200 -30
- package/src/browser/navigation-client.ts +217 -58
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +76 -67
- package/src/browser/navigation-transaction.ts +18 -66
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +187 -112
- package/src/browser/prefetch/cache.ts +312 -30
- package/src/browser/prefetch/fetch.ts +344 -47
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +126 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +125 -18
- package/src/browser/react/NavigationProvider.tsx +135 -120
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -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 +23 -69
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +32 -7
- package/src/browser/react/use-params.ts +20 -10
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +46 -11
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +80 -5
- package/src/browser/rsc-router.tsx +226 -75
- package/src/browser/scroll-restoration.ts +54 -42
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +619 -442
- package/src/browser/types.ts +115 -11
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +65 -40
- package/src/build/generate-route-types.ts +7 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +182 -37
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +125 -24
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +392 -106
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +214 -48
- package/src/cache/cache-scope.ts +236 -89
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2224 -171
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +11 -17
- package/src/cache/document-cache.ts +89 -27
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +11 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +31 -31
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +45 -21
- package/src/client.tsx +120 -336
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +84 -2
- package/src/debug.ts +2 -2
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +56 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +95 -0
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -5
- package/src/host/pattern-matcher.ts +23 -52
- 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 +79 -29
- package/src/index.ts +149 -65
- package/src/internal-debug.ts +11 -10
- 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/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +63 -26
- package/src/prerender.ts +198 -82
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +469 -276
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +113 -37
- package/src/route-definition/index.ts +3 -3
- package/src/route-definition/redirect.ts +53 -12
- package/src/route-definition/resolve-handler-use.ts +161 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +7 -17
- package/src/route-types.ts +37 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +164 -17
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +45 -22
- package/src/router/handler-context.ts +110 -39
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +50 -24
- package/src/router/lazy-includes.ts +19 -53
- package/src/router/loader-resolution.ts +274 -56
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +49 -45
- package/src/router/match-api.ts +121 -205
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +33 -6
- package/src/router/match-middleware/cache-lookup.ts +214 -263
- package/src/router/match-middleware/cache-store.ts +73 -33
- package/src/router/match-middleware/intercept-resolution.ts +8 -28
- package/src/router/match-middleware/segment-resolution.ts +52 -18
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +104 -49
- package/src/router/metrics.ts +217 -26
- package/src/router/middleware-types.ts +24 -110
- package/src/router/middleware.ts +384 -197
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +148 -91
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +199 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +144 -74
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +8 -28
- package/src/router/router-interfaces.ts +129 -36
- package/src/router/router-options.ts +185 -23
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +281 -76
- package/src/router/segment-resolution/helpers.ts +116 -31
- package/src/router/segment-resolution/loader-cache.ts +63 -37
- package/src/router/segment-resolution/revalidation.ts +493 -391
- 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 +5 -1
- package/src/router/segment-wrappers.ts +8 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +180 -58
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +182 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +702 -460
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +127 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +98 -19
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +99 -189
- package/src/rsc/rsc-rendering.ts +126 -106
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +269 -114
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/types.ts +34 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +49 -41
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +281 -129
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +317 -63
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +26 -46
- package/src/server/request-context.ts +425 -177
- package/src/server.ts +6 -0
- package/src/ssr/index.tsx +25 -16
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +701 -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 +257 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +371 -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 +343 -0
- package/src/testing/render-route.tsx +581 -0
- package/src/testing/run-loader.ts +385 -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 +20 -58
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +3 -19
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +236 -88
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +10 -45
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -19
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +58 -11
- package/src/urls/path-helper.ts +57 -111
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -18
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +64 -91
- package/src/vite/discovery/discover-routers.ts +147 -88
- 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 +247 -145
- 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 +61 -13
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +10 -3
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +155 -65
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- 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 +194 -0
- package/src/vite/plugins/expose-action-id.ts +49 -98
- package/src/vite/plugins/expose-id-utils.ts +96 -51
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +553 -317
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +21 -25
- package/src/vite/plugins/version-plugin.ts +46 -37
- package/src/vite/plugins/virtual-entries.ts +13 -18
- package/src/vite/rango.ts +241 -287
- package/src/vite/router-discovery.ts +956 -149
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -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 +20 -52
- package/src/vite/utils/prerender-utils.ts +141 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- package/CLAUDE.md +0 -5
- 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 -6
- package/src/network-error-thrower.tsx +0 -23
- package/src/route-definition/route-function.ts +0 -119
- package/src/router/middleware-cookies.ts +0 -55
package/dist/bin/rango.js
CHANGED
|
@@ -22,10 +22,10 @@ function extractParamsFromPattern(pattern) {
|
|
|
22
22
|
function formatRouteEntry(key, pattern, _params, search) {
|
|
23
23
|
const hasSearch = search && Object.keys(search).length > 0;
|
|
24
24
|
if (!hasSearch) {
|
|
25
|
-
return ` ${key}:
|
|
25
|
+
return ` ${key}: ${JSON.stringify(pattern)},`;
|
|
26
26
|
}
|
|
27
|
-
const searchBody = Object.entries(search).map(([k, v]) => `${k}:
|
|
28
|
-
return ` ${key}: { path:
|
|
27
|
+
const searchBody = Object.entries(search).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ");
|
|
28
|
+
return ` ${key}: { path: ${JSON.stringify(pattern)}, search: { ${searchBody} } },`;
|
|
29
29
|
}
|
|
30
30
|
var init_param_extraction = __esm({
|
|
31
31
|
"src/build/route-types/param-extraction.ts"() {
|
|
@@ -59,8 +59,8 @@ var init_ast_helpers = __esm({
|
|
|
59
59
|
|
|
60
60
|
// src/build/route-types/ast-route-extraction.ts
|
|
61
61
|
import ts2 from "typescript";
|
|
62
|
-
function extractRoutesFromSource(code) {
|
|
63
|
-
const sourceFile = ts2.createSourceFile(
|
|
62
|
+
function extractRoutesFromSource(code, sourceFileArg) {
|
|
63
|
+
const sourceFile = sourceFileArg ?? ts2.createSourceFile(
|
|
64
64
|
"input.tsx",
|
|
65
65
|
code,
|
|
66
66
|
ts2.ScriptTarget.Latest,
|
|
@@ -139,7 +139,7 @@ function generatePerModuleTypesSource(routes) {
|
|
|
139
139
|
const valid = routes.filter(({ name }) => {
|
|
140
140
|
if (!name || /["'\\`\n\r]/.test(name)) {
|
|
141
141
|
console.warn(
|
|
142
|
-
`[
|
|
142
|
+
`[rango] Skipping route with invalid name: ${JSON.stringify(name)}`
|
|
143
143
|
);
|
|
144
144
|
return false;
|
|
145
145
|
}
|
|
@@ -149,7 +149,7 @@ function generatePerModuleTypesSource(routes) {
|
|
|
149
149
|
for (const { name, pattern, params, search } of valid) {
|
|
150
150
|
if (deduped.has(name)) {
|
|
151
151
|
console.warn(
|
|
152
|
-
`[
|
|
152
|
+
`[rango] Duplicate route name "${name}" \u2014 keeping first definition`
|
|
153
153
|
);
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
@@ -185,9 +185,13 @@ export const NamedRoutes = {
|
|
|
185
185
|
${objectBody}
|
|
186
186
|
} as const;
|
|
187
187
|
|
|
188
|
+
// Aliased so the augmentation below does not pay a homomorphic mapped-type
|
|
189
|
+
// instantiation per route; \`as const\` already makes the members readonly.
|
|
190
|
+
type NamedRoutesShape = typeof NamedRoutes;
|
|
191
|
+
|
|
188
192
|
declare global {
|
|
189
|
-
namespace
|
|
190
|
-
interface GeneratedRouteMap extends
|
|
193
|
+
namespace Rango {
|
|
194
|
+
interface GeneratedRouteMap extends NamedRoutesShape {}
|
|
191
195
|
}
|
|
192
196
|
}
|
|
193
197
|
`;
|
|
@@ -211,14 +215,15 @@ function findTsFiles(dir, filter) {
|
|
|
211
215
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
212
216
|
} catch (err) {
|
|
213
217
|
console.warn(
|
|
214
|
-
`[
|
|
218
|
+
`[rango] Failed to scan directory ${dir}: ${err.message}`
|
|
215
219
|
);
|
|
216
220
|
return results;
|
|
217
221
|
}
|
|
218
222
|
for (const entry of entries) {
|
|
219
223
|
const fullPath = join(dir, entry.name);
|
|
220
224
|
if (entry.isDirectory()) {
|
|
221
|
-
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
225
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".") || entry.name === "dist" || entry.name === "build" || entry.name === "coverage")
|
|
226
|
+
continue;
|
|
222
227
|
results.push(...findTsFiles(fullPath, filter));
|
|
223
228
|
} else if ((entry.name.endsWith(".ts") || entry.name.endsWith(".tsx") || entry.name.endsWith(".js") || entry.name.endsWith(".jsx")) && !entry.name.includes(".gen.")) {
|
|
224
229
|
if (filter && !filter(fullPath)) continue;
|
|
@@ -237,6 +242,33 @@ var init_scan_filter = __esm({
|
|
|
237
242
|
import { readFileSync, existsSync } from "node:fs";
|
|
238
243
|
import { dirname, resolve } from "node:path";
|
|
239
244
|
import ts3 from "typescript";
|
|
245
|
+
function createScanMemo() {
|
|
246
|
+
return { files: /* @__PURE__ */ new Map(), blockSourceFiles: /* @__PURE__ */ new Map() };
|
|
247
|
+
}
|
|
248
|
+
function parseBlock(memo, block) {
|
|
249
|
+
if (memo) {
|
|
250
|
+
const cached = memo.blockSourceFiles.get(block);
|
|
251
|
+
if (cached) return cached;
|
|
252
|
+
}
|
|
253
|
+
const sf = ts3.createSourceFile(
|
|
254
|
+
"input.tsx",
|
|
255
|
+
block,
|
|
256
|
+
ts3.ScriptTarget.Latest,
|
|
257
|
+
true,
|
|
258
|
+
ts3.ScriptKind.TSX
|
|
259
|
+
);
|
|
260
|
+
if (memo) memo.blockSourceFiles.set(block, sf);
|
|
261
|
+
return sf;
|
|
262
|
+
}
|
|
263
|
+
function readSourceMemoized(memo, realPath) {
|
|
264
|
+
if (memo) {
|
|
265
|
+
const cached = memo.files.get(realPath);
|
|
266
|
+
if (cached !== void 0) return cached;
|
|
267
|
+
}
|
|
268
|
+
const source = readFileSync(realPath, "utf-8");
|
|
269
|
+
if (memo) memo.files.set(realPath, source);
|
|
270
|
+
return source;
|
|
271
|
+
}
|
|
240
272
|
function extractNamePrefixFromInclude(node) {
|
|
241
273
|
if (node.arguments.length >= 3) {
|
|
242
274
|
const thirdArg = node.arguments[2];
|
|
@@ -252,8 +284,8 @@ function extractNamePrefixFromInclude(node) {
|
|
|
252
284
|
}
|
|
253
285
|
return null;
|
|
254
286
|
}
|
|
255
|
-
function extractIncludesWithDiagnostics(code) {
|
|
256
|
-
const sourceFile = ts3.createSourceFile(
|
|
287
|
+
function extractIncludesWithDiagnostics(code, sourceFileArg) {
|
|
288
|
+
const sourceFile = sourceFileArg ?? ts3.createSourceFile(
|
|
257
289
|
"input.tsx",
|
|
258
290
|
code,
|
|
259
291
|
ts3.ScriptTarget.Latest,
|
|
@@ -307,7 +339,7 @@ function extractIncludesWithDiagnostics(code) {
|
|
|
307
339
|
return { resolved, unresolvable };
|
|
308
340
|
}
|
|
309
341
|
function resolveImportedVariable(code, localName) {
|
|
310
|
-
const importRegex = /import\s
|
|
342
|
+
const importRegex = /import\s*(?:[\w$]+\s*,\s*)?\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
|
|
311
343
|
let match;
|
|
312
344
|
while ((match = importRegex.exec(code)) !== null) {
|
|
313
345
|
const imports = match[1];
|
|
@@ -344,8 +376,8 @@ function resolveImportPath(importSpec, fromFile) {
|
|
|
344
376
|
}
|
|
345
377
|
return null;
|
|
346
378
|
}
|
|
347
|
-
function extractUrlsBlockForVariable(code, varName) {
|
|
348
|
-
const sourceFile = ts3.createSourceFile(
|
|
379
|
+
function extractUrlsBlockForVariable(code, varName, sourceFileArg) {
|
|
380
|
+
const sourceFile = sourceFileArg ?? ts3.createSourceFile(
|
|
349
381
|
"input.tsx",
|
|
350
382
|
code,
|
|
351
383
|
ts3.ScriptTarget.Latest,
|
|
@@ -367,16 +399,20 @@ function extractUrlsBlockForVariable(code, varName) {
|
|
|
367
399
|
visit(sourceFile);
|
|
368
400
|
return result;
|
|
369
401
|
}
|
|
370
|
-
function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSchemasOut, diagnosticsOut) {
|
|
402
|
+
function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSchemasOut, diagnosticsOut, memo) {
|
|
371
403
|
const routeMap = {};
|
|
372
|
-
const
|
|
404
|
+
const blockSourceFile = parseBlock(memo, block);
|
|
405
|
+
const localRoutes = extractRoutesFromSource(block, blockSourceFile);
|
|
373
406
|
for (const { name, pattern, search } of localRoutes) {
|
|
374
407
|
routeMap[name] = pattern;
|
|
375
408
|
if (search && searchSchemasOut) {
|
|
376
409
|
searchSchemasOut[name] = search;
|
|
377
410
|
}
|
|
378
411
|
}
|
|
379
|
-
const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(
|
|
412
|
+
const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(
|
|
413
|
+
block,
|
|
414
|
+
blockSourceFile
|
|
415
|
+
);
|
|
380
416
|
if (diagnosticsOut) {
|
|
381
417
|
for (const entry of unresolvable) {
|
|
382
418
|
diagnosticsOut.push({ ...entry, sourceFile: filePath });
|
|
@@ -403,12 +439,15 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
|
|
|
403
439
|
targetFile,
|
|
404
440
|
imported.exportedName,
|
|
405
441
|
visited,
|
|
406
|
-
diagnosticsOut
|
|
442
|
+
diagnosticsOut,
|
|
443
|
+
void 0,
|
|
444
|
+
memo
|
|
407
445
|
);
|
|
408
446
|
} else {
|
|
409
447
|
const sameFileBlock = extractUrlsBlockForVariable(
|
|
410
448
|
fullSource,
|
|
411
|
-
variableName
|
|
449
|
+
variableName,
|
|
450
|
+
parseBlock(memo, fullSource)
|
|
412
451
|
);
|
|
413
452
|
if (!sameFileBlock) {
|
|
414
453
|
if (diagnosticsOut) {
|
|
@@ -426,7 +465,9 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
|
|
|
426
465
|
filePath,
|
|
427
466
|
variableName,
|
|
428
467
|
visited,
|
|
429
|
-
diagnosticsOut
|
|
468
|
+
diagnosticsOut,
|
|
469
|
+
void 0,
|
|
470
|
+
memo
|
|
430
471
|
);
|
|
431
472
|
}
|
|
432
473
|
if (namePrefix === null) {
|
|
@@ -450,24 +491,31 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
|
|
|
450
491
|
}
|
|
451
492
|
return routeMap;
|
|
452
493
|
}
|
|
453
|
-
function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut) {
|
|
494
|
+
function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut, inlineBlock, memo) {
|
|
454
495
|
visited = visited ?? /* @__PURE__ */ new Set();
|
|
496
|
+
memo = memo ?? createScanMemo();
|
|
455
497
|
const realPath = resolve(filePath);
|
|
456
498
|
const key = variableName ? `${realPath}:${variableName}` : realPath;
|
|
457
499
|
if (visited.has(key)) {
|
|
458
|
-
console.warn(`[
|
|
500
|
+
console.warn(`[rango] Circular include detected, skipping: ${key}`);
|
|
459
501
|
return { routes: {}, searchSchemas: {} };
|
|
460
502
|
}
|
|
461
503
|
visited.add(key);
|
|
462
504
|
let source;
|
|
463
505
|
try {
|
|
464
|
-
source =
|
|
506
|
+
source = readSourceMemoized(memo, realPath);
|
|
465
507
|
} catch {
|
|
466
508
|
return { routes: {}, searchSchemas: {} };
|
|
467
509
|
}
|
|
468
510
|
let block;
|
|
469
|
-
if (
|
|
470
|
-
|
|
511
|
+
if (inlineBlock) {
|
|
512
|
+
block = inlineBlock;
|
|
513
|
+
} else if (variableName) {
|
|
514
|
+
const extracted = extractUrlsBlockForVariable(
|
|
515
|
+
source,
|
|
516
|
+
variableName,
|
|
517
|
+
parseBlock(memo, source)
|
|
518
|
+
);
|
|
471
519
|
if (!extracted) return { routes: {}, searchSchemas: {} };
|
|
472
520
|
block = extracted;
|
|
473
521
|
} else {
|
|
@@ -480,7 +528,8 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
|
|
|
480
528
|
realPath,
|
|
481
529
|
visited,
|
|
482
530
|
searchSchemas,
|
|
483
|
-
diagnosticsOut
|
|
531
|
+
diagnosticsOut,
|
|
532
|
+
memo
|
|
484
533
|
);
|
|
485
534
|
visited.delete(key);
|
|
486
535
|
return { routes, searchSchemas };
|
|
@@ -525,8 +574,16 @@ function writePerModuleRouteTypesForFile(filePath) {
|
|
|
525
574
|
let routes;
|
|
526
575
|
if (varNames.length > 0) {
|
|
527
576
|
routes = [];
|
|
577
|
+
const memo = createScanMemo();
|
|
528
578
|
for (const varName of varNames) {
|
|
529
|
-
const { routes: routeMap, searchSchemas } = buildCombinedRouteMapWithSearch(
|
|
579
|
+
const { routes: routeMap, searchSchemas } = buildCombinedRouteMapWithSearch(
|
|
580
|
+
filePath,
|
|
581
|
+
varName,
|
|
582
|
+
void 0,
|
|
583
|
+
void 0,
|
|
584
|
+
void 0,
|
|
585
|
+
memo
|
|
586
|
+
);
|
|
530
587
|
for (const [name, pattern] of Object.entries(routeMap)) {
|
|
531
588
|
const params = extractParamsFromPattern(pattern);
|
|
532
589
|
routes.push({
|
|
@@ -540,12 +597,12 @@ function writePerModuleRouteTypesForFile(filePath) {
|
|
|
540
597
|
} else {
|
|
541
598
|
routes = extractRoutesFromSource(source);
|
|
542
599
|
}
|
|
543
|
-
const genPath = filePath.replace(/\.(tsx?)$/, ".gen.ts");
|
|
600
|
+
const genPath = filePath.replace(/\.(tsx?|jsx?)$/, ".gen.ts");
|
|
544
601
|
if (routes.length === 0) {
|
|
545
602
|
if (varNames.length > 0 && !existsSync2(genPath)) {
|
|
546
603
|
writeFileSync(genPath, generatePerModuleTypesSource([]));
|
|
547
604
|
console.log(
|
|
548
|
-
`[
|
|
605
|
+
`[rango] Generated route types (placeholder) -> ${genPath}`
|
|
549
606
|
);
|
|
550
607
|
}
|
|
551
608
|
return;
|
|
@@ -554,11 +611,11 @@ function writePerModuleRouteTypesForFile(filePath) {
|
|
|
554
611
|
const existing = existsSync2(genPath) ? readFileSync2(genPath, "utf-8") : null;
|
|
555
612
|
if (existing !== genSource) {
|
|
556
613
|
writeFileSync(genPath, genSource);
|
|
557
|
-
console.log(`[
|
|
614
|
+
console.log(`[rango] Generated route types -> ${genPath}`);
|
|
558
615
|
}
|
|
559
616
|
} catch (err) {
|
|
560
617
|
console.warn(
|
|
561
|
-
`[
|
|
618
|
+
`[rango] Failed to generate route types for ${filePath}: ${err.message}`
|
|
562
619
|
);
|
|
563
620
|
}
|
|
564
621
|
}
|
|
@@ -573,9 +630,146 @@ var init_per_module_writer = __esm({
|
|
|
573
630
|
}
|
|
574
631
|
});
|
|
575
632
|
|
|
633
|
+
// src/build/route-types/source-scan.ts
|
|
634
|
+
function isLineTerminator(ch) {
|
|
635
|
+
const c = ch.charCodeAt(0);
|
|
636
|
+
return c === 10 || c === 13 || c === 8232 || c === 8233;
|
|
637
|
+
}
|
|
638
|
+
function isRegexPositionAt(code, slashPos, prevChar) {
|
|
639
|
+
if (prevChar === void 0) return true;
|
|
640
|
+
if (prevChar === ")" || prevChar === "]" || prevChar === "}") return false;
|
|
641
|
+
if (!/[\w$]/.test(prevChar)) return true;
|
|
642
|
+
let k = slashPos - 1;
|
|
643
|
+
while (k >= 0 && /\s/.test(code[k])) k--;
|
|
644
|
+
const wordEnd = k + 1;
|
|
645
|
+
while (k >= 0 && /[\w$]/.test(code[k])) k--;
|
|
646
|
+
return REGEX_PRECEDING_KEYWORDS.has(code.slice(k + 1, wordEnd));
|
|
647
|
+
}
|
|
648
|
+
function makeCodeClassifier(code) {
|
|
649
|
+
const n = code.length;
|
|
650
|
+
let i = 0;
|
|
651
|
+
let skipStart = -1;
|
|
652
|
+
let skipEnd = -1;
|
|
653
|
+
let lastSig;
|
|
654
|
+
return (q) => {
|
|
655
|
+
if (q >= skipStart && q < skipEnd) return false;
|
|
656
|
+
while (i < n && i <= q) {
|
|
657
|
+
const c = code[i];
|
|
658
|
+
const d = i + 1 < n ? code[i + 1] : "";
|
|
659
|
+
let end = -1;
|
|
660
|
+
let transparent = false;
|
|
661
|
+
if (c === "/" && d === "/") {
|
|
662
|
+
let j = i + 2;
|
|
663
|
+
while (j < n && !isLineTerminator(code[j])) j++;
|
|
664
|
+
end = j;
|
|
665
|
+
transparent = true;
|
|
666
|
+
} else if (c === "/" && d === "*") {
|
|
667
|
+
let j = i + 2;
|
|
668
|
+
while (j < n && !(code[j] === "*" && code[j + 1] === "/")) j++;
|
|
669
|
+
end = Math.min(n, j + 2);
|
|
670
|
+
transparent = true;
|
|
671
|
+
} else if (c === '"' || c === "'" || c === "`") {
|
|
672
|
+
let j = i + 1;
|
|
673
|
+
while (j < n) {
|
|
674
|
+
if (code[j] === "\\") {
|
|
675
|
+
j += 2;
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
if (code[j] === c) {
|
|
679
|
+
j++;
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
j++;
|
|
683
|
+
}
|
|
684
|
+
end = j;
|
|
685
|
+
} else if (c === "/" && d !== "/" && d !== "*" && isRegexPositionAt(code, i, lastSig)) {
|
|
686
|
+
let j = i + 1;
|
|
687
|
+
let inClass = false;
|
|
688
|
+
let closed = false;
|
|
689
|
+
while (j < n && !isLineTerminator(code[j])) {
|
|
690
|
+
const r = code[j];
|
|
691
|
+
if (r === "\\") {
|
|
692
|
+
j += 2;
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
if (r === "[") inClass = true;
|
|
696
|
+
else if (r === "]") inClass = false;
|
|
697
|
+
else if (r === "/" && !inClass) {
|
|
698
|
+
j++;
|
|
699
|
+
closed = true;
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
702
|
+
j++;
|
|
703
|
+
}
|
|
704
|
+
if (closed) {
|
|
705
|
+
while (j < n && /[a-z]/.test(code[j])) j++;
|
|
706
|
+
end = j;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
if (end >= 0) {
|
|
710
|
+
if (q < end) {
|
|
711
|
+
skipStart = i;
|
|
712
|
+
skipEnd = end;
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
i = end;
|
|
716
|
+
if (!transparent) lastSig = "x";
|
|
717
|
+
} else {
|
|
718
|
+
if (!/\s/.test(c)) lastSig = c;
|
|
719
|
+
i++;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return true;
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function firstCodeMatchIndex(code, pattern) {
|
|
726
|
+
const inCode = makeCodeClassifier(code);
|
|
727
|
+
pattern.lastIndex = 0;
|
|
728
|
+
let m;
|
|
729
|
+
while ((m = pattern.exec(code)) !== null) {
|
|
730
|
+
if (inCode(m.index)) return m.index;
|
|
731
|
+
if (pattern.lastIndex <= m.index) pattern.lastIndex = m.index + 1;
|
|
732
|
+
}
|
|
733
|
+
return -1;
|
|
734
|
+
}
|
|
735
|
+
var REGEX_PRECEDING_KEYWORDS;
|
|
736
|
+
var init_source_scan = __esm({
|
|
737
|
+
"src/build/route-types/source-scan.ts"() {
|
|
738
|
+
"use strict";
|
|
739
|
+
REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
|
|
740
|
+
"return",
|
|
741
|
+
"typeof",
|
|
742
|
+
"instanceof",
|
|
743
|
+
"in",
|
|
744
|
+
"of",
|
|
745
|
+
"new",
|
|
746
|
+
"delete",
|
|
747
|
+
"void",
|
|
748
|
+
"do",
|
|
749
|
+
"else",
|
|
750
|
+
"yield",
|
|
751
|
+
"await",
|
|
752
|
+
"case",
|
|
753
|
+
"throw"
|
|
754
|
+
]);
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
|
|
576
758
|
// src/build/route-types/router-processing.ts
|
|
577
|
-
import {
|
|
578
|
-
|
|
759
|
+
import {
|
|
760
|
+
readFileSync as readFileSync3,
|
|
761
|
+
writeFileSync as writeFileSync2,
|
|
762
|
+
existsSync as existsSync3,
|
|
763
|
+
unlinkSync,
|
|
764
|
+
readdirSync as readdirSync2
|
|
765
|
+
} from "node:fs";
|
|
766
|
+
import {
|
|
767
|
+
join as join2,
|
|
768
|
+
dirname as dirname2,
|
|
769
|
+
resolve as resolve2,
|
|
770
|
+
sep,
|
|
771
|
+
basename as pathBasename
|
|
772
|
+
} from "node:path";
|
|
579
773
|
import ts5 from "typescript";
|
|
580
774
|
function countPublicRouteEntries(source) {
|
|
581
775
|
const matches = source.matchAll(/^\s+(?:"([^"]+)"|([a-zA-Z_$][^:]*)):\s*["{]/gm) ?? [];
|
|
@@ -588,7 +782,78 @@ function countPublicRouteEntries(source) {
|
|
|
588
782
|
}
|
|
589
783
|
return count;
|
|
590
784
|
}
|
|
591
|
-
function
|
|
785
|
+
function isRoutableSourceFile(name) {
|
|
786
|
+
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
787
|
+
}
|
|
788
|
+
function findRouterFilesRecursive(dir, filter, results) {
|
|
789
|
+
let entries;
|
|
790
|
+
try {
|
|
791
|
+
entries = readdirSync2(dir, { withFileTypes: true });
|
|
792
|
+
} catch (err) {
|
|
793
|
+
console.warn(
|
|
794
|
+
`[rango] Failed to scan directory ${dir}: ${err.message}`
|
|
795
|
+
);
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
const childDirs = [];
|
|
799
|
+
const routerFilesInDir = [];
|
|
800
|
+
for (const entry of entries) {
|
|
801
|
+
const fullPath = join2(dir, entry.name);
|
|
802
|
+
if (entry.isDirectory()) {
|
|
803
|
+
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "coverage" || entry.name === "__tests__" || entry.name === "__mocks__" || entry.name.startsWith("."))
|
|
804
|
+
continue;
|
|
805
|
+
childDirs.push(fullPath);
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
if (!isRoutableSourceFile(entry.name)) continue;
|
|
809
|
+
if (filter && !filter(fullPath)) continue;
|
|
810
|
+
try {
|
|
811
|
+
const source = readFileSync3(fullPath, "utf-8");
|
|
812
|
+
if (ROUTER_CALL_PATTERN.test(source) && firstCodeMatchIndex(source, ROUTER_CALL_PATTERN_G) >= 0) {
|
|
813
|
+
routerFilesInDir.push(fullPath);
|
|
814
|
+
}
|
|
815
|
+
} catch {
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
if (routerFilesInDir.length > 0) {
|
|
820
|
+
results.push(...routerFilesInDir);
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
for (const childDir of childDirs) {
|
|
824
|
+
findRouterFilesRecursive(childDir, filter, results);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
function findNestedRouterConflict(routerFiles) {
|
|
828
|
+
const routerDirs = [
|
|
829
|
+
...new Set(routerFiles.map((filePath) => dirname2(resolve2(filePath))))
|
|
830
|
+
].sort((a, b) => a.length - b.length);
|
|
831
|
+
for (let i = 0; i < routerDirs.length; i++) {
|
|
832
|
+
const ancestorDir = routerDirs[i];
|
|
833
|
+
const prefix = ancestorDir.endsWith(sep) ? ancestorDir : `${ancestorDir}${sep}`;
|
|
834
|
+
for (let j = i + 1; j < routerDirs.length; j++) {
|
|
835
|
+
const nestedDir = routerDirs[j];
|
|
836
|
+
if (!nestedDir.startsWith(prefix)) continue;
|
|
837
|
+
const ancestorFile = routerFiles.find(
|
|
838
|
+
(filePath) => dirname2(resolve2(filePath)) === ancestorDir
|
|
839
|
+
);
|
|
840
|
+
const nestedFile = routerFiles.find(
|
|
841
|
+
(filePath) => dirname2(resolve2(filePath)) === nestedDir
|
|
842
|
+
);
|
|
843
|
+
if (ancestorFile && nestedFile) {
|
|
844
|
+
return { ancestor: ancestorFile, nested: nestedFile };
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
function formatNestedRouterConflictError(conflict, prefix = "[rango]") {
|
|
851
|
+
return `${prefix} Nested router roots are not supported.
|
|
852
|
+
Router root: ${conflict.ancestor}
|
|
853
|
+
Nested router: ${conflict.nested}
|
|
854
|
+
Move the nested router into a sibling directory or configure it as a separate app root.`;
|
|
855
|
+
}
|
|
856
|
+
function extractUrlsFromRouter(code) {
|
|
592
857
|
const sourceFile = ts5.createSourceFile(
|
|
593
858
|
"router.tsx",
|
|
594
859
|
code,
|
|
@@ -602,24 +867,70 @@ function extractUrlsVariableFromRouter(code) {
|
|
|
602
867
|
const callee = node.expression;
|
|
603
868
|
return ts5.isIdentifier(callee) && callee.text === "createRouter";
|
|
604
869
|
}
|
|
870
|
+
function isInlineBuilder(node) {
|
|
871
|
+
return ts5.isArrowFunction(node) || ts5.isFunctionExpression(node);
|
|
872
|
+
}
|
|
873
|
+
function isRoutesOnCreateRouter(node) {
|
|
874
|
+
if (!ts5.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "routes")
|
|
875
|
+
return false;
|
|
876
|
+
let inner = node.expression.expression;
|
|
877
|
+
while (ts5.isCallExpression(inner) && ts5.isPropertyAccessExpression(inner.expression)) {
|
|
878
|
+
inner = inner.expression.expression;
|
|
879
|
+
}
|
|
880
|
+
return isCreateRouterCall(inner);
|
|
881
|
+
}
|
|
605
882
|
function visit(node) {
|
|
606
883
|
if (result) return;
|
|
607
|
-
if (ts5.isCallExpression(node) &&
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
result = node.arguments[0].text;
|
|
614
|
-
return;
|
|
884
|
+
if (ts5.isCallExpression(node) && node.arguments.length >= 1 && isRoutesOnCreateRouter(node)) {
|
|
885
|
+
const arg = node.arguments[0];
|
|
886
|
+
if (ts5.isIdentifier(arg)) {
|
|
887
|
+
result = { kind: "variable", name: arg.text };
|
|
888
|
+
} else if (isInlineBuilder(arg)) {
|
|
889
|
+
result = { kind: "inline", block: arg.getText(sourceFile) };
|
|
615
890
|
}
|
|
891
|
+
return;
|
|
616
892
|
}
|
|
617
893
|
if (isCreateRouterCall(node)) {
|
|
618
894
|
const callExpr = node;
|
|
619
|
-
for (const
|
|
895
|
+
for (const callArg of callExpr.arguments) {
|
|
896
|
+
if (ts5.isObjectLiteralExpression(callArg)) {
|
|
897
|
+
for (const prop of callArg.properties) {
|
|
898
|
+
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "urls") {
|
|
899
|
+
if (ts5.isIdentifier(prop.initializer)) {
|
|
900
|
+
result = { kind: "variable", name: prop.initializer.text };
|
|
901
|
+
} else if (isInlineBuilder(prop.initializer)) {
|
|
902
|
+
result = {
|
|
903
|
+
kind: "inline",
|
|
904
|
+
block: prop.initializer.getText(sourceFile)
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
ts5.forEachChild(node, visit);
|
|
914
|
+
}
|
|
915
|
+
visit(sourceFile);
|
|
916
|
+
return result;
|
|
917
|
+
}
|
|
918
|
+
function extractBasenameFromRouter(code) {
|
|
919
|
+
const sourceFile = ts5.createSourceFile(
|
|
920
|
+
"router.tsx",
|
|
921
|
+
code,
|
|
922
|
+
ts5.ScriptTarget.Latest,
|
|
923
|
+
true,
|
|
924
|
+
ts5.ScriptKind.TSX
|
|
925
|
+
);
|
|
926
|
+
let result;
|
|
927
|
+
function visit(node) {
|
|
928
|
+
if (result !== void 0) return;
|
|
929
|
+
if (ts5.isCallExpression(node) && ts5.isIdentifier(node.expression) && node.expression.text === "createRouter") {
|
|
930
|
+
for (const arg of node.arguments) {
|
|
620
931
|
if (ts5.isObjectLiteralExpression(arg)) {
|
|
621
932
|
for (const prop of arg.properties) {
|
|
622
|
-
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "
|
|
933
|
+
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "basename" && ts5.isStringLiteral(prop.initializer)) {
|
|
623
934
|
result = prop.initializer.text;
|
|
624
935
|
return;
|
|
625
936
|
}
|
|
@@ -632,6 +943,38 @@ function extractUrlsVariableFromRouter(code) {
|
|
|
632
943
|
visit(sourceFile);
|
|
633
944
|
return result;
|
|
634
945
|
}
|
|
946
|
+
function applyBasenameToRoutes(result, basename) {
|
|
947
|
+
const prefixed = {};
|
|
948
|
+
for (const [name, pattern] of Object.entries(result.routes)) {
|
|
949
|
+
if (pattern === "/") {
|
|
950
|
+
prefixed[name] = basename;
|
|
951
|
+
} else if (basename.endsWith("/") && pattern.startsWith("/")) {
|
|
952
|
+
prefixed[name] = basename + pattern.slice(1);
|
|
953
|
+
} else {
|
|
954
|
+
prefixed[name] = basename + pattern;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
return { routes: prefixed, searchSchemas: result.searchSchemas };
|
|
958
|
+
}
|
|
959
|
+
function genFileTsPath(sourceFile) {
|
|
960
|
+
const base = pathBasename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
961
|
+
return join2(dirname2(sourceFile), `${base}.named-routes.gen.ts`);
|
|
962
|
+
}
|
|
963
|
+
function resolveSearchSchemas(publicRouteNames, runtimeSchemas, sourceFile) {
|
|
964
|
+
if (runtimeSchemas && Object.keys(runtimeSchemas).length > 0) {
|
|
965
|
+
return runtimeSchemas;
|
|
966
|
+
}
|
|
967
|
+
const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
|
|
968
|
+
if (Object.keys(staticParsed.searchSchemas).length === 0) {
|
|
969
|
+
return runtimeSchemas;
|
|
970
|
+
}
|
|
971
|
+
const filtered = {};
|
|
972
|
+
for (const name of publicRouteNames) {
|
|
973
|
+
const schema = staticParsed.searchSchemas[name];
|
|
974
|
+
if (schema) filtered[name] = schema;
|
|
975
|
+
}
|
|
976
|
+
return Object.keys(filtered).length > 0 ? filtered : runtimeSchemas;
|
|
977
|
+
}
|
|
635
978
|
function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
636
979
|
let routerSource;
|
|
637
980
|
try {
|
|
@@ -639,19 +982,40 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
|
|
|
639
982
|
} catch {
|
|
640
983
|
return { routes: {}, searchSchemas: {} };
|
|
641
984
|
}
|
|
642
|
-
const
|
|
643
|
-
if (!
|
|
985
|
+
const extraction = extractUrlsFromRouter(routerSource);
|
|
986
|
+
if (!extraction) {
|
|
644
987
|
return { routes: {}, searchSchemas: {} };
|
|
645
988
|
}
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
989
|
+
const rawBasename = extractBasenameFromRouter(routerSource);
|
|
990
|
+
const basename = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
|
|
991
|
+
let result;
|
|
992
|
+
if (extraction.kind === "inline") {
|
|
993
|
+
result = buildCombinedRouteMapWithSearch(
|
|
994
|
+
routerFilePath,
|
|
995
|
+
void 0,
|
|
996
|
+
void 0,
|
|
997
|
+
void 0,
|
|
998
|
+
extraction.block
|
|
999
|
+
);
|
|
1000
|
+
} else {
|
|
1001
|
+
const imported = resolveImportedVariable(routerSource, extraction.name);
|
|
1002
|
+
if (imported) {
|
|
1003
|
+
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
1004
|
+
if (!targetFile) {
|
|
1005
|
+
return { routes: {}, searchSchemas: {} };
|
|
1006
|
+
}
|
|
1007
|
+
result = buildCombinedRouteMapWithSearch(
|
|
1008
|
+
targetFile,
|
|
1009
|
+
imported.exportedName
|
|
1010
|
+
);
|
|
1011
|
+
} else {
|
|
1012
|
+
result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
|
|
651
1013
|
}
|
|
652
|
-
return buildCombinedRouteMapWithSearch(targetFile, imported.exportedName);
|
|
653
1014
|
}
|
|
654
|
-
|
|
1015
|
+
if (basename) {
|
|
1016
|
+
result = applyBasenameToRoutes(result, basename);
|
|
1017
|
+
}
|
|
1018
|
+
return result;
|
|
655
1019
|
}
|
|
656
1020
|
function detectUnresolvableIncludes(routerFilePath) {
|
|
657
1021
|
const realPath = resolve2(routerFilePath);
|
|
@@ -661,9 +1025,20 @@ function detectUnresolvableIncludes(routerFilePath) {
|
|
|
661
1025
|
} catch {
|
|
662
1026
|
return [];
|
|
663
1027
|
}
|
|
664
|
-
const
|
|
665
|
-
if (!
|
|
666
|
-
const
|
|
1028
|
+
const extraction = extractUrlsFromRouter(source);
|
|
1029
|
+
if (!extraction) return [];
|
|
1030
|
+
const diagnostics = [];
|
|
1031
|
+
if (extraction.kind === "inline") {
|
|
1032
|
+
buildCombinedRouteMapWithSearch(
|
|
1033
|
+
realPath,
|
|
1034
|
+
void 0,
|
|
1035
|
+
/* @__PURE__ */ new Set(),
|
|
1036
|
+
diagnostics,
|
|
1037
|
+
extraction.block
|
|
1038
|
+
);
|
|
1039
|
+
return diagnostics;
|
|
1040
|
+
}
|
|
1041
|
+
const imported = resolveImportedVariable(source, extraction.name);
|
|
667
1042
|
let targetFile;
|
|
668
1043
|
let exportedName;
|
|
669
1044
|
if (imported) {
|
|
@@ -683,9 +1058,8 @@ function detectUnresolvableIncludes(routerFilePath) {
|
|
|
683
1058
|
exportedName = imported.exportedName;
|
|
684
1059
|
} else {
|
|
685
1060
|
targetFile = realPath;
|
|
686
|
-
exportedName =
|
|
1061
|
+
exportedName = extraction.name;
|
|
687
1062
|
}
|
|
688
|
-
const diagnostics = [];
|
|
689
1063
|
buildCombinedRouteMapWithSearch(
|
|
690
1064
|
targetFile,
|
|
691
1065
|
exportedName,
|
|
@@ -711,19 +1085,8 @@ function detectUnresolvableIncludesForUrlsFile(filePath) {
|
|
|
711
1085
|
return diagnostics;
|
|
712
1086
|
}
|
|
713
1087
|
function findRouterFiles(root, filter) {
|
|
714
|
-
const files = findTsFiles(root, filter);
|
|
715
1088
|
const result = [];
|
|
716
|
-
|
|
717
|
-
if (filePath.includes(".gen.")) continue;
|
|
718
|
-
try {
|
|
719
|
-
const source = readFileSync3(filePath, "utf-8");
|
|
720
|
-
if (/\bcreateRouter\s*[<(]/.test(source)) {
|
|
721
|
-
result.push(filePath);
|
|
722
|
-
}
|
|
723
|
-
} catch {
|
|
724
|
-
continue;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
1089
|
+
findRouterFilesRecursive(root, filter, result);
|
|
727
1090
|
return result;
|
|
728
1091
|
}
|
|
729
1092
|
function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
@@ -732,46 +1095,34 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
732
1095
|
if (existsSync3(oldCombinedPath)) {
|
|
733
1096
|
unlinkSync(oldCombinedPath);
|
|
734
1097
|
console.log(
|
|
735
|
-
`[
|
|
1098
|
+
`[rango] Removed stale combined route types: ${oldCombinedPath}`
|
|
736
1099
|
);
|
|
737
1100
|
}
|
|
738
1101
|
} catch {
|
|
739
1102
|
}
|
|
740
1103
|
const routerFilePaths = knownRouterFiles ?? findRouterFiles(root);
|
|
741
1104
|
if (routerFilePaths.length === 0) return;
|
|
1105
|
+
const nestedRouterConflict = findNestedRouterConflict(routerFilePaths);
|
|
1106
|
+
if (nestedRouterConflict) {
|
|
1107
|
+
throw new Error(formatNestedRouterConflictError(nestedRouterConflict));
|
|
1108
|
+
}
|
|
742
1109
|
for (const routerFilePath of routerFilePaths) {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
routerSource
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
const imported = resolveImportedVariable(routerSource, urlsVarName);
|
|
753
|
-
if (imported) {
|
|
754
|
-
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
755
|
-
if (!targetFile) continue;
|
|
756
|
-
result = buildCombinedRouteMapWithSearch(
|
|
757
|
-
targetFile,
|
|
758
|
-
imported.exportedName
|
|
759
|
-
);
|
|
760
|
-
} else {
|
|
761
|
-
result = buildCombinedRouteMapWithSearch(routerFilePath, urlsVarName);
|
|
1110
|
+
const result = buildCombinedRouteMapForRouterFile(routerFilePath);
|
|
1111
|
+
if (Object.keys(result.routes).length === 0 && Object.keys(result.searchSchemas).length === 0) {
|
|
1112
|
+
let routerSource;
|
|
1113
|
+
try {
|
|
1114
|
+
routerSource = readFileSync3(routerFilePath, "utf-8");
|
|
1115
|
+
} catch {
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1118
|
+
if (!extractUrlsFromRouter(routerSource)) continue;
|
|
762
1119
|
}
|
|
763
|
-
const
|
|
764
|
-
/\.(tsx?|jsx?)$/,
|
|
765
|
-
""
|
|
766
|
-
);
|
|
767
|
-
const outPath = join2(
|
|
768
|
-
dirname2(routerFilePath),
|
|
769
|
-
`${routerBasename}.named-routes.gen.ts`
|
|
770
|
-
);
|
|
1120
|
+
const outPath = genFileTsPath(routerFilePath);
|
|
771
1121
|
const existing = existsSync3(outPath) ? readFileSync3(outPath, "utf-8") : null;
|
|
772
1122
|
if (Object.keys(result.routes).length === 0) {
|
|
773
1123
|
if (!existing) {
|
|
774
1124
|
const emptySource = generateRouteTypesSource({});
|
|
1125
|
+
opts?.onWrite?.(outPath, emptySource);
|
|
775
1126
|
writeFileSync2(outPath, emptySource);
|
|
776
1127
|
}
|
|
777
1128
|
continue;
|
|
@@ -791,21 +1142,25 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
|
|
|
791
1142
|
continue;
|
|
792
1143
|
}
|
|
793
1144
|
}
|
|
1145
|
+
opts?.onWrite?.(outPath, source);
|
|
794
1146
|
writeFileSync2(outPath, source);
|
|
795
1147
|
console.log(
|
|
796
|
-
`[
|
|
1148
|
+
`[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
|
|
797
1149
|
);
|
|
798
1150
|
}
|
|
799
1151
|
}
|
|
800
1152
|
}
|
|
1153
|
+
var ROUTER_CALL_PATTERN, ROUTER_CALL_PATTERN_G;
|
|
801
1154
|
var init_router_processing = __esm({
|
|
802
1155
|
"src/build/route-types/router-processing.ts"() {
|
|
803
1156
|
"use strict";
|
|
804
1157
|
init_codegen();
|
|
805
|
-
|
|
1158
|
+
init_source_scan();
|
|
806
1159
|
init_include_resolution();
|
|
807
1160
|
init_per_module_writer();
|
|
808
1161
|
init_route_name();
|
|
1162
|
+
ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
1163
|
+
ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
|
|
809
1164
|
}
|
|
810
1165
|
});
|
|
811
1166
|
|
|
@@ -843,7 +1198,7 @@ import {
|
|
|
843
1198
|
import { createElement, StrictMode } from "react";
|
|
844
1199
|
import { hydrateRoot } from "react-dom/client";
|
|
845
1200
|
import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
|
|
846
|
-
import { initBrowserApp,
|
|
1201
|
+
import { initBrowserApp, Rango } from "@rangojs/router/browser";
|
|
847
1202
|
|
|
848
1203
|
async function initializeApp() {
|
|
849
1204
|
const deps = {
|
|
@@ -854,11 +1209,16 @@ async function initializeApp() {
|
|
|
854
1209
|
createTemporaryReferenceSet,
|
|
855
1210
|
};
|
|
856
1211
|
|
|
857
|
-
|
|
1212
|
+
// initBrowserApp resolves the initial payload and returns the browser app
|
|
1213
|
+
// context, including strictMode (default true) from createRouter. StrictMode
|
|
1214
|
+
// is the default; createRouter({ strictMode: false }) ships the opt-out in the
|
|
1215
|
+
// payload metadata. StrictMode emits no DOM, so toggling never changes markup.
|
|
1216
|
+
const { strictMode } = await initBrowserApp({ rscStream, deps });
|
|
858
1217
|
|
|
1218
|
+
const app = createElement(Rango);
|
|
859
1219
|
hydrateRoot(
|
|
860
1220
|
document,
|
|
861
|
-
createElement(StrictMode, null,
|
|
1221
|
+
strictMode === false ? app : createElement(StrictMode, null, app)
|
|
862
1222
|
);
|
|
863
1223
|
}
|
|
864
1224
|
|
|
@@ -887,12 +1247,37 @@ export const renderHTML = createSSRHandler({
|
|
|
887
1247
|
}
|
|
888
1248
|
});
|
|
889
1249
|
|
|
1250
|
+
// src/vite/utils/directive-prologue.ts
|
|
1251
|
+
import { parseAst } from "vite";
|
|
1252
|
+
function hasUseClientDirective(source) {
|
|
1253
|
+
let program;
|
|
1254
|
+
try {
|
|
1255
|
+
program = parseAst(source, { lang: "tsx" });
|
|
1256
|
+
} catch {
|
|
1257
|
+
return false;
|
|
1258
|
+
}
|
|
1259
|
+
for (const node of program.body ?? []) {
|
|
1260
|
+
if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
|
|
1261
|
+
if (node.expression.value === "use client") return true;
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
break;
|
|
1265
|
+
}
|
|
1266
|
+
return false;
|
|
1267
|
+
}
|
|
1268
|
+
var init_directive_prologue = __esm({
|
|
1269
|
+
"src/vite/utils/directive-prologue.ts"() {
|
|
1270
|
+
"use strict";
|
|
1271
|
+
}
|
|
1272
|
+
});
|
|
1273
|
+
|
|
890
1274
|
// src/vite/plugins/version-plugin.ts
|
|
891
1275
|
var version_plugin_exports = {};
|
|
892
1276
|
__export(version_plugin_exports, {
|
|
893
|
-
createVersionPlugin: () => createVersionPlugin
|
|
1277
|
+
createVersionPlugin: () => createVersionPlugin,
|
|
1278
|
+
isViteDepCachePath: () => isViteDepCachePath
|
|
894
1279
|
});
|
|
895
|
-
import { parseAst } from "vite";
|
|
1280
|
+
import { parseAst as parseAst2 } from "vite";
|
|
896
1281
|
function isCodeModule(id) {
|
|
897
1282
|
return /\.(tsx?|jsx?)($|\?)/.test(id);
|
|
898
1283
|
}
|
|
@@ -900,23 +1285,13 @@ function normalizeModuleId(id) {
|
|
|
900
1285
|
return id.split("?", 1)[0];
|
|
901
1286
|
}
|
|
902
1287
|
function getClientModuleSignature(source) {
|
|
1288
|
+
if (!hasUseClientDirective(source)) return void 0;
|
|
903
1289
|
let program;
|
|
904
1290
|
try {
|
|
905
|
-
program =
|
|
1291
|
+
program = parseAst2(source, { lang: "tsx" });
|
|
906
1292
|
} catch {
|
|
907
1293
|
return void 0;
|
|
908
1294
|
}
|
|
909
|
-
let isUseClient = false;
|
|
910
|
-
for (const node of program.body ?? []) {
|
|
911
|
-
if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
|
|
912
|
-
if (node.expression.value === "use client") {
|
|
913
|
-
isUseClient = true;
|
|
914
|
-
}
|
|
915
|
-
continue;
|
|
916
|
-
}
|
|
917
|
-
break;
|
|
918
|
-
}
|
|
919
|
-
if (!isUseClient) return void 0;
|
|
920
1295
|
const exports = /* @__PURE__ */ new Set();
|
|
921
1296
|
let hasDefault = false;
|
|
922
1297
|
let hasExportAll = false;
|
|
@@ -985,10 +1360,12 @@ function createVersionPlugin() {
|
|
|
985
1360
|
let currentVersion = buildVersion;
|
|
986
1361
|
let isDev = false;
|
|
987
1362
|
let server = null;
|
|
1363
|
+
let resolvedCacheDir;
|
|
988
1364
|
const clientModuleSignatures = /* @__PURE__ */ new Map();
|
|
1365
|
+
let versionCounter = 0;
|
|
989
1366
|
const bumpVersion = (reason) => {
|
|
990
|
-
currentVersion = Date.now().toString(16);
|
|
991
|
-
console.log(`[
|
|
1367
|
+
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
1368
|
+
console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
|
|
992
1369
|
const rscEnv = server?.environments?.rsc;
|
|
993
1370
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
994
1371
|
"\0" + VIRTUAL_IDS.version
|
|
@@ -1002,6 +1379,7 @@ function createVersionPlugin() {
|
|
|
1002
1379
|
enforce: "pre",
|
|
1003
1380
|
configResolved(config) {
|
|
1004
1381
|
isDev = config.command === "serve";
|
|
1382
|
+
resolvedCacheDir = config.cacheDir ? String(config.cacheDir).replace(/\\/g, "/") : void 0;
|
|
1005
1383
|
},
|
|
1006
1384
|
configureServer(devServer) {
|
|
1007
1385
|
server = devServer;
|
|
@@ -1038,11 +1416,14 @@ function createVersionPlugin() {
|
|
|
1038
1416
|
}
|
|
1039
1417
|
return null;
|
|
1040
1418
|
},
|
|
1041
|
-
// Track RSC module changes and update version
|
|
1042
1419
|
async hotUpdate(ctx) {
|
|
1043
1420
|
if (!isDev) return;
|
|
1044
1421
|
const isRscModule = this.environment?.name === "rsc";
|
|
1045
1422
|
if (!isRscModule) return;
|
|
1423
|
+
if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
|
|
1424
|
+
if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1046
1427
|
if (isCodeModule(ctx.file)) {
|
|
1047
1428
|
const filePath = normalizeModuleId(ctx.file);
|
|
1048
1429
|
const previousSignature = clientModuleSignatures.get(filePath);
|
|
@@ -1069,10 +1450,22 @@ function createVersionPlugin() {
|
|
|
1069
1450
|
}
|
|
1070
1451
|
};
|
|
1071
1452
|
}
|
|
1453
|
+
function isViteDepCachePath(filePath, cacheDir) {
|
|
1454
|
+
if (!filePath) return false;
|
|
1455
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
1456
|
+
if (cacheDir) {
|
|
1457
|
+
const normalizedCacheDir = cacheDir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
1458
|
+
if (normalized === normalizedCacheDir || normalized.startsWith(normalizedCacheDir + "/")) {
|
|
1459
|
+
return true;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
return /\/node_modules\/\.vite[^/]*\//.test(normalized) || normalized.includes("/.vite-isolated/");
|
|
1463
|
+
}
|
|
1072
1464
|
var init_version_plugin = __esm({
|
|
1073
1465
|
"src/vite/plugins/version-plugin.ts"() {
|
|
1074
1466
|
"use strict";
|
|
1075
1467
|
init_virtual_entries();
|
|
1468
|
+
init_directive_prologue();
|
|
1076
1469
|
}
|
|
1077
1470
|
});
|
|
1078
1471
|
|
|
@@ -1114,7 +1507,7 @@ var runtime_discovery_exports = {};
|
|
|
1114
1507
|
__export(runtime_discovery_exports, {
|
|
1115
1508
|
discoverAndWriteRouteTypes: () => discoverAndWriteRouteTypes
|
|
1116
1509
|
});
|
|
1117
|
-
import {
|
|
1510
|
+
import { resolve as resolve3 } from "node:path";
|
|
1118
1511
|
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
1119
1512
|
async function discoverAndWriteRouteTypes(opts) {
|
|
1120
1513
|
let createViteServer;
|
|
@@ -1224,22 +1617,12 @@ This means createRouter() stack trace parsing matched an internal frame.
|
|
|
1224
1617
|
Set an explicit \`id\` on createRouter() or check the call site.`
|
|
1225
1618
|
);
|
|
1226
1619
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
if (schema) filtered[name] = schema;
|
|
1234
|
-
}
|
|
1235
|
-
if (Object.keys(filtered).length > 0) {
|
|
1236
|
-
routeSearchSchemas = filtered;
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
const routerDir = dirname3(sourceFile);
|
|
1241
|
-
const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
1242
|
-
const outPath = join3(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
1620
|
+
routeSearchSchemas = resolveSearchSchemas(
|
|
1621
|
+
Object.keys(routeManifest),
|
|
1622
|
+
routeSearchSchemas,
|
|
1623
|
+
sourceFile
|
|
1624
|
+
);
|
|
1625
|
+
const outPath = genFileTsPath(sourceFile);
|
|
1243
1626
|
const source = generateRouteTypesSource(
|
|
1244
1627
|
routeManifest,
|
|
1245
1628
|
routeSearchSchemas && Object.keys(routeSearchSchemas).length > 0 ? routeSearchSchemas : void 0
|
|
@@ -1276,7 +1659,7 @@ var init_runtime_discovery = __esm({
|
|
|
1276
1659
|
|
|
1277
1660
|
// src/bin/rango.ts
|
|
1278
1661
|
init_generate_route_types();
|
|
1279
|
-
import { resolve as resolve4, dirname as
|
|
1662
|
+
import { resolve as resolve4, dirname as dirname3 } from "node:path";
|
|
1280
1663
|
import { readFileSync as readFileSync5, statSync, existsSync as existsSync5 } from "node:fs";
|
|
1281
1664
|
var [command, ...rawArgs] = process.argv.slice(2);
|
|
1282
1665
|
if (command === "generate") {
|
|
@@ -1347,12 +1730,12 @@ Examples:
|
|
|
1347
1730
|
);
|
|
1348
1731
|
}
|
|
1349
1732
|
function findProjectRoot(fromPath) {
|
|
1350
|
-
let dir =
|
|
1351
|
-
while (dir !==
|
|
1733
|
+
let dir = dirname3(resolve4(fromPath));
|
|
1734
|
+
while (dir !== dirname3(dir)) {
|
|
1352
1735
|
if (existsSync5(resolve4(dir, "package.json")) || existsSync5(resolve4(dir, "vite.config.ts")) || existsSync5(resolve4(dir, "vite.config.js"))) {
|
|
1353
1736
|
return dir;
|
|
1354
1737
|
}
|
|
1355
|
-
dir =
|
|
1738
|
+
dir = dirname3(dir);
|
|
1356
1739
|
}
|
|
1357
1740
|
return process.cwd();
|
|
1358
1741
|
}
|
|
@@ -1428,6 +1811,15 @@ function runStaticGeneration(args, mode) {
|
|
|
1428
1811
|
formatDiagnostics(uniqueDiagnostics);
|
|
1429
1812
|
console.warn("");
|
|
1430
1813
|
}
|
|
1814
|
+
const nestedRouterConflict = findNestedRouterConflict(routerFiles);
|
|
1815
|
+
if (nestedRouterConflict) {
|
|
1816
|
+
console.error(
|
|
1817
|
+
`
|
|
1818
|
+
${formatNestedRouterConflictError(nestedRouterConflict, "[rango]")}
|
|
1819
|
+
`
|
|
1820
|
+
);
|
|
1821
|
+
process.exit(1);
|
|
1822
|
+
}
|
|
1431
1823
|
for (const urlsFile of urlsFiles) {
|
|
1432
1824
|
writePerModuleRouteTypesForFile(urlsFile);
|
|
1433
1825
|
}
|
|
@@ -1471,6 +1863,15 @@ async function runRuntimeDiscovery(args, configFile) {
|
|
|
1471
1863
|
console.error("[rango] No router files found in the provided paths");
|
|
1472
1864
|
process.exit(1);
|
|
1473
1865
|
}
|
|
1866
|
+
const nestedRouterConflict = findNestedRouterConflict(routerEntries);
|
|
1867
|
+
if (nestedRouterConflict) {
|
|
1868
|
+
console.error(
|
|
1869
|
+
`
|
|
1870
|
+
${formatNestedRouterConflictError(nestedRouterConflict, "[rango]")}
|
|
1871
|
+
`
|
|
1872
|
+
);
|
|
1873
|
+
process.exit(1);
|
|
1874
|
+
}
|
|
1474
1875
|
let discoverAndWriteRouteTypes2;
|
|
1475
1876
|
try {
|
|
1476
1877
|
const mod = await Promise.resolve().then(() => (init_runtime_discovery(), runtime_discovery_exports));
|