@rangojs/router 0.0.0-experimental.1b930379 → 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 +12 -0
- package/README.md +245 -49
- package/dist/bin/rango.js +441 -134
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3453 -1240
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +76 -21
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +247 -23
- package/skills/caching/SKILL.md +318 -15
- 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 +250 -30
- package/skills/host-router/SKILL.md +83 -23
- 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 +279 -53
- 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 +153 -109
- package/skills/rango/SKILL.md +251 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +101 -5
- package/skills/router-setup/SKILL.md +116 -8
- 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 +129 -0
- 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 +332 -29
- 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 +1 -66
- 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/navigation-bridge.ts +111 -31
- package/src/browser/navigation-client.ts +201 -67
- 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 +230 -35
- package/src/browser/prefetch/fetch.ts +338 -39
- 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 +111 -16
- 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 +218 -76
- 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 +222 -61
- package/src/browser/types.ts +91 -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 +5 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +165 -36
- 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 +272 -96
- 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 +44 -21
- package/src/client.tsx +119 -290
- 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 +37 -8
- 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 -2
- 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 +93 -12
- package/src/index.ts +133 -15
- 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 +37 -41
- 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 -0
- 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 +83 -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 +120 -204
- 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 -40
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +270 -172
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +132 -90
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +195 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +8 -28
- package/src/router/router-interfaces.ts +115 -35
- package/src/router/router-options.ts +172 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +264 -77
- package/src/router/segment-resolution/helpers.ts +115 -30
- package/src/router/segment-resolution/loader-cache.ts +63 -37
- package/src/router/segment-resolution/revalidation.ts +474 -385
- 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 +163 -59
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +163 -55
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +658 -511
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -5
- 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 +77 -11
- 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 +105 -72
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +263 -112
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/types.ts +32 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- 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 +309 -61
- 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 +398 -172
- 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 +0 -7
- 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 +233 -81
- 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 +6 -50
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -14
- 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 +36 -38
- package/src/vite/discovery/discover-routers.ts +130 -85
- 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 +214 -132
- 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 +57 -6
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +6 -0
- 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 +16 -11
- 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 +89 -27
- 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 +238 -295
- package/src/vite/router-discovery.ts +940 -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 +81 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- 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/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import ts from "typescript";
|
|
16
16
|
import { generateRouteTypesSource } from "./codegen.js";
|
|
17
17
|
import type { ScanFilter } from "./scan-filter.js";
|
|
18
|
+
import { firstCodeMatchIndex } from "./source-scan.js";
|
|
18
19
|
import {
|
|
19
20
|
resolveImportedVariable,
|
|
20
21
|
resolveImportPath,
|
|
@@ -38,6 +39,8 @@ function countPublicRouteEntries(source: string): number {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
const ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
42
|
+
// Global variant for the code-region scan (firstCodeMatchIndex sets lastIndex).
|
|
43
|
+
const ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
|
|
41
44
|
|
|
42
45
|
function isRoutableSourceFile(name: string): boolean {
|
|
43
46
|
return (
|
|
@@ -45,7 +48,9 @@ function isRoutableSourceFile(name: string): boolean {
|
|
|
45
48
|
name.endsWith(".tsx") ||
|
|
46
49
|
name.endsWith(".js") ||
|
|
47
50
|
name.endsWith(".jsx")) &&
|
|
48
|
-
!name.includes(".gen.")
|
|
51
|
+
!name.includes(".gen.") &&
|
|
52
|
+
!name.includes(".test.") &&
|
|
53
|
+
!name.includes(".spec.")
|
|
49
54
|
);
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -59,7 +64,7 @@ function findRouterFilesRecursive(
|
|
|
59
64
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
60
65
|
} catch (err) {
|
|
61
66
|
console.warn(
|
|
62
|
-
`[
|
|
67
|
+
`[rango] Failed to scan directory ${dir}: ${(err as Error).message}`,
|
|
63
68
|
);
|
|
64
69
|
return;
|
|
65
70
|
}
|
|
@@ -70,7 +75,15 @@ function findRouterFilesRecursive(
|
|
|
70
75
|
for (const entry of entries) {
|
|
71
76
|
const fullPath = join(dir, entry.name);
|
|
72
77
|
if (entry.isDirectory()) {
|
|
73
|
-
if (
|
|
78
|
+
if (
|
|
79
|
+
entry.name === "node_modules" ||
|
|
80
|
+
entry.name === "dist" ||
|
|
81
|
+
entry.name === "coverage" ||
|
|
82
|
+
entry.name === "__tests__" ||
|
|
83
|
+
entry.name === "__mocks__" ||
|
|
84
|
+
entry.name.startsWith(".")
|
|
85
|
+
)
|
|
86
|
+
continue;
|
|
74
87
|
childDirs.push(fullPath);
|
|
75
88
|
continue;
|
|
76
89
|
}
|
|
@@ -80,7 +93,17 @@ function findRouterFilesRecursive(
|
|
|
80
93
|
|
|
81
94
|
try {
|
|
82
95
|
const source = readFileSync(fullPath, "utf-8");
|
|
83
|
-
|
|
96
|
+
// Fast path: most files contain no `createRouter(` at all, so the cheap
|
|
97
|
+
// raw regex short-circuits before the code-region scan. Only a file that
|
|
98
|
+
// mentions the token (real call OR a comment/string mention) is rescanned
|
|
99
|
+
// over code regions — allocation-free, never building a stripped copy —
|
|
100
|
+
// so a mention inside a comment or string is not mistaken for a real
|
|
101
|
+
// router file (which previously triggered a spurious "Multiple routers
|
|
102
|
+
// found" error).
|
|
103
|
+
if (
|
|
104
|
+
ROUTER_CALL_PATTERN.test(source) &&
|
|
105
|
+
firstCodeMatchIndex(source, ROUTER_CALL_PATTERN_G) >= 0
|
|
106
|
+
) {
|
|
84
107
|
routerFilesInDir.push(fullPath);
|
|
85
108
|
}
|
|
86
109
|
} catch {
|
|
@@ -132,7 +155,7 @@ export function findNestedRouterConflict(
|
|
|
132
155
|
|
|
133
156
|
export function formatNestedRouterConflictError(
|
|
134
157
|
conflict: { ancestor: string; nested: string },
|
|
135
|
-
prefix = "[
|
|
158
|
+
prefix = "[rango]",
|
|
136
159
|
): string {
|
|
137
160
|
return (
|
|
138
161
|
`${prefix} Nested router roots are not supported.\n` +
|
|
@@ -147,13 +170,26 @@ export function formatNestedRouterConflictError(
|
|
|
147
170
|
// ---------------------------------------------------------------------------
|
|
148
171
|
|
|
149
172
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
173
|
+
* Result of extracting URL patterns from a router file.
|
|
174
|
+
* - "variable": a named variable reference (e.g., `.routes(patterns)` or `urls: patterns`)
|
|
175
|
+
* - "inline": an inline builder function (e.g., `.routes(({ path }) => [...])` or `urls: ({ path }) => [...]`)
|
|
176
|
+
*/
|
|
177
|
+
export type UrlsExtractionResult =
|
|
178
|
+
| { kind: "variable"; name: string }
|
|
179
|
+
| { kind: "inline"; block: string };
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Extract the url patterns from a router file using AST.
|
|
183
|
+
* Detects four patterns:
|
|
152
184
|
* 1. createRouter(...).routes(variableName)
|
|
153
185
|
* 2. createRouter({ urls: variableName, ... })
|
|
154
|
-
*
|
|
186
|
+
* 3. createRouter(...).routes(({ path, ... }) => [...])
|
|
187
|
+
* 4. createRouter({ urls: ({ path, ... }) => [...], ... })
|
|
188
|
+
* Returns either a variable name or an inline code block.
|
|
155
189
|
*/
|
|
156
|
-
export function
|
|
190
|
+
export function extractUrlsFromRouter(
|
|
191
|
+
code: string,
|
|
192
|
+
): UrlsExtractionResult | null {
|
|
157
193
|
const sourceFile = ts.createSourceFile(
|
|
158
194
|
"router.tsx",
|
|
159
195
|
code,
|
|
@@ -161,7 +197,7 @@ export function extractUrlsVariableFromRouter(code: string): string | null {
|
|
|
161
197
|
true,
|
|
162
198
|
ts.ScriptKind.TSX,
|
|
163
199
|
);
|
|
164
|
-
let result:
|
|
200
|
+
let result: UrlsExtractionResult | null = null;
|
|
165
201
|
|
|
166
202
|
function isCreateRouterCall(node: ts.Node): boolean {
|
|
167
203
|
if (!ts.isCallExpression(node)) return false;
|
|
@@ -169,44 +205,108 @@ export function extractUrlsVariableFromRouter(code: string): string | null {
|
|
|
169
205
|
return ts.isIdentifier(callee) && callee.text === "createRouter";
|
|
170
206
|
}
|
|
171
207
|
|
|
208
|
+
/** Check if a node is an arrow/function expression (inline builder). */
|
|
209
|
+
function isInlineBuilder(node: ts.Node): boolean {
|
|
210
|
+
return ts.isArrowFunction(node) || ts.isFunctionExpression(node);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Check if a .routes() call chains from createRouter(). */
|
|
214
|
+
function isRoutesOnCreateRouter(node: ts.CallExpression): boolean {
|
|
215
|
+
if (
|
|
216
|
+
!ts.isPropertyAccessExpression(node.expression) ||
|
|
217
|
+
node.expression.name.text !== "routes"
|
|
218
|
+
)
|
|
219
|
+
return false;
|
|
220
|
+
let inner: ts.Expression = node.expression.expression;
|
|
221
|
+
while (
|
|
222
|
+
ts.isCallExpression(inner) &&
|
|
223
|
+
ts.isPropertyAccessExpression(inner.expression)
|
|
224
|
+
) {
|
|
225
|
+
inner = inner.expression.expression;
|
|
226
|
+
}
|
|
227
|
+
return isCreateRouterCall(inner);
|
|
228
|
+
}
|
|
229
|
+
|
|
172
230
|
function visit(node: ts.Node) {
|
|
173
231
|
if (result) return;
|
|
174
232
|
|
|
175
|
-
// Pattern 1: createRouter(...).routes(variableName)
|
|
176
|
-
// The AST shape is CallExpression(.routes) -> PropertyAccessExpression -> CallExpression(createRouter)
|
|
233
|
+
// Pattern 1 & 3: createRouter(...).routes(variableName | builder)
|
|
177
234
|
if (
|
|
178
235
|
ts.isCallExpression(node) &&
|
|
179
|
-
ts.isPropertyAccessExpression(node.expression) &&
|
|
180
|
-
node.expression.name.text === "routes" &&
|
|
181
236
|
node.arguments.length >= 1 &&
|
|
182
|
-
|
|
237
|
+
isRoutesOnCreateRouter(node)
|
|
183
238
|
) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
ts.isPropertyAccessExpression(inner.expression)
|
|
190
|
-
) {
|
|
191
|
-
inner = inner.expression.expression;
|
|
192
|
-
}
|
|
193
|
-
if (isCreateRouterCall(inner)) {
|
|
194
|
-
result = (node.arguments[0] as ts.Identifier).text;
|
|
195
|
-
return;
|
|
239
|
+
const arg = node.arguments[0];
|
|
240
|
+
if (ts.isIdentifier(arg)) {
|
|
241
|
+
result = { kind: "variable", name: arg.text };
|
|
242
|
+
} else if (isInlineBuilder(arg)) {
|
|
243
|
+
result = { kind: "inline", block: arg.getText(sourceFile) };
|
|
196
244
|
}
|
|
245
|
+
return;
|
|
197
246
|
}
|
|
198
247
|
|
|
199
|
-
// Pattern 2: createRouter({ urls: variableName, ... })
|
|
248
|
+
// Pattern 2 & 4: createRouter({ urls: variableName | builder, ... })
|
|
200
249
|
if (isCreateRouterCall(node)) {
|
|
201
250
|
const callExpr = node as ts.CallExpression;
|
|
202
|
-
for (const
|
|
251
|
+
for (const callArg of callExpr.arguments) {
|
|
252
|
+
if (ts.isObjectLiteralExpression(callArg)) {
|
|
253
|
+
for (const prop of callArg.properties) {
|
|
254
|
+
if (
|
|
255
|
+
ts.isPropertyAssignment(prop) &&
|
|
256
|
+
ts.isIdentifier(prop.name) &&
|
|
257
|
+
prop.name.text === "urls"
|
|
258
|
+
) {
|
|
259
|
+
if (ts.isIdentifier(prop.initializer)) {
|
|
260
|
+
result = { kind: "variable", name: prop.initializer.text };
|
|
261
|
+
} else if (isInlineBuilder(prop.initializer)) {
|
|
262
|
+
result = {
|
|
263
|
+
kind: "inline",
|
|
264
|
+
block: prop.initializer.getText(sourceFile),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
ts.forEachChild(node, visit);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
visit(sourceFile);
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Extract the `basename` string literal from createRouter({ basename: "..." }).
|
|
283
|
+
* Returns the basename value or undefined if not present.
|
|
284
|
+
*/
|
|
285
|
+
export function extractBasenameFromRouter(code: string): string | undefined {
|
|
286
|
+
const sourceFile = ts.createSourceFile(
|
|
287
|
+
"router.tsx",
|
|
288
|
+
code,
|
|
289
|
+
ts.ScriptTarget.Latest,
|
|
290
|
+
true,
|
|
291
|
+
ts.ScriptKind.TSX,
|
|
292
|
+
);
|
|
293
|
+
let result: string | undefined;
|
|
294
|
+
|
|
295
|
+
function visit(node: ts.Node) {
|
|
296
|
+
if (result !== undefined) return;
|
|
297
|
+
if (
|
|
298
|
+
ts.isCallExpression(node) &&
|
|
299
|
+
ts.isIdentifier(node.expression) &&
|
|
300
|
+
node.expression.text === "createRouter"
|
|
301
|
+
) {
|
|
302
|
+
for (const arg of node.arguments) {
|
|
203
303
|
if (ts.isObjectLiteralExpression(arg)) {
|
|
204
304
|
for (const prop of arg.properties) {
|
|
205
305
|
if (
|
|
206
306
|
ts.isPropertyAssignment(prop) &&
|
|
207
307
|
ts.isIdentifier(prop.name) &&
|
|
208
|
-
prop.name.text === "
|
|
209
|
-
ts.
|
|
308
|
+
prop.name.text === "basename" &&
|
|
309
|
+
ts.isStringLiteral(prop.initializer)
|
|
210
310
|
) {
|
|
211
311
|
result = prop.initializer.text;
|
|
212
312
|
return;
|
|
@@ -215,7 +315,6 @@ export function extractUrlsVariableFromRouter(code: string): string | null {
|
|
|
215
315
|
}
|
|
216
316
|
}
|
|
217
317
|
}
|
|
218
|
-
|
|
219
318
|
ts.forEachChild(node, visit);
|
|
220
319
|
}
|
|
221
320
|
|
|
@@ -223,9 +322,64 @@ export function extractUrlsVariableFromRouter(code: string): string | null {
|
|
|
223
322
|
return result;
|
|
224
323
|
}
|
|
225
324
|
|
|
325
|
+
/** Apply a basename prefix to all route patterns in a result set. */
|
|
326
|
+
function applyBasenameToRoutes(
|
|
327
|
+
result: {
|
|
328
|
+
routes: Record<string, string>;
|
|
329
|
+
searchSchemas: Record<string, Record<string, string>>;
|
|
330
|
+
},
|
|
331
|
+
basename: string,
|
|
332
|
+
): {
|
|
333
|
+
routes: Record<string, string>;
|
|
334
|
+
searchSchemas: Record<string, Record<string, string>>;
|
|
335
|
+
} {
|
|
336
|
+
const prefixed: Record<string, string> = {};
|
|
337
|
+
for (const [name, pattern] of Object.entries(result.routes)) {
|
|
338
|
+
if (pattern === "/") {
|
|
339
|
+
prefixed[name] = basename;
|
|
340
|
+
} else if (basename.endsWith("/") && pattern.startsWith("/")) {
|
|
341
|
+
prefixed[name] = basename + pattern.slice(1);
|
|
342
|
+
} else {
|
|
343
|
+
prefixed[name] = basename + pattern;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return { routes: prefixed, searchSchemas: result.searchSchemas };
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Filesystem path of the generated route-types file for a router source file.
|
|
350
|
+
// Native separators — matches the self-gen-tracking Map key the watcher compares.
|
|
351
|
+
export function genFileTsPath(sourceFile: string): string {
|
|
352
|
+
const base = pathBasename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
|
|
353
|
+
return join(dirname(sourceFile), `${base}.named-routes.gen.ts`);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Search schemas for the gen file: prefer the runtime manifest's; when it omits
|
|
357
|
+
// them (some module-runner flows) fall back to static parsing filtered to the
|
|
358
|
+
// public route-name set. Returns the runtime value unchanged otherwise.
|
|
359
|
+
export function resolveSearchSchemas(
|
|
360
|
+
publicRouteNames: string[],
|
|
361
|
+
runtimeSchemas: Record<string, Record<string, string>> | undefined,
|
|
362
|
+
sourceFile: string,
|
|
363
|
+
): Record<string, Record<string, string>> | undefined {
|
|
364
|
+
if (runtimeSchemas && Object.keys(runtimeSchemas).length > 0) {
|
|
365
|
+
return runtimeSchemas;
|
|
366
|
+
}
|
|
367
|
+
const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
|
|
368
|
+
if (Object.keys(staticParsed.searchSchemas).length === 0) {
|
|
369
|
+
return runtimeSchemas;
|
|
370
|
+
}
|
|
371
|
+
const filtered: Record<string, Record<string, string>> = {};
|
|
372
|
+
for (const name of publicRouteNames) {
|
|
373
|
+
const schema = staticParsed.searchSchemas[name];
|
|
374
|
+
if (schema) filtered[name] = schema;
|
|
375
|
+
}
|
|
376
|
+
return Object.keys(filtered).length > 0 ? filtered : runtimeSchemas;
|
|
377
|
+
}
|
|
378
|
+
|
|
226
379
|
/**
|
|
227
380
|
* Resolve routes and search schemas from a router source file by following the
|
|
228
|
-
* variable passed to `.routes(...)` or `urls: ...` in createRouter options
|
|
381
|
+
* variable passed to `.routes(...)` or `urls: ...` in createRouter options,
|
|
382
|
+
* or by parsing an inline builder function directly.
|
|
229
383
|
*/
|
|
230
384
|
export function buildCombinedRouteMapForRouterFile(routerFilePath: string): {
|
|
231
385
|
routes: Record<string, string>;
|
|
@@ -238,21 +392,54 @@ export function buildCombinedRouteMapForRouterFile(routerFilePath: string): {
|
|
|
238
392
|
return { routes: {}, searchSchemas: {} };
|
|
239
393
|
}
|
|
240
394
|
|
|
241
|
-
const
|
|
242
|
-
if (!
|
|
395
|
+
const extraction = extractUrlsFromRouter(routerSource);
|
|
396
|
+
if (!extraction) {
|
|
243
397
|
return { routes: {}, searchSchemas: {} };
|
|
244
398
|
}
|
|
245
399
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
400
|
+
// Detect basename from createRouter({ basename: "..." })
|
|
401
|
+
const rawBasename = extractBasenameFromRouter(routerSource);
|
|
402
|
+
const basename = rawBasename
|
|
403
|
+
? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "")
|
|
404
|
+
: undefined;
|
|
405
|
+
|
|
406
|
+
let result: {
|
|
407
|
+
routes: Record<string, string>;
|
|
408
|
+
searchSchemas: Record<string, Record<string, string>>;
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
// Inline builder: extract routes directly from the function body
|
|
412
|
+
if (extraction.kind === "inline") {
|
|
413
|
+
result = buildCombinedRouteMapWithSearch(
|
|
414
|
+
routerFilePath,
|
|
415
|
+
undefined,
|
|
416
|
+
undefined,
|
|
417
|
+
undefined,
|
|
418
|
+
extraction.block,
|
|
419
|
+
);
|
|
420
|
+
} else {
|
|
421
|
+
// Variable reference: follow imports or same-file declaration
|
|
422
|
+
const imported = resolveImportedVariable(routerSource, extraction.name);
|
|
423
|
+
if (imported) {
|
|
424
|
+
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
425
|
+
if (!targetFile) {
|
|
426
|
+
return { routes: {}, searchSchemas: {} };
|
|
427
|
+
}
|
|
428
|
+
result = buildCombinedRouteMapWithSearch(
|
|
429
|
+
targetFile,
|
|
430
|
+
imported.exportedName,
|
|
431
|
+
);
|
|
432
|
+
} else {
|
|
433
|
+
result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
|
|
251
434
|
}
|
|
252
|
-
return buildCombinedRouteMapWithSearch(targetFile, imported.exportedName);
|
|
253
435
|
}
|
|
254
436
|
|
|
255
|
-
|
|
437
|
+
// Apply basename prefix to all extracted route patterns
|
|
438
|
+
if (basename) {
|
|
439
|
+
result = applyBasenameToRoutes(result, basename);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return result;
|
|
256
443
|
}
|
|
257
444
|
|
|
258
445
|
// ---------------------------------------------------------------------------
|
|
@@ -275,12 +462,26 @@ export function detectUnresolvableIncludes(
|
|
|
275
462
|
return [];
|
|
276
463
|
}
|
|
277
464
|
|
|
278
|
-
// Extract the urls
|
|
279
|
-
const
|
|
280
|
-
if (!
|
|
465
|
+
// Extract the urls source from the router file
|
|
466
|
+
const extraction = extractUrlsFromRouter(source);
|
|
467
|
+
if (!extraction) return [];
|
|
281
468
|
|
|
282
|
-
|
|
283
|
-
|
|
469
|
+
const diagnostics: UnresolvableInclude[] = [];
|
|
470
|
+
|
|
471
|
+
if (extraction.kind === "inline") {
|
|
472
|
+
// Inline builder: parse directly
|
|
473
|
+
buildCombinedRouteMapWithSearch(
|
|
474
|
+
realPath,
|
|
475
|
+
undefined,
|
|
476
|
+
new Set(),
|
|
477
|
+
diagnostics,
|
|
478
|
+
extraction.block,
|
|
479
|
+
);
|
|
480
|
+
return diagnostics;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Variable reference: resolve where it comes from
|
|
484
|
+
const imported = resolveImportedVariable(source, extraction.name);
|
|
284
485
|
let targetFile: string;
|
|
285
486
|
let exportedName: string | undefined;
|
|
286
487
|
|
|
@@ -302,10 +503,9 @@ export function detectUnresolvableIncludes(
|
|
|
302
503
|
} else {
|
|
303
504
|
// Same-file urls() definition
|
|
304
505
|
targetFile = realPath;
|
|
305
|
-
exportedName =
|
|
506
|
+
exportedName = extraction.name;
|
|
306
507
|
}
|
|
307
508
|
|
|
308
|
-
const diagnostics: UnresolvableInclude[] = [];
|
|
309
509
|
buildCombinedRouteMapWithSearch(
|
|
310
510
|
targetFile,
|
|
311
511
|
exportedName,
|
|
@@ -365,7 +565,10 @@ export function findRouterFiles(root: string, filter?: ScanFilter): string[] {
|
|
|
365
565
|
export function writeCombinedRouteTypes(
|
|
366
566
|
root: string,
|
|
367
567
|
knownRouterFiles?: string[],
|
|
368
|
-
opts?: {
|
|
568
|
+
opts?: {
|
|
569
|
+
preserveIfLarger?: boolean;
|
|
570
|
+
onWrite?: (outPath: string, content: string) => void;
|
|
571
|
+
},
|
|
369
572
|
): void {
|
|
370
573
|
// Delete old combined named-routes.gen.ts if it exists (stale from older versions)
|
|
371
574
|
try {
|
|
@@ -373,7 +576,7 @@ export function writeCombinedRouteTypes(
|
|
|
373
576
|
if (existsSync(oldCombinedPath)) {
|
|
374
577
|
unlinkSync(oldCombinedPath);
|
|
375
578
|
console.log(
|
|
376
|
-
`[
|
|
579
|
+
`[rango] Removed stale combined route types: ${oldCombinedPath}`,
|
|
377
580
|
);
|
|
378
581
|
}
|
|
379
582
|
} catch {}
|
|
@@ -387,54 +590,31 @@ export function writeCombinedRouteTypes(
|
|
|
387
590
|
}
|
|
388
591
|
|
|
389
592
|
for (const routerFilePath of routerFilePaths) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
};
|
|
405
|
-
|
|
406
|
-
const imported = resolveImportedVariable(routerSource, urlsVarName);
|
|
407
|
-
if (imported) {
|
|
408
|
-
// Variable is imported from another module
|
|
409
|
-
const targetFile = resolveImportPath(imported.specifier, routerFilePath);
|
|
410
|
-
if (!targetFile) continue;
|
|
411
|
-
result = buildCombinedRouteMapWithSearch(
|
|
412
|
-
targetFile,
|
|
413
|
-
imported.exportedName,
|
|
414
|
-
);
|
|
415
|
-
} else {
|
|
416
|
-
// Variable is defined in the same file
|
|
417
|
-
result = buildCombinedRouteMapWithSearch(routerFilePath, urlsVarName);
|
|
593
|
+
const result = buildCombinedRouteMapForRouterFile(routerFilePath);
|
|
594
|
+
if (
|
|
595
|
+
Object.keys(result.routes).length === 0 &&
|
|
596
|
+
Object.keys(result.searchSchemas).length === 0
|
|
597
|
+
) {
|
|
598
|
+
// Check if the file even has a createRouter call — if not, skip entirely.
|
|
599
|
+
// If it does, fall through to write an empty placeholder below.
|
|
600
|
+
let routerSource: string;
|
|
601
|
+
try {
|
|
602
|
+
routerSource = readFileSync(routerFilePath, "utf-8");
|
|
603
|
+
} catch {
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
if (!extractUrlsFromRouter(routerSource)) continue;
|
|
418
607
|
}
|
|
419
608
|
|
|
420
|
-
const
|
|
421
|
-
/\.(tsx?|jsx?)$/,
|
|
422
|
-
"",
|
|
423
|
-
);
|
|
424
|
-
const outPath = join(
|
|
425
|
-
dirname(routerFilePath),
|
|
426
|
-
`${routerBasename}.named-routes.gen.ts`,
|
|
427
|
-
);
|
|
609
|
+
const outPath = genFileTsPath(routerFilePath);
|
|
428
610
|
const existing = existsSync(outPath)
|
|
429
611
|
? readFileSync(outPath, "utf-8")
|
|
430
612
|
: null;
|
|
431
613
|
|
|
432
|
-
// When the static parser can't extract routes (e.g. callback-style urls()),
|
|
433
|
-
// write an empty placeholder so the build-time transform's injected import
|
|
434
|
-
// resolves. Runtime discovery will overwrite this with the real routes.
|
|
435
614
|
if (Object.keys(result.routes).length === 0) {
|
|
436
615
|
if (!existing) {
|
|
437
616
|
const emptySource = generateRouteTypesSource({});
|
|
617
|
+
opts?.onWrite?.(outPath, emptySource);
|
|
438
618
|
writeFileSync(outPath, emptySource);
|
|
439
619
|
}
|
|
440
620
|
continue;
|
|
@@ -446,11 +626,6 @@ export function writeCombinedRouteTypes(
|
|
|
446
626
|
hasSearchSchemas ? result.searchSchemas : undefined,
|
|
447
627
|
);
|
|
448
628
|
if (existing !== source) {
|
|
449
|
-
// On initial dev startup, don't overwrite a file from runtime discovery
|
|
450
|
-
// (which has all dynamic routes) with a smaller set from the static
|
|
451
|
-
// parser. The static parser can't see routes generated by Array.from()
|
|
452
|
-
// or other dynamic code. During HMR (file watcher), always write so
|
|
453
|
-
// newly added routes appear immediately.
|
|
454
629
|
if (opts?.preserveIfLarger && existing) {
|
|
455
630
|
const existingCount = countPublicRouteEntries(existing);
|
|
456
631
|
const newCount = Object.keys(result.routes).filter(
|
|
@@ -460,9 +635,10 @@ export function writeCombinedRouteTypes(
|
|
|
460
635
|
continue;
|
|
461
636
|
}
|
|
462
637
|
}
|
|
638
|
+
opts?.onWrite?.(outPath, source);
|
|
463
639
|
writeFileSync(outPath, source);
|
|
464
640
|
console.log(
|
|
465
|
-
`[
|
|
641
|
+
`[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`,
|
|
466
642
|
);
|
|
467
643
|
}
|
|
468
644
|
}
|
|
@@ -54,14 +54,21 @@ export function findTsFiles(dir: string, filter?: ScanFilter): string[] {
|
|
|
54
54
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
55
55
|
} catch (err) {
|
|
56
56
|
console.warn(
|
|
57
|
-
`[
|
|
57
|
+
`[rango] Failed to scan directory ${dir}: ${(err as Error).message}`,
|
|
58
58
|
);
|
|
59
59
|
return results;
|
|
60
60
|
}
|
|
61
61
|
for (const entry of entries) {
|
|
62
62
|
const fullPath = join(dir, entry.name);
|
|
63
63
|
if (entry.isDirectory()) {
|
|
64
|
-
if (
|
|
64
|
+
if (
|
|
65
|
+
entry.name === "node_modules" ||
|
|
66
|
+
entry.name.startsWith(".") ||
|
|
67
|
+
entry.name === "dist" ||
|
|
68
|
+
entry.name === "build" ||
|
|
69
|
+
entry.name === "coverage"
|
|
70
|
+
)
|
|
71
|
+
continue;
|
|
65
72
|
results.push(...findTsFiles(fullPath, filter));
|
|
66
73
|
} else if (
|
|
67
74
|
(entry.name.endsWith(".ts") ||
|