vinext 0.0.30 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/build/prerender.d.ts +188 -0
- package/dist/build/prerender.js +675 -0
- package/dist/build/prerender.js.map +1 -0
- package/dist/build/report.d.ts +45 -46
- package/dist/build/report.js +247 -276
- package/dist/build/report.js.map +1 -1
- package/dist/build/run-prerender.d.ts +62 -0
- package/dist/build/run-prerender.js +183 -0
- package/dist/build/run-prerender.js.map +1 -0
- package/dist/build/server-manifest.d.ts +19 -0
- package/dist/build/server-manifest.js +29 -0
- package/dist/build/server-manifest.js.map +1 -0
- package/dist/build/static-export.d.ts +51 -66
- package/dist/build/static-export.js +51 -545
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.d.ts +26 -24
- package/dist/check.js +591 -571
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +1 -15
- package/dist/cli.js +430 -491
- package/dist/cli.js.map +1 -1
- package/dist/client/entry.d.ts +1 -2
- package/dist/client/entry.js +49 -62
- package/dist/client/entry.js.map +1 -1
- package/dist/client/validate-module-path.d.ts +4 -1
- package/dist/client/validate-module-path.js +23 -28
- package/dist/client/validate-module-path.js.map +1 -1
- package/dist/client/vinext-next-data.d.ts +15 -20
- package/dist/client/vinext-next-data.js +0 -1
- package/dist/cloudflare/index.d.ts +3 -8
- package/dist/cloudflare/index.js +3 -8
- package/dist/cloudflare/kv-cache-handler.d.ts +95 -105
- package/dist/cloudflare/kv-cache-handler.js +354 -380
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.d.ts +36 -34
- package/dist/cloudflare/tpr.js +460 -603
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +31 -40
- package/dist/config/config-matchers.js +727 -936
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/dotenv.d.ts +18 -11
- package/dist/config/dotenv.js +79 -84
- package/dist/config/dotenv.js.map +1 -1
- package/dist/config/next-config.d.ts +156 -146
- package/dist/config/next-config.js +374 -464
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts +87 -96
- package/dist/deploy.js +490 -628
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.d.ts +4 -1
- package/dist/entries/app-browser-entry.js +12 -8
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +33 -20
- package/dist/entries/app-rsc-entry.js +442 -211
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-ssr-entry.d.ts +9 -1
- package/dist/entries/app-ssr-entry.js +61 -28
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.d.ts +6 -2
- package/dist/entries/pages-client-entry.js +30 -33
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-entry-helpers.d.ts +5 -1
- package/dist/entries/pages-entry-helpers.js +17 -14
- package/dist/entries/pages-entry-helpers.js.map +1 -1
- package/dist/entries/pages-server-entry.d.ts +6 -2
- package/dist/entries/pages-server-entry.js +84 -113
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/index.d.ts +82 -62
- package/dist/index.js +2172 -3133
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +40 -37
- package/dist/init.js +201 -258
- package/dist/init.js.map +1 -1
- package/dist/plugins/async-hooks-stub.d.ts +7 -3
- package/dist/plugins/async-hooks-stub.js +39 -42
- package/dist/plugins/async-hooks-stub.js.map +1 -1
- package/dist/plugins/client-reference-dedup.d.ts +7 -3
- package/dist/plugins/client-reference-dedup.js +63 -88
- package/dist/plugins/client-reference-dedup.js.map +1 -1
- package/dist/routing/app-router.d.ts +100 -96
- package/dist/routing/app-router.js +560 -670
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +18 -15
- package/dist/routing/file-matcher.js +65 -65
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.d.ts +23 -24
- package/dist/routing/pages-router.js +147 -172
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-trie.d.ts +23 -20
- package/dist/routing/route-trie.js +131 -151
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.d.ts +5 -2
- package/dist/routing/route-validation.js +98 -130
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.d.ts +10 -7
- package/dist/routing/utils.js +75 -111
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.d.ts +8 -13
- package/dist/server/api-handler.js +161 -193
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-router-entry.d.ts +6 -16
- package/dist/server/app-router-entry.js +26 -54
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/dev-module-runner.d.ts +11 -64
- package/dist/server/dev-module-runner.js +89 -101
- package/dist/server/dev-module-runner.js.map +1 -1
- package/dist/server/dev-origin-check.d.ts +12 -10
- package/dist/server/dev-origin-check.js +98 -108
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.d.ts +17 -14
- package/dist/server/dev-server.js +542 -869
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/html.d.ts +4 -1
- package/dist/server/html.js +25 -26
- package/dist/server/html.js.map +1 -1
- package/dist/server/image-optimization.d.ts +31 -28
- package/dist/server/image-optimization.js +181 -210
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/instrumentation.d.ts +25 -22
- package/dist/server/instrumentation.js +110 -122
- package/dist/server/instrumentation.js.map +1 -1
- package/dist/server/isr-cache.d.ts +16 -26
- package/dist/server/isr-cache.js +106 -128
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-routes.d.ts +85 -88
- package/dist/server/metadata-routes.js +270 -317
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-codegen.d.ts +7 -4
- package/dist/server/middleware-codegen.js +61 -61
- package/dist/server/middleware-codegen.js.map +1 -1
- package/dist/server/middleware-request-headers.d.ts +8 -6
- package/dist/server/middleware-request-headers.js +47 -65
- package/dist/server/middleware-request-headers.js.map +1 -1
- package/dist/server/middleware.d.ts +31 -47
- package/dist/server/middleware.js +273 -404
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/normalize-path.d.ts +4 -1
- package/dist/server/normalize-path.js +33 -47
- package/dist/server/normalize-path.js.map +1 -1
- package/dist/server/pages-i18n.d.ts +38 -30
- package/dist/server/pages-i18n.js +112 -139
- package/dist/server/pages-i18n.js.map +1 -1
- package/dist/server/prod-server.d.ts +19 -31
- package/dist/server/prod-server.js +714 -945
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-log.d.ts +18 -12
- package/dist/server/request-log.js +45 -52
- package/dist/server/request-log.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +9 -17
- package/dist/server/request-pipeline.js +133 -184
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/worker-utils.d.ts +4 -1
- package/dist/server/worker-utils.js +31 -37
- package/dist/server/worker-utils.js.map +1 -1
- package/dist/shims/amp.d.ts +5 -2
- package/dist/shims/amp.js +19 -15
- package/dist/shims/amp.js.map +1 -1
- package/dist/shims/app.d.ts +8 -10
- package/dist/shims/app.js +0 -1
- package/dist/shims/cache-runtime.d.ts +20 -45
- package/dist/shims/cache-runtime.js +271 -422
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +130 -121
- package/dist/shims/cache.js +339 -427
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/client-only.d.ts +1 -18
- package/dist/shims/client-only.js +0 -17
- package/dist/shims/compat-router.d.ts +4 -1
- package/dist/shims/compat-router.js +23 -19
- package/dist/shims/compat-router.js.map +1 -1
- package/dist/shims/config.d.ts +7 -5
- package/dist/shims/config.js +16 -23
- package/dist/shims/config.js.map +1 -1
- package/dist/shims/constants.d.ts +119 -118
- package/dist/shims/constants.js +159 -164
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/document.d.ts +20 -16
- package/dist/shims/document.js +41 -22
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/dynamic.d.ts +13 -22
- package/dist/shims/dynamic.js +122 -136
- package/dist/shims/dynamic.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +22 -15
- package/dist/shims/error-boundary.js +81 -79
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/error.d.ts +11 -12
- package/dist/shims/error.js +35 -39
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +16 -14
- package/dist/shims/fetch-cache.js +437 -645
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.d.ts +28 -26
- package/dist/shims/font-google-base.js +238 -325
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-google.d.ts +3 -3
- package/dist/shims/font-google.generated.d.ts +1928 -1924
- package/dist/shims/font-google.generated.js +1928 -2133
- package/dist/shims/font-google.generated.js.map +1 -1
- package/dist/shims/font-google.js +3 -3
- package/dist/shims/font-local.d.ts +28 -26
- package/dist/shims/font-local.js +204 -260
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/form.d.ts +13 -27
- package/dist/shims/form.js +128 -180
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/head-state.d.ts +8 -13
- package/dist/shims/head-state.js +25 -42
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/head.d.ts +16 -20
- package/dist/shims/head.js +172 -250
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +84 -78
- package/dist/shims/headers.js +447 -575
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-context.d.ts +16 -20
- package/dist/shims/i18n-context.js +35 -48
- package/dist/shims/i18n-context.js.map +1 -1
- package/dist/shims/i18n-state.d.ts +8 -14
- package/dist/shims/i18n-state.js +34 -42
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/image-config.d.ts +11 -8
- package/dist/shims/image-config.js +50 -83
- package/dist/shims/image-config.js.map +1 -1
- package/dist/shims/image.d.ts +37 -46
- package/dist/shims/image.js +283 -308
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/api-utils.d.ts +7 -4
- package/dist/shims/internal/api-utils.js +0 -6
- package/dist/shims/internal/app-router-context.d.ts +22 -17
- package/dist/shims/internal/app-router-context.js +17 -13
- package/dist/shims/internal/app-router-context.js.map +1 -1
- package/dist/shims/internal/cookies.d.ts +2 -9
- package/dist/shims/internal/cookies.js +2 -9
- package/dist/shims/internal/parse-cookie-header.d.ts +4 -1
- package/dist/shims/internal/parse-cookie-header.js +29 -29
- package/dist/shims/internal/parse-cookie-header.js.map +1 -1
- package/dist/shims/internal/router-context.d.ts +6 -1
- package/dist/shims/internal/router-context.js +11 -7
- package/dist/shims/internal/router-context.js.map +1 -1
- package/dist/shims/internal/utils.d.ts +40 -37
- package/dist/shims/internal/utils.js +24 -30
- package/dist/shims/internal/utils.js.map +1 -1
- package/dist/shims/internal/work-unit-async-storage.d.ts +6 -10
- package/dist/shims/internal/work-unit-async-storage.js +14 -11
- package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
- package/dist/shims/layout-segment-context.d.ts +11 -14
- package/dist/shims/layout-segment-context.js +24 -23
- package/dist/shims/layout-segment-context.js.map +1 -1
- package/dist/shims/legacy-image.d.ts +39 -46
- package/dist/shims/legacy-image.js +47 -42
- package/dist/shims/legacy-image.js.map +1 -1
- package/dist/shims/link.d.ts +32 -36
- package/dist/shims/link.js +255 -391
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +210 -202
- package/dist/shims/metadata.js +545 -546
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.d.ts +10 -18
- package/dist/shims/navigation-state.js +66 -74
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +59 -63
- package/dist/shims/navigation.js +505 -704
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/og.d.ts +2 -20
- package/dist/shims/og.js +2 -19
- package/dist/shims/readonly-url-search-params.d.ts +8 -5
- package/dist/shims/readonly-url-search-params.js +26 -22
- package/dist/shims/readonly-url-search-params.js.map +1 -1
- package/dist/shims/request-context.d.ts +8 -5
- package/dist/shims/request-context.js +50 -60
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +11 -11
- package/dist/shims/request-state-types.js +0 -1
- package/dist/shims/router-state.d.ts +13 -10
- package/dist/shims/router-state.js +34 -43
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts +81 -85
- package/dist/shims/router.js +506 -628
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script.d.ts +39 -48
- package/dist/shims/script.js +107 -160
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server-only.d.ts +1 -19
- package/dist/shims/server-only.js +0 -18
- package/dist/shims/server.d.ts +175 -164
- package/dist/shims/server.js +462 -478
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +20 -20
- package/dist/shims/unified-request-context.js +81 -99
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/url-safety.d.ts +4 -1
- package/dist/shims/url-safety.js +15 -11
- package/dist/shims/url-safety.js.map +1 -1
- package/dist/shims/url-utils.d.ts +8 -5
- package/dist/shims/url-utils.js +62 -93
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/shims/web-vitals.d.ts +10 -8
- package/dist/shims/web-vitals.js +9 -15
- package/dist/shims/web-vitals.js.map +1 -1
- package/dist/utils/base-path.d.ts +5 -2
- package/dist/utils/base-path.js +21 -19
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/domain-locale.d.ts +17 -9
- package/dist/utils/domain-locale.js +36 -56
- package/dist/utils/domain-locale.js.map +1 -1
- package/dist/utils/hash.d.ts +4 -1
- package/dist/utils/hash.js +19 -17
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/manifest-paths.d.ts +6 -3
- package/dist/utils/manifest-paths.js +15 -16
- package/dist/utils/manifest-paths.js.map +1 -1
- package/dist/utils/project.d.ts +13 -11
- package/dist/utils/project.js +169 -216
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/query.d.ts +8 -6
- package/dist/utils/query.js +57 -67
- package/dist/utils/query.js.map +1 -1
- package/package.json +10 -9
- package/dist/build/report.d.ts.map +0 -1
- package/dist/build/static-export.d.ts.map +0 -1
- package/dist/check.d.ts.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/client/entry.d.ts.map +0 -1
- package/dist/client/validate-module-path.d.ts.map +0 -1
- package/dist/client/vinext-next-data.d.ts.map +0 -1
- package/dist/client/vinext-next-data.js.map +0 -1
- package/dist/cloudflare/index.d.ts.map +0 -1
- package/dist/cloudflare/index.js.map +0 -1
- package/dist/cloudflare/kv-cache-handler.d.ts.map +0 -1
- package/dist/cloudflare/tpr.d.ts.map +0 -1
- package/dist/config/config-matchers.d.ts.map +0 -1
- package/dist/config/dotenv.d.ts.map +0 -1
- package/dist/config/next-config.d.ts.map +0 -1
- package/dist/deploy.d.ts.map +0 -1
- package/dist/entries/app-browser-entry.d.ts.map +0 -1
- package/dist/entries/app-rsc-entry.d.ts.map +0 -1
- package/dist/entries/app-ssr-entry.d.ts.map +0 -1
- package/dist/entries/pages-client-entry.d.ts.map +0 -1
- package/dist/entries/pages-entry-helpers.d.ts.map +0 -1
- package/dist/entries/pages-server-entry.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/init.d.ts.map +0 -1
- package/dist/plugins/async-hooks-stub.d.ts.map +0 -1
- package/dist/plugins/client-reference-dedup.d.ts.map +0 -1
- package/dist/routing/app-router.d.ts.map +0 -1
- package/dist/routing/file-matcher.d.ts.map +0 -1
- package/dist/routing/pages-router.d.ts.map +0 -1
- package/dist/routing/route-trie.d.ts.map +0 -1
- package/dist/routing/route-validation.d.ts.map +0 -1
- package/dist/routing/utils.d.ts.map +0 -1
- package/dist/server/api-handler.d.ts.map +0 -1
- package/dist/server/app-router-entry.d.ts.map +0 -1
- package/dist/server/dev-module-runner.d.ts.map +0 -1
- package/dist/server/dev-origin-check.d.ts.map +0 -1
- package/dist/server/dev-server.d.ts.map +0 -1
- package/dist/server/html.d.ts.map +0 -1
- package/dist/server/image-optimization.d.ts.map +0 -1
- package/dist/server/instrumentation.d.ts.map +0 -1
- package/dist/server/isr-cache.d.ts.map +0 -1
- package/dist/server/metadata-routes.d.ts.map +0 -1
- package/dist/server/middleware-codegen.d.ts.map +0 -1
- package/dist/server/middleware-request-headers.d.ts.map +0 -1
- package/dist/server/middleware.d.ts.map +0 -1
- package/dist/server/normalize-path.d.ts.map +0 -1
- package/dist/server/pages-i18n.d.ts.map +0 -1
- package/dist/server/prod-server.d.ts.map +0 -1
- package/dist/server/request-log.d.ts.map +0 -1
- package/dist/server/request-pipeline.d.ts.map +0 -1
- package/dist/server/worker-utils.d.ts.map +0 -1
- package/dist/shims/amp.d.ts.map +0 -1
- package/dist/shims/app.d.ts.map +0 -1
- package/dist/shims/app.js.map +0 -1
- package/dist/shims/cache-runtime.d.ts.map +0 -1
- package/dist/shims/cache.d.ts.map +0 -1
- package/dist/shims/client-only.d.ts.map +0 -1
- package/dist/shims/client-only.js.map +0 -1
- package/dist/shims/compat-router.d.ts.map +0 -1
- package/dist/shims/config.d.ts.map +0 -1
- package/dist/shims/constants.d.ts.map +0 -1
- package/dist/shims/document.d.ts.map +0 -1
- package/dist/shims/dynamic.d.ts.map +0 -1
- package/dist/shims/error-boundary.d.ts.map +0 -1
- package/dist/shims/error.d.ts.map +0 -1
- package/dist/shims/fetch-cache.d.ts.map +0 -1
- package/dist/shims/font-google-base.d.ts.map +0 -1
- package/dist/shims/font-google.d.ts.map +0 -1
- package/dist/shims/font-google.generated.d.ts.map +0 -1
- package/dist/shims/font-google.js.map +0 -1
- package/dist/shims/font-local.d.ts.map +0 -1
- package/dist/shims/form.d.ts.map +0 -1
- package/dist/shims/head-state.d.ts.map +0 -1
- package/dist/shims/head.d.ts.map +0 -1
- package/dist/shims/headers.d.ts.map +0 -1
- package/dist/shims/i18n-context.d.ts.map +0 -1
- package/dist/shims/i18n-state.d.ts.map +0 -1
- package/dist/shims/image-config.d.ts.map +0 -1
- package/dist/shims/image.d.ts.map +0 -1
- package/dist/shims/internal/api-utils.d.ts.map +0 -1
- package/dist/shims/internal/api-utils.js.map +0 -1
- package/dist/shims/internal/app-router-context.d.ts.map +0 -1
- package/dist/shims/internal/cookies.d.ts.map +0 -1
- package/dist/shims/internal/cookies.js.map +0 -1
- package/dist/shims/internal/parse-cookie-header.d.ts.map +0 -1
- package/dist/shims/internal/router-context.d.ts.map +0 -1
- package/dist/shims/internal/utils.d.ts.map +0 -1
- package/dist/shims/internal/work-unit-async-storage.d.ts.map +0 -1
- package/dist/shims/layout-segment-context.d.ts.map +0 -1
- package/dist/shims/legacy-image.d.ts.map +0 -1
- package/dist/shims/link.d.ts.map +0 -1
- package/dist/shims/metadata.d.ts.map +0 -1
- package/dist/shims/navigation-state.d.ts.map +0 -1
- package/dist/shims/navigation.d.ts.map +0 -1
- package/dist/shims/og.d.ts.map +0 -1
- package/dist/shims/og.js.map +0 -1
- package/dist/shims/readonly-url-search-params.d.ts.map +0 -1
- package/dist/shims/request-context.d.ts.map +0 -1
- package/dist/shims/request-state-types.d.ts.map +0 -1
- package/dist/shims/request-state-types.js.map +0 -1
- package/dist/shims/router-state.d.ts.map +0 -1
- package/dist/shims/router.d.ts.map +0 -1
- package/dist/shims/script.d.ts.map +0 -1
- package/dist/shims/server-only.d.ts.map +0 -1
- package/dist/shims/server-only.js.map +0 -1
- package/dist/shims/server.d.ts.map +0 -1
- package/dist/shims/unified-request-context.d.ts.map +0 -1
- package/dist/shims/url-safety.d.ts.map +0 -1
- package/dist/shims/url-utils.d.ts.map +0 -1
- package/dist/shims/web-vitals.d.ts.map +0 -1
- package/dist/utils/base-path.d.ts.map +0 -1
- package/dist/utils/domain-locale.d.ts.map +0 -1
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/manifest-paths.d.ts.map +0 -1
- package/dist/utils/project.d.ts.map +0 -1
- package/dist/utils/query.d.ts.map +0 -1
|
@@ -1,748 +1,638 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* App Router file-system routing.
|
|
3
|
-
*
|
|
4
|
-
* Scans the app/ directory following Next.js App Router conventions:
|
|
5
|
-
* - app/page.tsx -> /
|
|
6
|
-
* - app/about/page.tsx -> /about
|
|
7
|
-
* - app/blog/[slug]/page.tsx -> /blog/:slug
|
|
8
|
-
* - app/[...catchAll]/page.tsx -> /:catchAll+
|
|
9
|
-
* - app/route.ts -> / (API route)
|
|
10
|
-
* - app/(group)/page.tsx -> / (route groups are transparent)
|
|
11
|
-
* - Layouts: app/layout.tsx wraps all children
|
|
12
|
-
* - Loading: app/loading.tsx -> Suspense fallback
|
|
13
|
-
* - Error: app/error.tsx -> ErrorBoundary
|
|
14
|
-
* - Not Found: app/not-found.tsx
|
|
15
|
-
*/
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import fs from "node:fs";
|
|
18
1
|
import { compareRoutes, decodeRouteSegment, normalizePathnameForRouteMatch } from "./utils.js";
|
|
19
|
-
import { createValidFileMatcher, scanWithExtensions
|
|
2
|
+
import { createValidFileMatcher, scanWithExtensions } from "./file-matcher.js";
|
|
20
3
|
import { validateRoutePatterns } from "./route-validation.js";
|
|
21
4
|
import { buildRouteTrie, trieMatch } from "./route-trie.js";
|
|
22
|
-
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
//#region src/routing/app-router.ts
|
|
8
|
+
/**
|
|
9
|
+
* App Router file-system routing.
|
|
10
|
+
*
|
|
11
|
+
* Scans the app/ directory following Next.js App Router conventions:
|
|
12
|
+
* - app/page.tsx -> /
|
|
13
|
+
* - app/about/page.tsx -> /about
|
|
14
|
+
* - app/blog/[slug]/page.tsx -> /blog/:slug
|
|
15
|
+
* - app/[...catchAll]/page.tsx -> /:catchAll+
|
|
16
|
+
* - app/route.ts -> / (API route)
|
|
17
|
+
* - app/(group)/page.tsx -> / (route groups are transparent)
|
|
18
|
+
* - Layouts: app/layout.tsx wraps all children
|
|
19
|
+
* - Loading: app/loading.tsx -> Suspense fallback
|
|
20
|
+
* - Error: app/error.tsx -> ErrorBoundary
|
|
21
|
+
* - Not Found: app/not-found.tsx
|
|
22
|
+
*/
|
|
23
23
|
let cachedRoutes = null;
|
|
24
24
|
let cachedAppDir = null;
|
|
25
25
|
let cachedPageExtensionsKey = null;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
function invalidateAppRouteCache() {
|
|
27
|
+
cachedRoutes = null;
|
|
28
|
+
cachedAppDir = null;
|
|
29
|
+
cachedPageExtensionsKey = null;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
// Discover sub-routes created by nested pages within parallel slots.
|
|
59
|
-
// In Next.js, pages nested inside @slot directories create additional URL routes.
|
|
60
|
-
// For example, @audience/demographics/page.tsx at app/parallel-routes/ creates
|
|
61
|
-
// a route at /parallel-routes/demographics.
|
|
62
|
-
const slotSubRoutes = discoverSlotSubRoutes(routes, appDir, matcher);
|
|
63
|
-
routes.push(...slotSubRoutes);
|
|
64
|
-
validateRoutePatterns(routes.map((route) => route.pattern));
|
|
65
|
-
validateRoutePatterns(routes.flatMap((route) => route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.map((intercept) => intercept.targetPattern))));
|
|
66
|
-
// Sort: static routes first, then dynamic, then catch-all
|
|
67
|
-
routes.sort(compareRoutes);
|
|
68
|
-
cachedRoutes = routes;
|
|
69
|
-
cachedAppDir = appDir;
|
|
70
|
-
cachedPageExtensionsKey = pageExtensionsKey;
|
|
71
|
-
return routes;
|
|
32
|
+
* Scan the app/ directory and return a list of routes.
|
|
33
|
+
*/
|
|
34
|
+
async function appRouter(appDir, pageExtensions, matcher) {
|
|
35
|
+
matcher ??= createValidFileMatcher(pageExtensions);
|
|
36
|
+
const pageExtensionsKey = JSON.stringify(matcher.extensions);
|
|
37
|
+
if (cachedRoutes && cachedAppDir === appDir && cachedPageExtensionsKey === pageExtensionsKey) return cachedRoutes;
|
|
38
|
+
const routes = [];
|
|
39
|
+
const excludeDir = (name) => name.startsWith("@") || name.startsWith("_");
|
|
40
|
+
for await (const file of scanWithExtensions("**/page", appDir, matcher.extensions, excludeDir)) {
|
|
41
|
+
const route = fileToAppRoute(file, appDir, "page", matcher);
|
|
42
|
+
if (route) routes.push(route);
|
|
43
|
+
}
|
|
44
|
+
for await (const file of scanWithExtensions("**/route", appDir, matcher.extensions, excludeDir)) {
|
|
45
|
+
const route = fileToAppRoute(file, appDir, "route", matcher);
|
|
46
|
+
if (route) routes.push(route);
|
|
47
|
+
}
|
|
48
|
+
const slotSubRoutes = discoverSlotSubRoutes(routes, appDir, matcher);
|
|
49
|
+
routes.push(...slotSubRoutes);
|
|
50
|
+
validateRoutePatterns(routes.map((route) => route.pattern));
|
|
51
|
+
validateRoutePatterns(routes.flatMap((route) => route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.map((intercept) => intercept.targetPattern))));
|
|
52
|
+
routes.sort(compareRoutes);
|
|
53
|
+
cachedRoutes = routes;
|
|
54
|
+
cachedAppDir = appDir;
|
|
55
|
+
cachedPageExtensionsKey = pageExtensionsKey;
|
|
56
|
+
return routes;
|
|
72
57
|
}
|
|
73
58
|
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
59
|
+
* Discover sub-routes created by nested pages within parallel slots.
|
|
60
|
+
*
|
|
61
|
+
* In Next.js, pages nested inside @slot directories create additional URL routes.
|
|
62
|
+
* For example, given:
|
|
63
|
+
* app/parallel-routes/@audience/demographics/page.tsx
|
|
64
|
+
* This creates a route at /parallel-routes/demographics where:
|
|
65
|
+
* - children slot → parent's default.tsx
|
|
66
|
+
* - @audience slot → @audience/demographics/page.tsx (matched)
|
|
67
|
+
* - other slots → their default.tsx (fallback)
|
|
68
|
+
*/
|
|
84
69
|
function discoverSlotSubRoutes(routes, _appDir, matcher) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
errorPath: parentRoute.errorPath,
|
|
169
|
-
layoutErrorPaths: parentRoute.layoutErrorPaths,
|
|
170
|
-
notFoundPath: parentRoute.notFoundPath,
|
|
171
|
-
notFoundPaths: parentRoute.notFoundPaths,
|
|
172
|
-
forbiddenPath: parentRoute.forbiddenPath,
|
|
173
|
-
unauthorizedPath: parentRoute.unauthorizedPath,
|
|
174
|
-
routeSegments: [...parentRoute.routeSegments, ...rawSegments],
|
|
175
|
-
layoutTreePositions: parentRoute.layoutTreePositions,
|
|
176
|
-
isDynamic: parentRoute.isDynamic || subIsDynamic,
|
|
177
|
-
params: [...parentRoute.params, ...subParams],
|
|
178
|
-
patternParts: [...parentRoute.patternParts, ...urlParts],
|
|
179
|
-
};
|
|
180
|
-
syntheticRoutes.push(newRoute);
|
|
181
|
-
routesByPattern.set(pattern, newRoute);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return syntheticRoutes;
|
|
70
|
+
const syntheticRoutes = [];
|
|
71
|
+
const routesByPattern = new Map(routes.map((r) => [r.pattern, r]));
|
|
72
|
+
const slotKey = (slotName, ownerDir) => `${slotName}\u0000${ownerDir}`;
|
|
73
|
+
const applySlotSubPages = (route, slotPages) => {
|
|
74
|
+
route.parallelSlots = route.parallelSlots.map((slot) => ({
|
|
75
|
+
...slot,
|
|
76
|
+
pagePath: slotPages.get(slotKey(slot.name, slot.ownerDir)) ?? slot.pagePath
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
for (const parentRoute of routes) {
|
|
80
|
+
if (parentRoute.parallelSlots.length === 0) continue;
|
|
81
|
+
if (!parentRoute.pagePath) continue;
|
|
82
|
+
const parentPageDir = path.dirname(parentRoute.pagePath);
|
|
83
|
+
const subPathMap = /* @__PURE__ */ new Map();
|
|
84
|
+
for (const slot of parentRoute.parallelSlots) {
|
|
85
|
+
const slotDir = path.join(parentPageDir, `@${slot.name}`);
|
|
86
|
+
if (!fs.existsSync(slotDir)) continue;
|
|
87
|
+
const subPages = findSlotSubPages(slotDir, matcher);
|
|
88
|
+
for (const { relativePath, pagePath } of subPages) {
|
|
89
|
+
const subSegments = relativePath.split(path.sep);
|
|
90
|
+
const convertedSubRoute = convertSegmentsToRouteParts(subSegments);
|
|
91
|
+
if (!convertedSubRoute) continue;
|
|
92
|
+
const { urlSegments } = convertedSubRoute;
|
|
93
|
+
const normalizedSubPath = urlSegments.join("/");
|
|
94
|
+
let subPathEntry = subPathMap.get(normalizedSubPath);
|
|
95
|
+
if (!subPathEntry) {
|
|
96
|
+
subPathEntry = {
|
|
97
|
+
rawSegments: subSegments,
|
|
98
|
+
converted: convertedSubRoute,
|
|
99
|
+
slotPages: /* @__PURE__ */ new Map()
|
|
100
|
+
};
|
|
101
|
+
subPathMap.set(normalizedSubPath, subPathEntry);
|
|
102
|
+
}
|
|
103
|
+
const slotId = slotKey(slot.name, slot.ownerDir);
|
|
104
|
+
if (subPathEntry.slotPages.get(slotId)) {
|
|
105
|
+
const pattern = joinRoutePattern(parentRoute.pattern, normalizedSubPath);
|
|
106
|
+
throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
|
|
107
|
+
}
|
|
108
|
+
subPathEntry.slotPages.set(slotId, pagePath);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (subPathMap.size === 0) continue;
|
|
112
|
+
const childrenDefault = findFile(parentPageDir, "default", matcher);
|
|
113
|
+
if (!childrenDefault) continue;
|
|
114
|
+
for (const { rawSegments, converted: convertedSubRoute, slotPages } of subPathMap.values()) {
|
|
115
|
+
const { urlSegments: urlParts, params: subParams, isDynamic: subIsDynamic } = convertedSubRoute;
|
|
116
|
+
const subUrlPath = urlParts.join("/");
|
|
117
|
+
const pattern = joinRoutePattern(parentRoute.pattern, subUrlPath);
|
|
118
|
+
const existingRoute = routesByPattern.get(pattern);
|
|
119
|
+
if (existingRoute) {
|
|
120
|
+
if (existingRoute.routePath && !existingRoute.pagePath) throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
|
|
121
|
+
applySlotSubPages(existingRoute, slotPages);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const subSlots = parentRoute.parallelSlots.map((slot) => ({
|
|
125
|
+
...slot,
|
|
126
|
+
pagePath: slotPages.get(slotKey(slot.name, slot.ownerDir)) || null
|
|
127
|
+
}));
|
|
128
|
+
const newRoute = {
|
|
129
|
+
pattern,
|
|
130
|
+
pagePath: childrenDefault,
|
|
131
|
+
routePath: null,
|
|
132
|
+
layouts: parentRoute.layouts,
|
|
133
|
+
templates: parentRoute.templates,
|
|
134
|
+
parallelSlots: subSlots,
|
|
135
|
+
loadingPath: parentRoute.loadingPath,
|
|
136
|
+
errorPath: parentRoute.errorPath,
|
|
137
|
+
layoutErrorPaths: parentRoute.layoutErrorPaths,
|
|
138
|
+
notFoundPath: parentRoute.notFoundPath,
|
|
139
|
+
notFoundPaths: parentRoute.notFoundPaths,
|
|
140
|
+
forbiddenPath: parentRoute.forbiddenPath,
|
|
141
|
+
unauthorizedPath: parentRoute.unauthorizedPath,
|
|
142
|
+
routeSegments: [...parentRoute.routeSegments, ...rawSegments],
|
|
143
|
+
layoutTreePositions: parentRoute.layoutTreePositions,
|
|
144
|
+
isDynamic: parentRoute.isDynamic || subIsDynamic,
|
|
145
|
+
params: [...parentRoute.params, ...subParams],
|
|
146
|
+
patternParts: [...parentRoute.patternParts, ...urlParts]
|
|
147
|
+
};
|
|
148
|
+
syntheticRoutes.push(newRoute);
|
|
149
|
+
routesByPattern.set(pattern, newRoute);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return syntheticRoutes;
|
|
185
153
|
}
|
|
186
154
|
/**
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
155
|
+
* Find all page files in subdirectories of a parallel slot directory.
|
|
156
|
+
* Returns relative paths (from the slot dir) and absolute page paths.
|
|
157
|
+
* Skips the root page.tsx (already handled as the slot's main page)
|
|
158
|
+
* and intercepting route directories.
|
|
159
|
+
*/
|
|
192
160
|
function findSlotSubPages(slotDir, matcher) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
scan(slotDir);
|
|
218
|
-
return results;
|
|
161
|
+
const results = [];
|
|
162
|
+
function scan(dir) {
|
|
163
|
+
if (!fs.existsSync(dir)) return;
|
|
164
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
165
|
+
for (const entry of entries) {
|
|
166
|
+
if (!entry.isDirectory()) continue;
|
|
167
|
+
if (matchInterceptConvention(entry.name)) continue;
|
|
168
|
+
if (entry.name.startsWith("_")) continue;
|
|
169
|
+
const subDir = path.join(dir, entry.name);
|
|
170
|
+
const page = findFile(subDir, "page", matcher);
|
|
171
|
+
if (page) {
|
|
172
|
+
const relativePath = path.relative(slotDir, subDir);
|
|
173
|
+
results.push({
|
|
174
|
+
relativePath,
|
|
175
|
+
pagePath: page
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
scan(subDir);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
scan(slotDir);
|
|
182
|
+
return results;
|
|
219
183
|
}
|
|
220
184
|
/**
|
|
221
|
-
|
|
222
|
-
|
|
185
|
+
* Convert a file path relative to app/ into an AppRoute.
|
|
186
|
+
*/
|
|
223
187
|
function fileToAppRoute(file, appDir, type, matcher) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
templates,
|
|
267
|
-
parallelSlots,
|
|
268
|
-
loadingPath,
|
|
269
|
-
errorPath,
|
|
270
|
-
layoutErrorPaths,
|
|
271
|
-
notFoundPath,
|
|
272
|
-
notFoundPaths,
|
|
273
|
-
forbiddenPath,
|
|
274
|
-
unauthorizedPath,
|
|
275
|
-
routeSegments: segments,
|
|
276
|
-
layoutTreePositions,
|
|
277
|
-
isDynamic,
|
|
278
|
-
params,
|
|
279
|
-
patternParts: urlSegments,
|
|
280
|
-
};
|
|
188
|
+
const dir = path.dirname(file);
|
|
189
|
+
const segments = dir === "." ? [] : dir.split(path.sep);
|
|
190
|
+
const params = [];
|
|
191
|
+
let isDynamic = false;
|
|
192
|
+
const convertedRoute = convertSegmentsToRouteParts(segments);
|
|
193
|
+
if (!convertedRoute) return null;
|
|
194
|
+
const { urlSegments, params: routeParams, isDynamic: routeIsDynamic } = convertedRoute;
|
|
195
|
+
params.push(...routeParams);
|
|
196
|
+
isDynamic = routeIsDynamic;
|
|
197
|
+
const pattern = "/" + urlSegments.join("/");
|
|
198
|
+
const layouts = discoverLayouts(segments, appDir, matcher);
|
|
199
|
+
const templates = discoverTemplates(segments, appDir, matcher);
|
|
200
|
+
const layoutTreePositions = computeLayoutTreePositions(appDir, layouts);
|
|
201
|
+
const layoutErrorPaths = discoverLayoutAlignedErrors(segments, appDir, matcher);
|
|
202
|
+
const routeDir = dir === "." ? appDir : path.join(appDir, dir);
|
|
203
|
+
const loadingPath = findFile(routeDir, "loading", matcher);
|
|
204
|
+
const errorPath = findFile(routeDir, "error", matcher);
|
|
205
|
+
const notFoundPath = discoverBoundaryFile(segments, appDir, "not-found", matcher);
|
|
206
|
+
const forbiddenPath = discoverBoundaryFile(segments, appDir, "forbidden", matcher);
|
|
207
|
+
const unauthorizedPath = discoverBoundaryFile(segments, appDir, "unauthorized", matcher);
|
|
208
|
+
const notFoundPaths = discoverBoundaryFilePerLayout(layouts, "not-found", matcher);
|
|
209
|
+
const parallelSlots = discoverInheritedParallelSlots(segments, appDir, routeDir, matcher);
|
|
210
|
+
return {
|
|
211
|
+
pattern: pattern === "/" ? "/" : pattern,
|
|
212
|
+
pagePath: type === "page" ? path.join(appDir, file) : null,
|
|
213
|
+
routePath: type === "route" ? path.join(appDir, file) : null,
|
|
214
|
+
layouts,
|
|
215
|
+
templates,
|
|
216
|
+
parallelSlots,
|
|
217
|
+
loadingPath,
|
|
218
|
+
errorPath,
|
|
219
|
+
layoutErrorPaths,
|
|
220
|
+
notFoundPath,
|
|
221
|
+
notFoundPaths,
|
|
222
|
+
forbiddenPath,
|
|
223
|
+
unauthorizedPath,
|
|
224
|
+
routeSegments: segments,
|
|
225
|
+
layoutTreePositions,
|
|
226
|
+
isDynamic,
|
|
227
|
+
params,
|
|
228
|
+
patternParts: urlSegments
|
|
229
|
+
};
|
|
281
230
|
}
|
|
282
231
|
/**
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
232
|
+
* Compute the tree position (directory depth from app root) for each layout.
|
|
233
|
+
* Root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.
|
|
234
|
+
* Counts ALL directory levels including route groups and parallel slots.
|
|
235
|
+
*/
|
|
287
236
|
function computeLayoutTreePositions(appDir, layouts) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
return relative.split(path.sep).length;
|
|
294
|
-
});
|
|
237
|
+
return layouts.map((layoutPath) => {
|
|
238
|
+
const layoutDir = path.dirname(layoutPath);
|
|
239
|
+
if (layoutDir === appDir) return 0;
|
|
240
|
+
return path.relative(appDir, layoutDir).split(path.sep).length;
|
|
241
|
+
});
|
|
295
242
|
}
|
|
296
243
|
/**
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
244
|
+
* Discover all layout files from root to the given directory.
|
|
245
|
+
* Each level of the directory tree may have a layout.tsx.
|
|
246
|
+
*/
|
|
300
247
|
function discoverLayouts(segments, appDir, matcher) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
if (layout)
|
|
312
|
-
layouts.push(layout);
|
|
313
|
-
}
|
|
314
|
-
return layouts;
|
|
248
|
+
const layouts = [];
|
|
249
|
+
const rootLayout = findFile(appDir, "layout", matcher);
|
|
250
|
+
if (rootLayout) layouts.push(rootLayout);
|
|
251
|
+
let currentDir = appDir;
|
|
252
|
+
for (const segment of segments) {
|
|
253
|
+
currentDir = path.join(currentDir, segment);
|
|
254
|
+
const layout = findFile(currentDir, "layout", matcher);
|
|
255
|
+
if (layout) layouts.push(layout);
|
|
256
|
+
}
|
|
257
|
+
return layouts;
|
|
315
258
|
}
|
|
316
259
|
/**
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
260
|
+
* Discover all template files from root to the given directory.
|
|
261
|
+
* Each level of the directory tree may have a template.tsx.
|
|
262
|
+
* Templates are like layouts but re-mount on navigation.
|
|
263
|
+
*/
|
|
321
264
|
function discoverTemplates(segments, appDir, matcher) {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (template)
|
|
333
|
-
templates.push(template);
|
|
334
|
-
}
|
|
335
|
-
return templates;
|
|
265
|
+
const templates = [];
|
|
266
|
+
const rootTemplate = findFile(appDir, "template", matcher);
|
|
267
|
+
if (rootTemplate) templates.push(rootTemplate);
|
|
268
|
+
let currentDir = appDir;
|
|
269
|
+
for (const segment of segments) {
|
|
270
|
+
currentDir = path.join(currentDir, segment);
|
|
271
|
+
const template = findFile(currentDir, "template", matcher);
|
|
272
|
+
if (template) templates.push(template);
|
|
273
|
+
}
|
|
274
|
+
return templates;
|
|
336
275
|
}
|
|
337
276
|
/**
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
277
|
+
* Discover error.tsx files aligned with the layouts array.
|
|
278
|
+
* Walks the same directory levels as discoverLayouts and, for each level
|
|
279
|
+
* that contributes a layout entry, checks whether error.tsx also exists.
|
|
280
|
+
* Returns an array of the same length as discoverLayouts() would return,
|
|
281
|
+
* with the error path (or null) at each corresponding layout level.
|
|
282
|
+
*
|
|
283
|
+
* This enables interleaving ErrorBoundary components with layouts in the
|
|
284
|
+
* rendering tree, matching Next.js behavior where each segment independently
|
|
285
|
+
* wraps its children with an error boundary.
|
|
286
|
+
*/
|
|
348
287
|
function discoverLayoutAlignedErrors(segments, appDir, matcher) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
for (const segment of segments) {
|
|
358
|
-
currentDir = path.join(currentDir, segment);
|
|
359
|
-
const layout = findFile(currentDir, "layout", matcher);
|
|
360
|
-
if (layout) {
|
|
361
|
-
errors.push(findFile(currentDir, "error", matcher));
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return errors;
|
|
288
|
+
const errors = [];
|
|
289
|
+
if (findFile(appDir, "layout", matcher)) errors.push(findFile(appDir, "error", matcher));
|
|
290
|
+
let currentDir = appDir;
|
|
291
|
+
for (const segment of segments) {
|
|
292
|
+
currentDir = path.join(currentDir, segment);
|
|
293
|
+
if (findFile(currentDir, "layout", matcher)) errors.push(findFile(currentDir, "error", matcher));
|
|
294
|
+
}
|
|
295
|
+
return errors;
|
|
365
296
|
}
|
|
366
297
|
/**
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
298
|
+
* Discover the nearest boundary file (not-found, forbidden, unauthorized)
|
|
299
|
+
* by walking from the route's directory up to the app root.
|
|
300
|
+
* Returns the first (closest) file found, or null.
|
|
301
|
+
*/
|
|
371
302
|
function discoverBoundaryFile(segments, appDir, fileName, matcher) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return f;
|
|
385
|
-
}
|
|
386
|
-
return null;
|
|
303
|
+
const dirs = [];
|
|
304
|
+
let dir = appDir;
|
|
305
|
+
dirs.push(dir);
|
|
306
|
+
for (const segment of segments) {
|
|
307
|
+
dir = path.join(dir, segment);
|
|
308
|
+
dirs.push(dir);
|
|
309
|
+
}
|
|
310
|
+
for (let i = dirs.length - 1; i >= 0; i--) {
|
|
311
|
+
const f = findFile(dirs[i], fileName, matcher);
|
|
312
|
+
if (f) return f;
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
387
315
|
}
|
|
388
316
|
/**
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
317
|
+
* Discover boundary files (not-found, forbidden, unauthorized) at each layout directory.
|
|
318
|
+
* Returns an array aligned with the layouts array, where each entry is the boundary
|
|
319
|
+
* file at that layout's directory, or null if none exists there.
|
|
320
|
+
*
|
|
321
|
+
* This is used for per-layout error boundaries. In Next.js, each layout level
|
|
322
|
+
* has its own boundary that wraps the layout's children. When notFound() is thrown
|
|
323
|
+
* from a layout, it propagates up to the parent layout's boundary.
|
|
324
|
+
*/
|
|
397
325
|
function discoverBoundaryFilePerLayout(layouts, fileName, matcher) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
});
|
|
326
|
+
return layouts.map((layoutPath) => {
|
|
327
|
+
return findFile(path.dirname(layoutPath), fileName, matcher);
|
|
328
|
+
});
|
|
402
329
|
}
|
|
403
330
|
/**
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
331
|
+
* Discover parallel slots inherited from ancestor directories.
|
|
332
|
+
*
|
|
333
|
+
* In Next.js, parallel slots belong to the layout that defines them. When a
|
|
334
|
+
* child route is rendered, its parent layout's slots must still be present.
|
|
335
|
+
* If the child doesn't have matching content in a slot, the slot's default.tsx
|
|
336
|
+
* is rendered instead.
|
|
337
|
+
*
|
|
338
|
+
* Walk from appDir through each segment to the route's directory. At each level
|
|
339
|
+
* that has @slot dirs, collect them. Slots at the route's own directory level
|
|
340
|
+
* use page.tsx; slots at ancestor levels use default.tsx only.
|
|
341
|
+
*/
|
|
415
342
|
function discoverInheritedParallelSlots(segments, appDir, routeDir, matcher) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
};
|
|
449
|
-
// Only inherit if we haven't seen this slot at a closer level
|
|
450
|
-
if (!slotMap.has(slot.name)) {
|
|
451
|
-
slotMap.set(slot.name, inheritedSlot);
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
return Array.from(slotMap.values());
|
|
343
|
+
const slotMap = /* @__PURE__ */ new Map();
|
|
344
|
+
let currentDir = appDir;
|
|
345
|
+
const dirsToCheck = [];
|
|
346
|
+
let layoutIdx = findFile(appDir, "layout", matcher) ? 0 : -1;
|
|
347
|
+
dirsToCheck.push({
|
|
348
|
+
dir: appDir,
|
|
349
|
+
layoutIdx: Math.max(layoutIdx, 0)
|
|
350
|
+
});
|
|
351
|
+
for (const segment of segments) {
|
|
352
|
+
currentDir = path.join(currentDir, segment);
|
|
353
|
+
if (findFile(currentDir, "layout", matcher)) layoutIdx++;
|
|
354
|
+
dirsToCheck.push({
|
|
355
|
+
dir: currentDir,
|
|
356
|
+
layoutIdx: Math.max(layoutIdx, 0)
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
for (const { dir, layoutIdx: lvlLayoutIdx } of dirsToCheck) {
|
|
360
|
+
const isOwnDir = dir === routeDir;
|
|
361
|
+
const slotsAtLevel = discoverParallelSlots(dir, appDir, matcher);
|
|
362
|
+
for (const slot of slotsAtLevel) if (isOwnDir) {
|
|
363
|
+
slot.layoutIndex = lvlLayoutIdx;
|
|
364
|
+
slotMap.set(slot.name, slot);
|
|
365
|
+
} else {
|
|
366
|
+
const inheritedSlot = {
|
|
367
|
+
...slot,
|
|
368
|
+
pagePath: null,
|
|
369
|
+
layoutIndex: lvlLayoutIdx
|
|
370
|
+
};
|
|
371
|
+
slotMap.set(slot.name, inheritedSlot);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return Array.from(slotMap.values());
|
|
457
375
|
}
|
|
458
376
|
/**
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
377
|
+
* Discover parallel route slots (@team, @analytics, etc.) in a directory.
|
|
378
|
+
* Returns a ParallelSlot for each @-prefixed subdirectory that has a page or default component.
|
|
379
|
+
*/
|
|
462
380
|
function discoverParallelSlots(dir, appDir, matcher) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
layoutIndex: -1, // Will be set by discoverInheritedParallelSlots
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
return slots;
|
|
381
|
+
if (!fs.existsSync(dir)) return [];
|
|
382
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
383
|
+
const slots = [];
|
|
384
|
+
for (const entry of entries) {
|
|
385
|
+
if (!entry.isDirectory() || !entry.name.startsWith("@")) continue;
|
|
386
|
+
const slotName = entry.name.slice(1);
|
|
387
|
+
const slotDir = path.join(dir, entry.name);
|
|
388
|
+
const pagePath = findFile(slotDir, "page", matcher);
|
|
389
|
+
const defaultPath = findFile(slotDir, "default", matcher);
|
|
390
|
+
const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);
|
|
391
|
+
if (!pagePath && !defaultPath && interceptingRoutes.length === 0) continue;
|
|
392
|
+
slots.push({
|
|
393
|
+
name: slotName,
|
|
394
|
+
ownerDir: slotDir,
|
|
395
|
+
pagePath,
|
|
396
|
+
defaultPath,
|
|
397
|
+
layoutPath: findFile(slotDir, "layout", matcher),
|
|
398
|
+
loadingPath: findFile(slotDir, "loading", matcher),
|
|
399
|
+
errorPath: findFile(slotDir, "error", matcher),
|
|
400
|
+
interceptingRoutes,
|
|
401
|
+
layoutIndex: -1
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return slots;
|
|
491
405
|
}
|
|
492
406
|
/**
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
407
|
+
* The interception convention prefix patterns.
|
|
408
|
+
* (.) — same level, (..) — one level up, (..)(..)" — two levels up, (...) — root
|
|
409
|
+
*/
|
|
496
410
|
const INTERCEPT_PATTERNS = [
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
411
|
+
{
|
|
412
|
+
prefix: "(...)",
|
|
413
|
+
convention: "..."
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
prefix: "(..)(..)",
|
|
417
|
+
convention: "../.."
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
prefix: "(..)",
|
|
421
|
+
convention: ".."
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
prefix: "(.)",
|
|
425
|
+
convention: "."
|
|
426
|
+
}
|
|
501
427
|
];
|
|
502
428
|
/**
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
429
|
+
* Discover intercepting routes inside a parallel slot directory.
|
|
430
|
+
*
|
|
431
|
+
* Intercepting routes use conventions like (.)photo, (..)feed, (...), etc.
|
|
432
|
+
* They intercept navigation to another route and render within the slot instead.
|
|
433
|
+
*
|
|
434
|
+
* @param slotDir - The parallel slot directory (e.g. app/feed/@modal)
|
|
435
|
+
* @param routeDir - The directory of the route that owns this slot (e.g. app/feed)
|
|
436
|
+
* @param appDir - The root app directory
|
|
437
|
+
*/
|
|
512
438
|
function discoverInterceptingRoutes(slotDir, routeDir, appDir, matcher) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
scanForInterceptingPages(slotDir, routeDir, appDir, results, matcher);
|
|
518
|
-
return results;
|
|
439
|
+
if (!fs.existsSync(slotDir)) return [];
|
|
440
|
+
const results = [];
|
|
441
|
+
scanForInterceptingPages(slotDir, routeDir, appDir, results, matcher);
|
|
442
|
+
return results;
|
|
519
443
|
}
|
|
520
444
|
/**
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
445
|
+
* Recursively scan a directory tree for page.tsx files that are inside
|
|
446
|
+
* intercepting route directories.
|
|
447
|
+
*/
|
|
524
448
|
function scanForInterceptingPages(currentDir, routeDir, appDir, results, matcher) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
// This directory is the start of an intercepting route
|
|
538
|
-
// e.g. "(.)photos" means intercept same-level "photos" route
|
|
539
|
-
const restOfName = entry.name.slice(interceptMatch.prefix.length);
|
|
540
|
-
const interceptDir = path.join(currentDir, entry.name);
|
|
541
|
-
// Find page files within this intercepting directory tree
|
|
542
|
-
collectInterceptingPages(interceptDir, interceptDir, interceptMatch.convention, restOfName, routeDir, appDir, results, matcher);
|
|
543
|
-
}
|
|
544
|
-
else {
|
|
545
|
-
// Regular subdirectory — keep scanning for intercepting dirs
|
|
546
|
-
scanForInterceptingPages(path.join(currentDir, entry.name), routeDir, appDir, results, matcher);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
449
|
+
if (!fs.existsSync(currentDir)) return;
|
|
450
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
451
|
+
for (const entry of entries) {
|
|
452
|
+
if (!entry.isDirectory()) continue;
|
|
453
|
+
if (entry.name.startsWith("_")) continue;
|
|
454
|
+
const interceptMatch = matchInterceptConvention(entry.name);
|
|
455
|
+
if (interceptMatch) {
|
|
456
|
+
const restOfName = entry.name.slice(interceptMatch.prefix.length);
|
|
457
|
+
const interceptDir = path.join(currentDir, entry.name);
|
|
458
|
+
collectInterceptingPages(interceptDir, interceptDir, interceptMatch.convention, restOfName, routeDir, appDir, results, matcher);
|
|
459
|
+
} else scanForInterceptingPages(path.join(currentDir, entry.name), routeDir, appDir, results, matcher);
|
|
460
|
+
}
|
|
549
461
|
}
|
|
550
462
|
/**
|
|
551
|
-
|
|
552
|
-
|
|
463
|
+
* Match a directory name against interception convention prefixes.
|
|
464
|
+
*/
|
|
553
465
|
function matchInterceptConvention(name) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
return pattern;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
return null;
|
|
466
|
+
for (const pattern of INTERCEPT_PATTERNS) if (name.startsWith(pattern.prefix)) return pattern;
|
|
467
|
+
return null;
|
|
560
468
|
}
|
|
561
469
|
/**
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
470
|
+
* Collect page.tsx files inside an intercepting route directory tree
|
|
471
|
+
* and compute their target URL patterns.
|
|
472
|
+
*/
|
|
565
473
|
function collectInterceptingPages(currentDir, interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
for (const entry of entries) {
|
|
584
|
-
if (!entry.isDirectory())
|
|
585
|
-
continue;
|
|
586
|
-
// Skip private folders (prefixed with _)
|
|
587
|
-
if (entry.name.startsWith("_"))
|
|
588
|
-
continue;
|
|
589
|
-
collectInterceptingPages(path.join(currentDir, entry.name), interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher);
|
|
590
|
-
}
|
|
474
|
+
const page = findFile(currentDir, "page", matcher);
|
|
475
|
+
if (page) {
|
|
476
|
+
const targetPattern = computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir);
|
|
477
|
+
if (targetPattern) results.push({
|
|
478
|
+
convention,
|
|
479
|
+
targetPattern: targetPattern.pattern,
|
|
480
|
+
pagePath: page,
|
|
481
|
+
params: targetPattern.params
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
if (!fs.existsSync(currentDir)) return;
|
|
485
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
486
|
+
for (const entry of entries) {
|
|
487
|
+
if (!entry.isDirectory()) continue;
|
|
488
|
+
if (entry.name.startsWith("_")) continue;
|
|
489
|
+
collectInterceptingPages(path.join(currentDir, entry.name), interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher);
|
|
490
|
+
}
|
|
591
491
|
}
|
|
592
492
|
/**
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
493
|
+
* Check whether a path segment is invisible in the URL (route groups, parallel slots, ".").
|
|
494
|
+
*
|
|
495
|
+
* Used by computeInterceptTarget, convertSegmentsToRouteParts, and
|
|
496
|
+
* hasRemainingVisibleSegments — keep this the single source of truth.
|
|
497
|
+
*/
|
|
598
498
|
function isInvisibleSegment(segment) {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
if (segment.startsWith("@"))
|
|
604
|
-
return true;
|
|
605
|
-
return false;
|
|
499
|
+
if (segment === ".") return true;
|
|
500
|
+
if (segment.startsWith("(") && segment.endsWith(")")) return true;
|
|
501
|
+
if (segment.startsWith("@")) return true;
|
|
502
|
+
return false;
|
|
606
503
|
}
|
|
607
504
|
/**
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
505
|
+
* Compute the target URL pattern for an intercepting route.
|
|
506
|
+
*
|
|
507
|
+
* Interception conventions (..), (..)(..)" climb by *visible route segments*
|
|
508
|
+
* (not filesystem directories). Route groups like (marketing) and parallel
|
|
509
|
+
* slots like @modal are invisible and must be skipped when counting levels.
|
|
510
|
+
*
|
|
511
|
+
* - (.) same level: resolve relative to routeDir
|
|
512
|
+
* - (..) one level up: climb 1 visible segment
|
|
513
|
+
* - (..)(..) two levels up: climb 2 visible segments
|
|
514
|
+
* - (...) root: resolve from appDir
|
|
515
|
+
*/
|
|
619
516
|
function computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir) {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
const pattern = "/" + urlSegments.join("/");
|
|
657
|
-
return { pattern: pattern === "/" ? "/" : pattern, params };
|
|
517
|
+
const routeSegments = path.relative(appDir, routeDir).split(path.sep).filter(Boolean);
|
|
518
|
+
let baseParts;
|
|
519
|
+
switch (convention) {
|
|
520
|
+
case ".":
|
|
521
|
+
baseParts = routeSegments;
|
|
522
|
+
break;
|
|
523
|
+
case "..":
|
|
524
|
+
case "../..": {
|
|
525
|
+
const levelsToClimb = convention === ".." ? 1 : 2;
|
|
526
|
+
let climbed = 0;
|
|
527
|
+
let cutIndex = routeSegments.length;
|
|
528
|
+
while (cutIndex > 0 && climbed < levelsToClimb) {
|
|
529
|
+
cutIndex--;
|
|
530
|
+
if (!isInvisibleSegment(routeSegments[cutIndex])) climbed++;
|
|
531
|
+
}
|
|
532
|
+
baseParts = routeSegments.slice(0, cutIndex);
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
case "...":
|
|
536
|
+
baseParts = [];
|
|
537
|
+
break;
|
|
538
|
+
default: return null;
|
|
539
|
+
}
|
|
540
|
+
const nestedParts = path.relative(interceptRoot, currentDir).split(path.sep).filter(Boolean);
|
|
541
|
+
const convertedTarget = convertSegmentsToRouteParts([
|
|
542
|
+
...baseParts,
|
|
543
|
+
interceptSegment,
|
|
544
|
+
...nestedParts
|
|
545
|
+
]);
|
|
546
|
+
if (!convertedTarget) return null;
|
|
547
|
+
const { urlSegments, params } = convertedTarget;
|
|
548
|
+
const pattern = "/" + urlSegments.join("/");
|
|
549
|
+
return {
|
|
550
|
+
pattern: pattern === "/" ? "/" : pattern,
|
|
551
|
+
params
|
|
552
|
+
};
|
|
658
553
|
}
|
|
659
554
|
/**
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
555
|
+
* Find a file by name (without extension) in a directory.
|
|
556
|
+
* Checks configured pageExtensions.
|
|
557
|
+
*/
|
|
663
558
|
function findFile(dir, name, matcher) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
return null;
|
|
559
|
+
for (const ext of matcher.dottedExtensions) {
|
|
560
|
+
const filePath = path.join(dir, name + ext);
|
|
561
|
+
if (fs.existsSync(filePath)) return filePath;
|
|
562
|
+
}
|
|
563
|
+
return null;
|
|
670
564
|
}
|
|
671
565
|
/**
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
566
|
+
* Convert filesystem path segments to URL route parts, skipping invisible segments
|
|
567
|
+
* (route groups, @slots, ".") and converting dynamic segment syntax to Express-style
|
|
568
|
+
* patterns (e.g. "[id]" → ":id", "[...slug]" → ":slug+").
|
|
569
|
+
*/
|
|
676
570
|
function convertSegmentsToRouteParts(segments) {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
571
|
+
const urlSegments = [];
|
|
572
|
+
const params = [];
|
|
573
|
+
let isDynamic = false;
|
|
574
|
+
for (let i = 0; i < segments.length; i++) {
|
|
575
|
+
const segment = segments[i];
|
|
576
|
+
if (isInvisibleSegment(segment)) continue;
|
|
577
|
+
const catchAllMatch = segment.match(/^\[\.\.\.([\w-]+)\]$/);
|
|
578
|
+
if (catchAllMatch) {
|
|
579
|
+
if (hasRemainingVisibleSegments(segments, i + 1)) return null;
|
|
580
|
+
isDynamic = true;
|
|
581
|
+
params.push(catchAllMatch[1]);
|
|
582
|
+
urlSegments.push(`:${catchAllMatch[1]}+`);
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.([\w-]+)\]\]$/);
|
|
586
|
+
if (optionalCatchAllMatch) {
|
|
587
|
+
if (hasRemainingVisibleSegments(segments, i + 1)) return null;
|
|
588
|
+
isDynamic = true;
|
|
589
|
+
params.push(optionalCatchAllMatch[1]);
|
|
590
|
+
urlSegments.push(`:${optionalCatchAllMatch[1]}*`);
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
const dynamicMatch = segment.match(/^\[([\w-]+)\]$/);
|
|
594
|
+
if (dynamicMatch) {
|
|
595
|
+
isDynamic = true;
|
|
596
|
+
params.push(dynamicMatch[1]);
|
|
597
|
+
urlSegments.push(`:${dynamicMatch[1]}`);
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
urlSegments.push(decodeRouteSegment(segment));
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
urlSegments,
|
|
604
|
+
params,
|
|
605
|
+
isDynamic
|
|
606
|
+
};
|
|
713
607
|
}
|
|
714
608
|
function hasRemainingVisibleSegments(segments, startIndex) {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
return true;
|
|
718
|
-
}
|
|
719
|
-
return false;
|
|
609
|
+
for (let i = startIndex; i < segments.length; i++) if (!isInvisibleSegment(segments[i])) return true;
|
|
610
|
+
return false;
|
|
720
611
|
}
|
|
721
|
-
|
|
722
|
-
const appTrieCache = new WeakMap();
|
|
612
|
+
const appTrieCache = /* @__PURE__ */ new WeakMap();
|
|
723
613
|
function getOrBuildAppTrie(routes) {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
614
|
+
let trie = appTrieCache.get(routes);
|
|
615
|
+
if (!trie) {
|
|
616
|
+
trie = buildRouteTrie(routes);
|
|
617
|
+
appTrieCache.set(routes, trie);
|
|
618
|
+
}
|
|
619
|
+
return trie;
|
|
730
620
|
}
|
|
731
621
|
function joinRoutePattern(basePattern, subPath) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
return basePattern === "/" ? `/${subPath}` : `${basePattern}/${subPath}`;
|
|
622
|
+
if (!subPath) return basePattern;
|
|
623
|
+
return basePattern === "/" ? `/${subPath}` : `${basePattern}/${subPath}`;
|
|
735
624
|
}
|
|
736
625
|
/**
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
const trie = getOrBuildAppTrie(routes);
|
|
746
|
-
return trieMatch(trie, urlParts);
|
|
626
|
+
* Match a URL against App Router routes.
|
|
627
|
+
*/
|
|
628
|
+
function matchAppRoute(url, routes) {
|
|
629
|
+
const pathname = url.split("?")[0];
|
|
630
|
+
let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
|
|
631
|
+
normalizedUrl = normalizePathnameForRouteMatch(normalizedUrl);
|
|
632
|
+
const urlParts = normalizedUrl.split("/").filter(Boolean);
|
|
633
|
+
return trieMatch(getOrBuildAppTrie(routes), urlParts);
|
|
747
634
|
}
|
|
635
|
+
//#endregion
|
|
636
|
+
export { appRouter, invalidateAppRouteCache, matchAppRoute };
|
|
637
|
+
|
|
748
638
|
//# sourceMappingURL=app-router.js.map
|