vinext 0.0.30 → 0.0.32
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 +15 -7
- 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 +581 -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 +681 -571
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts +1 -15
- package/dist/cli.js +432 -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 +376 -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 +444 -212
- 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 +86 -114
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/index.d.ts +92 -60
- package/dist/index.js +2151 -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 +160 -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 +19 -15
- package/dist/server/dev-server.js +543 -871
- 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 +34 -59
- package/dist/server/instrumentation.js +112 -125
- 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 +32 -47
- package/dist/server/middleware.js +261 -409
- 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 +715 -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 +6 -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 +439 -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 +17 -20
- package/dist/shims/head.js +194 -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 +7 -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 +213 -164
- package/dist/shims/server.js +545 -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,160 +1,140 @@
|
|
|
1
|
-
|
|
2
|
-
* Trie (prefix tree) for O(depth) route matching.
|
|
3
|
-
*
|
|
4
|
-
* Replaces the O(n) linear scan over pre-sorted routes with a trie-based
|
|
5
|
-
* lookup. Priority is enforced by traversal order at each node:
|
|
6
|
-
* 1. Static child (exact segment match) — highest priority
|
|
7
|
-
* 2. Dynamic child (single-segment param) — medium
|
|
8
|
-
* 3. Catch-all (1+ remaining segments) — low
|
|
9
|
-
* 4. Optional catch-all (0+ remaining segments) — lowest
|
|
10
|
-
*
|
|
11
|
-
* Backtracking via recursive DFS ensures that dead-end static/dynamic
|
|
12
|
-
* branches fall through to catch-all alternatives.
|
|
13
|
-
*/
|
|
1
|
+
//#region src/routing/route-trie.ts
|
|
14
2
|
function createNode() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
3
|
+
return {
|
|
4
|
+
staticChildren: /* @__PURE__ */ new Map(),
|
|
5
|
+
dynamicChild: null,
|
|
6
|
+
catchAllChild: null,
|
|
7
|
+
optionalCatchAllChild: null,
|
|
8
|
+
route: null
|
|
9
|
+
};
|
|
22
10
|
}
|
|
23
11
|
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
node.staticChildren.set(part, child);
|
|
90
|
-
}
|
|
91
|
-
node = child;
|
|
92
|
-
// If this is the last segment, set the route
|
|
93
|
-
if (i === parts.length - 1) {
|
|
94
|
-
if (node.route === null) {
|
|
95
|
-
node.route = route;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return root;
|
|
12
|
+
* Build a trie from pre-sorted routes.
|
|
13
|
+
*
|
|
14
|
+
* Routes must have a `patternParts` property (string[] of URL segments).
|
|
15
|
+
* Pattern segment conventions:
|
|
16
|
+
* - `:name` — dynamic segment
|
|
17
|
+
* - `:name+` — catch-all (1+ segments)
|
|
18
|
+
* - `:name*` — optional catch-all (0+ segments)
|
|
19
|
+
* - anything else — static segment
|
|
20
|
+
*
|
|
21
|
+
* First route to claim a terminal position wins (routes are pre-sorted
|
|
22
|
+
* by precedence, so insertion order preserves correct priority).
|
|
23
|
+
*/
|
|
24
|
+
function buildRouteTrie(routes) {
|
|
25
|
+
const root = createNode();
|
|
26
|
+
for (const route of routes) {
|
|
27
|
+
const parts = route.patternParts;
|
|
28
|
+
if (parts.length === 0) {
|
|
29
|
+
if (root.route === null) root.route = route;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
let node = root;
|
|
33
|
+
for (let i = 0; i < parts.length; i++) {
|
|
34
|
+
const part = parts[i];
|
|
35
|
+
if (part.endsWith("+") && part.startsWith(":")) {
|
|
36
|
+
if (i !== parts.length - 1) break;
|
|
37
|
+
const paramName = part.slice(1, -1);
|
|
38
|
+
if (node.catchAllChild === null) node.catchAllChild = {
|
|
39
|
+
paramName,
|
|
40
|
+
route
|
|
41
|
+
};
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (part.endsWith("*") && part.startsWith(":")) {
|
|
45
|
+
if (i !== parts.length - 1) break;
|
|
46
|
+
const paramName = part.slice(1, -1);
|
|
47
|
+
if (node.optionalCatchAllChild === null) node.optionalCatchAllChild = {
|
|
48
|
+
paramName,
|
|
49
|
+
route
|
|
50
|
+
};
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
if (part.startsWith(":")) {
|
|
54
|
+
const paramName = part.slice(1);
|
|
55
|
+
if (node.dynamicChild === null) node.dynamicChild = {
|
|
56
|
+
paramName,
|
|
57
|
+
node: createNode()
|
|
58
|
+
};
|
|
59
|
+
node = node.dynamicChild.node;
|
|
60
|
+
if (i === parts.length - 1) {
|
|
61
|
+
if (node.route === null) node.route = route;
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
let child = node.staticChildren.get(part);
|
|
66
|
+
if (!child) {
|
|
67
|
+
child = createNode();
|
|
68
|
+
node.staticChildren.set(part, child);
|
|
69
|
+
}
|
|
70
|
+
node = child;
|
|
71
|
+
if (i === parts.length - 1) {
|
|
72
|
+
if (node.route === null) node.route = route;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return root;
|
|
101
77
|
}
|
|
102
78
|
/**
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
79
|
+
* Match a URL against the trie.
|
|
80
|
+
*
|
|
81
|
+
* @param root - Trie root built by `buildRouteTrie`
|
|
82
|
+
* @param urlParts - Pre-split URL segments (no empty strings)
|
|
83
|
+
* @returns Match result with route and extracted params, or null
|
|
84
|
+
*/
|
|
85
|
+
function trieMatch(root, urlParts) {
|
|
86
|
+
return match(root, urlParts, 0);
|
|
111
87
|
}
|
|
112
88
|
function match(node, urlParts, index) {
|
|
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
|
-
|
|
89
|
+
if (index === urlParts.length) {
|
|
90
|
+
if (node.route !== null) return {
|
|
91
|
+
route: node.route,
|
|
92
|
+
params: Object.create(null)
|
|
93
|
+
};
|
|
94
|
+
if (node.optionalCatchAllChild !== null) {
|
|
95
|
+
const params = Object.create(null);
|
|
96
|
+
params[node.optionalCatchAllChild.paramName] = [];
|
|
97
|
+
return {
|
|
98
|
+
route: node.optionalCatchAllChild.route,
|
|
99
|
+
params
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const segment = urlParts[index];
|
|
105
|
+
const staticChild = node.staticChildren.get(segment);
|
|
106
|
+
if (staticChild) {
|
|
107
|
+
const result = match(staticChild, urlParts, index + 1);
|
|
108
|
+
if (result !== null) return result;
|
|
109
|
+
}
|
|
110
|
+
if (node.dynamicChild !== null) {
|
|
111
|
+
const result = match(node.dynamicChild.node, urlParts, index + 1);
|
|
112
|
+
if (result !== null) {
|
|
113
|
+
result.params[node.dynamicChild.paramName] = segment;
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (node.catchAllChild !== null) {
|
|
118
|
+
const remaining = urlParts.slice(index);
|
|
119
|
+
const params = Object.create(null);
|
|
120
|
+
params[node.catchAllChild.paramName] = remaining;
|
|
121
|
+
return {
|
|
122
|
+
route: node.catchAllChild.route,
|
|
123
|
+
params
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (node.optionalCatchAllChild !== null) {
|
|
127
|
+
const remaining = urlParts.slice(index);
|
|
128
|
+
const params = Object.create(null);
|
|
129
|
+
params[node.optionalCatchAllChild.paramName] = remaining;
|
|
130
|
+
return {
|
|
131
|
+
route: node.optionalCatchAllChild.route,
|
|
132
|
+
params
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
159
136
|
}
|
|
137
|
+
//#endregion
|
|
138
|
+
export { buildRouteTrie, trieMatch };
|
|
139
|
+
|
|
160
140
|
//# sourceMappingURL=route-trie.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-trie.js","sourceRoot":"","sources":["../../src/routing/route-trie.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Trie (prefix tree) for O(depth) route matching.\n *\n * Replaces the O(n) linear scan over pre-sorted routes with a trie-based\n * lookup. Priority is enforced by traversal order at each node:\n * 1. Static child (exact segment match) — highest priority\n * 2. Dynamic child (single-segment param) — medium\n * 3. Catch-all (1+ remaining segments) — low\n * 4. Optional catch-all (0+ remaining segments) — lowest\n *\n * Backtracking via recursive DFS ensures that dead-end static/dynamic\n * branches fall through to catch-all alternatives.\n */\n\nexport interface TrieNode<R> {\n staticChildren: Map<string, TrieNode<R>>;\n dynamicChild: { paramName: string; node: TrieNode<R> } | null;\n catchAllChild: { paramName: string; route: R } | null;\n optionalCatchAllChild: { paramName: string; route: R } | null;\n route: R | null;\n}\n\nfunction createNode<R>(): TrieNode<R> {\n return {\n staticChildren: new Map(),\n dynamicChild: null,\n catchAllChild: null,\n optionalCatchAllChild: null,\n route: null,\n };\n}\n\n/**\n * Build a trie from pre-sorted routes.\n *\n * Routes must have a `patternParts` property (string[] of URL segments).\n * Pattern segment conventions:\n * - `:name` — dynamic segment\n * - `:name+` — catch-all (1+ segments)\n * - `:name*` — optional catch-all (0+ segments)\n * - anything else — static segment\n *\n * First route to claim a terminal position wins (routes are pre-sorted\n * by precedence, so insertion order preserves correct priority).\n */\nexport function buildRouteTrie<R extends { patternParts: string[] }>(routes: R[]): TrieNode<R> {\n const root = createNode<R>();\n\n for (const route of routes) {\n const parts = route.patternParts;\n\n // Root route (patternParts = [])\n if (parts.length === 0) {\n if (root.route === null) {\n root.route = route;\n }\n continue;\n }\n\n let node = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n // Catch-all: :name+ (must be terminal — skip malformed non-terminal catch-alls)\n if (part.endsWith(\"+\") && part.startsWith(\":\")) {\n if (i !== parts.length - 1) break; // malformed: not terminal\n const paramName = part.slice(1, -1);\n if (node.catchAllChild === null) {\n node.catchAllChild = { paramName, route };\n }\n break;\n }\n\n // Optional catch-all: :name* (must be terminal — skip malformed non-terminal)\n if (part.endsWith(\"*\") && part.startsWith(\":\")) {\n if (i !== parts.length - 1) break; // malformed: not terminal\n const paramName = part.slice(1, -1);\n if (node.optionalCatchAllChild === null) {\n node.optionalCatchAllChild = { paramName, route };\n }\n break;\n }\n\n // Dynamic segment: :name\n if (part.startsWith(\":\")) {\n const paramName = part.slice(1);\n if (node.dynamicChild === null) {\n node.dynamicChild = { paramName, node: createNode<R>() };\n }\n node = node.dynamicChild.node;\n\n // If this is the last segment, set the route\n if (i === parts.length - 1) {\n if (node.route === null) {\n node.route = route;\n }\n }\n continue;\n }\n\n // Static segment\n let child = node.staticChildren.get(part);\n if (!child) {\n child = createNode<R>();\n node.staticChildren.set(part, child);\n }\n node = child;\n\n // If this is the last segment, set the route\n if (i === parts.length - 1) {\n if (node.route === null) {\n node.route = route;\n }\n }\n }\n }\n\n return root;\n}\n\n/**\n * Match a URL against the trie.\n *\n * @param root - Trie root built by `buildRouteTrie`\n * @param urlParts - Pre-split URL segments (no empty strings)\n * @returns Match result with route and extracted params, or null\n */\nexport function trieMatch<R>(\n root: TrieNode<R>,\n urlParts: string[],\n): { route: R; params: Record<string, string | string[]> } | null {\n return match(root, urlParts, 0);\n}\n\nfunction match<R>(\n node: TrieNode<R>,\n urlParts: string[],\n index: number,\n): { route: R; params: Record<string, string | string[]> } | null {\n // All URL segments consumed\n if (index === urlParts.length) {\n // Exact match at this node\n if (node.route !== null) {\n return { route: node.route, params: Object.create(null) };\n }\n\n // Optional catch-all with 0 segments\n if (node.optionalCatchAllChild !== null) {\n const params: Record<string, string | string[]> = Object.create(null);\n params[node.optionalCatchAllChild.paramName] = [];\n return { route: node.optionalCatchAllChild.route, params };\n }\n\n return null;\n }\n\n const segment = urlParts[index];\n\n // 1. Try static child (highest priority)\n const staticChild = node.staticChildren.get(segment);\n if (staticChild) {\n const result = match(staticChild, urlParts, index + 1);\n if (result !== null) {\n return result;\n }\n }\n\n // 2. Try dynamic child (single segment)\n if (node.dynamicChild !== null) {\n const result = match(node.dynamicChild.node, urlParts, index + 1);\n if (result !== null) {\n result.params[node.dynamicChild.paramName] = segment;\n return result;\n }\n }\n\n // 3. Try catch-all (1+ remaining segments)\n if (node.catchAllChild !== null) {\n const remaining = urlParts.slice(index);\n const params: Record<string, string | string[]> = Object.create(null);\n params[node.catchAllChild.paramName] = remaining;\n return { route: node.catchAllChild.route, params };\n }\n\n // 4. Try optional catch-all (0+ remaining segments)\n if (node.optionalCatchAllChild !== null) {\n const remaining = urlParts.slice(index);\n const params: Record<string, string | string[]> = Object.create(null);\n params[node.optionalCatchAllChild.paramName] = remaining;\n return { route: node.optionalCatchAllChild.route, params };\n }\n\n return null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"route-trie.js","names":[],"sources":["../../src/routing/route-trie.ts"],"sourcesContent":["/**\n * Trie (prefix tree) for O(depth) route matching.\n *\n * Replaces the O(n) linear scan over pre-sorted routes with a trie-based\n * lookup. Priority is enforced by traversal order at each node:\n * 1. Static child (exact segment match) — highest priority\n * 2. Dynamic child (single-segment param) — medium\n * 3. Catch-all (1+ remaining segments) — low\n * 4. Optional catch-all (0+ remaining segments) — lowest\n *\n * Backtracking via recursive DFS ensures that dead-end static/dynamic\n * branches fall through to catch-all alternatives.\n */\n\nexport interface TrieNode<R> {\n staticChildren: Map<string, TrieNode<R>>;\n dynamicChild: { paramName: string; node: TrieNode<R> } | null;\n catchAllChild: { paramName: string; route: R } | null;\n optionalCatchAllChild: { paramName: string; route: R } | null;\n route: R | null;\n}\n\nfunction createNode<R>(): TrieNode<R> {\n return {\n staticChildren: new Map(),\n dynamicChild: null,\n catchAllChild: null,\n optionalCatchAllChild: null,\n route: null,\n };\n}\n\n/**\n * Build a trie from pre-sorted routes.\n *\n * Routes must have a `patternParts` property (string[] of URL segments).\n * Pattern segment conventions:\n * - `:name` — dynamic segment\n * - `:name+` — catch-all (1+ segments)\n * - `:name*` — optional catch-all (0+ segments)\n * - anything else — static segment\n *\n * First route to claim a terminal position wins (routes are pre-sorted\n * by precedence, so insertion order preserves correct priority).\n */\nexport function buildRouteTrie<R extends { patternParts: string[] }>(routes: R[]): TrieNode<R> {\n const root = createNode<R>();\n\n for (const route of routes) {\n const parts = route.patternParts;\n\n // Root route (patternParts = [])\n if (parts.length === 0) {\n if (root.route === null) {\n root.route = route;\n }\n continue;\n }\n\n let node = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n // Catch-all: :name+ (must be terminal — skip malformed non-terminal catch-alls)\n if (part.endsWith(\"+\") && part.startsWith(\":\")) {\n if (i !== parts.length - 1) break; // malformed: not terminal\n const paramName = part.slice(1, -1);\n if (node.catchAllChild === null) {\n node.catchAllChild = { paramName, route };\n }\n break;\n }\n\n // Optional catch-all: :name* (must be terminal — skip malformed non-terminal)\n if (part.endsWith(\"*\") && part.startsWith(\":\")) {\n if (i !== parts.length - 1) break; // malformed: not terminal\n const paramName = part.slice(1, -1);\n if (node.optionalCatchAllChild === null) {\n node.optionalCatchAllChild = { paramName, route };\n }\n break;\n }\n\n // Dynamic segment: :name\n if (part.startsWith(\":\")) {\n const paramName = part.slice(1);\n if (node.dynamicChild === null) {\n node.dynamicChild = { paramName, node: createNode<R>() };\n }\n node = node.dynamicChild.node;\n\n // If this is the last segment, set the route\n if (i === parts.length - 1) {\n if (node.route === null) {\n node.route = route;\n }\n }\n continue;\n }\n\n // Static segment\n let child = node.staticChildren.get(part);\n if (!child) {\n child = createNode<R>();\n node.staticChildren.set(part, child);\n }\n node = child;\n\n // If this is the last segment, set the route\n if (i === parts.length - 1) {\n if (node.route === null) {\n node.route = route;\n }\n }\n }\n }\n\n return root;\n}\n\n/**\n * Match a URL against the trie.\n *\n * @param root - Trie root built by `buildRouteTrie`\n * @param urlParts - Pre-split URL segments (no empty strings)\n * @returns Match result with route and extracted params, or null\n */\nexport function trieMatch<R>(\n root: TrieNode<R>,\n urlParts: string[],\n): { route: R; params: Record<string, string | string[]> } | null {\n return match(root, urlParts, 0);\n}\n\nfunction match<R>(\n node: TrieNode<R>,\n urlParts: string[],\n index: number,\n): { route: R; params: Record<string, string | string[]> } | null {\n // All URL segments consumed\n if (index === urlParts.length) {\n // Exact match at this node\n if (node.route !== null) {\n return { route: node.route, params: Object.create(null) };\n }\n\n // Optional catch-all with 0 segments\n if (node.optionalCatchAllChild !== null) {\n const params: Record<string, string | string[]> = Object.create(null);\n params[node.optionalCatchAllChild.paramName] = [];\n return { route: node.optionalCatchAllChild.route, params };\n }\n\n return null;\n }\n\n const segment = urlParts[index];\n\n // 1. Try static child (highest priority)\n const staticChild = node.staticChildren.get(segment);\n if (staticChild) {\n const result = match(staticChild, urlParts, index + 1);\n if (result !== null) {\n return result;\n }\n }\n\n // 2. Try dynamic child (single segment)\n if (node.dynamicChild !== null) {\n const result = match(node.dynamicChild.node, urlParts, index + 1);\n if (result !== null) {\n result.params[node.dynamicChild.paramName] = segment;\n return result;\n }\n }\n\n // 3. Try catch-all (1+ remaining segments)\n if (node.catchAllChild !== null) {\n const remaining = urlParts.slice(index);\n const params: Record<string, string | string[]> = Object.create(null);\n params[node.catchAllChild.paramName] = remaining;\n return { route: node.catchAllChild.route, params };\n }\n\n // 4. Try optional catch-all (0+ remaining segments)\n if (node.optionalCatchAllChild !== null) {\n const remaining = urlParts.slice(index);\n const params: Record<string, string | string[]> = Object.create(null);\n params[node.optionalCatchAllChild.paramName] = remaining;\n return { route: node.optionalCatchAllChild.route, params };\n }\n\n return null;\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
//#region src/routing/route-validation.d.ts
|
|
1
2
|
/**
|
|
2
3
|
* Dynamic route validation adapted from Next.js' sorted-routes implementation.
|
|
3
4
|
* Source:
|
|
4
5
|
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/sorted-routes.ts
|
|
5
6
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
declare function patternToNextFormat(pattern: string): string;
|
|
8
|
+
declare function validateRoutePatterns(patterns: readonly string[]): void;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { patternToNextFormat, validateRoutePatterns };
|
|
8
11
|
//# sourceMappingURL=route-validation.d.ts.map
|
|
@@ -1,136 +1,104 @@
|
|
|
1
|
+
//#region src/routing/route-validation.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class UrlNode {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
let child = this.children.get(nextSegment);
|
|
86
|
-
if (!child) {
|
|
87
|
-
child = new UrlNode();
|
|
88
|
-
this.children.set(nextSegment, child);
|
|
89
|
-
}
|
|
90
|
-
child.insertSegments(urlPaths.slice(1), slugNames, isCatchAll);
|
|
91
|
-
}
|
|
92
|
-
assertOptionalCatchAllSpecificity(prefix = "/") {
|
|
93
|
-
if (!this.placeholder && this.optionalRestSlugName !== null) {
|
|
94
|
-
const route = prefix === "/" ? "/" : prefix.slice(0, -1);
|
|
95
|
-
throw new Error(`You cannot define a route with the same specificity as a optional catch-all route ("${route}" and "${route}[[...${this.optionalRestSlugName}]]").`);
|
|
96
|
-
}
|
|
97
|
-
for (const [segment, child] of this.children) {
|
|
98
|
-
const nextPrefixSegment = segment === "[]"
|
|
99
|
-
? `[${this.slugName}]`
|
|
100
|
-
: segment === "[...]"
|
|
101
|
-
? `[...${this.restSlugName}]`
|
|
102
|
-
: segment === "[[...]]"
|
|
103
|
-
? `[[...${this.optionalRestSlugName}]]`
|
|
104
|
-
: segment;
|
|
105
|
-
child.assertOptionalCatchAllSpecificity(`${prefix}${nextPrefixSegment}/`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
export function patternToNextFormat(pattern) {
|
|
110
|
-
if (pattern === "/")
|
|
111
|
-
return "/";
|
|
112
|
-
return pattern
|
|
113
|
-
.replace(/:([\w-]+)\+/g, "[...$1]")
|
|
114
|
-
.replace(/:([\w-]+)\*/g, "[[...$1]]")
|
|
115
|
-
.replace(/:([\w-]+)/g, "[$1]");
|
|
3
|
+
* Dynamic route validation adapted from Next.js' sorted-routes implementation.
|
|
4
|
+
* Source:
|
|
5
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/sorted-routes.ts
|
|
6
|
+
*/
|
|
7
|
+
var UrlNode = class UrlNode {
|
|
8
|
+
placeholder = true;
|
|
9
|
+
children = /* @__PURE__ */ new Map();
|
|
10
|
+
slugName = null;
|
|
11
|
+
restSlugName = null;
|
|
12
|
+
optionalRestSlugName = null;
|
|
13
|
+
insert(urlPath) {
|
|
14
|
+
this.insertSegments(urlPath.split("/").filter(Boolean), [], false);
|
|
15
|
+
}
|
|
16
|
+
insertSegments(urlPaths, slugNames, isCatchAll) {
|
|
17
|
+
if (urlPaths.length === 0) {
|
|
18
|
+
this.placeholder = false;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (isCatchAll) throw new Error("Catch-all must be the last part of the URL.");
|
|
22
|
+
let nextSegment = urlPaths[0];
|
|
23
|
+
if (nextSegment.startsWith("[") && nextSegment.endsWith("]")) {
|
|
24
|
+
let segmentName = nextSegment.slice(1, -1);
|
|
25
|
+
let isOptional = false;
|
|
26
|
+
if (segmentName.startsWith("[") && segmentName.endsWith("]")) {
|
|
27
|
+
segmentName = segmentName.slice(1, -1);
|
|
28
|
+
isOptional = true;
|
|
29
|
+
}
|
|
30
|
+
if (segmentName.startsWith("…")) throw new Error(`Detected a three-dot character ('…') at ('${segmentName}'). Did you mean ('...')?`);
|
|
31
|
+
if (segmentName.startsWith("...")) {
|
|
32
|
+
segmentName = segmentName.substring(3);
|
|
33
|
+
isCatchAll = true;
|
|
34
|
+
}
|
|
35
|
+
if (segmentName.startsWith("[") || segmentName.endsWith("]")) throw new Error(`Segment names may not start or end with extra brackets ('${segmentName}').`);
|
|
36
|
+
if (segmentName.startsWith(".")) throw new Error(`Segment names may not start with erroneous periods ('${segmentName}').`);
|
|
37
|
+
const handleSlug = (previousSlug, nextSlug) => {
|
|
38
|
+
if (previousSlug !== null && previousSlug !== nextSlug) throw new Error(`You cannot use different slug names for the same dynamic path ('${previousSlug}' !== '${nextSlug}').`);
|
|
39
|
+
for (const slug of slugNames) {
|
|
40
|
+
if (slug === nextSlug) throw new Error(`You cannot have the same slug name "${nextSlug}" repeat within a single dynamic path`);
|
|
41
|
+
if (slug.replace(/\W/g, "") === nextSegment.replace(/\W/g, "")) throw new Error(`You cannot have the slug names "${slug}" and "${nextSlug}" differ only by non-word symbols within a single dynamic path`);
|
|
42
|
+
}
|
|
43
|
+
slugNames.push(nextSlug);
|
|
44
|
+
};
|
|
45
|
+
if (isCatchAll) if (isOptional) {
|
|
46
|
+
if (this.restSlugName !== null) throw new Error(`You cannot use both an required and optional catch-all route at the same level ("[...${this.restSlugName}]" and "${urlPaths[0]}" ).`);
|
|
47
|
+
handleSlug(this.optionalRestSlugName, segmentName);
|
|
48
|
+
this.optionalRestSlugName = segmentName;
|
|
49
|
+
nextSegment = "[[...]]";
|
|
50
|
+
} else {
|
|
51
|
+
if (this.optionalRestSlugName !== null) throw new Error(`You cannot use both an optional and required catch-all route at the same level ("[[...${this.optionalRestSlugName}]]" and "${urlPaths[0]}").`);
|
|
52
|
+
handleSlug(this.restSlugName, segmentName);
|
|
53
|
+
this.restSlugName = segmentName;
|
|
54
|
+
nextSegment = "[...]";
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (isOptional) throw new Error(`Optional route parameters are not yet supported ("${urlPaths[0]}").`);
|
|
58
|
+
handleSlug(this.slugName, segmentName);
|
|
59
|
+
this.slugName = segmentName;
|
|
60
|
+
nextSegment = "[]";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let child = this.children.get(nextSegment);
|
|
64
|
+
if (!child) {
|
|
65
|
+
child = new UrlNode();
|
|
66
|
+
this.children.set(nextSegment, child);
|
|
67
|
+
}
|
|
68
|
+
child.insertSegments(urlPaths.slice(1), slugNames, isCatchAll);
|
|
69
|
+
}
|
|
70
|
+
assertOptionalCatchAllSpecificity(prefix = "/") {
|
|
71
|
+
if (!this.placeholder && this.optionalRestSlugName !== null) {
|
|
72
|
+
const route = prefix === "/" ? "/" : prefix.slice(0, -1);
|
|
73
|
+
throw new Error(`You cannot define a route with the same specificity as a optional catch-all route ("${route}" and "${route}[[...${this.optionalRestSlugName}]]").`);
|
|
74
|
+
}
|
|
75
|
+
for (const [segment, child] of this.children) {
|
|
76
|
+
const nextPrefixSegment = segment === "[]" ? `[${this.slugName}]` : segment === "[...]" ? `[...${this.restSlugName}]` : segment === "[[...]]" ? `[[...${this.optionalRestSlugName}]]` : segment;
|
|
77
|
+
child.assertOptionalCatchAllSpecificity(`${prefix}${nextPrefixSegment}/`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
function patternToNextFormat(pattern) {
|
|
82
|
+
if (pattern === "/") return "/";
|
|
83
|
+
return pattern.replace(/:([\w-]+)\+/g, "[...$1]").replace(/:([\w-]+)\*/g, "[[...$1]]").replace(/:([\w-]+)/g, "[$1]");
|
|
116
84
|
}
|
|
117
85
|
function normalizeRoutePattern(pattern) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return normalized === "" ? "/" : normalized;
|
|
86
|
+
if (pattern === "/") return "/";
|
|
87
|
+
const normalized = pattern.replace(/\/+$/, "");
|
|
88
|
+
return normalized === "" ? "/" : normalized;
|
|
122
89
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
root.assertOptionalCatchAllSpecificity();
|
|
90
|
+
function validateRoutePatterns(patterns) {
|
|
91
|
+
const root = new UrlNode();
|
|
92
|
+
const seenPatterns = /* @__PURE__ */ new Set();
|
|
93
|
+
for (const pattern of patterns) {
|
|
94
|
+
const normalizedPattern = normalizeRoutePattern(pattern);
|
|
95
|
+
if (seenPatterns.has(normalizedPattern)) throw new Error(`You cannot have two routes that resolve to the same path ("${normalizedPattern}").`);
|
|
96
|
+
seenPatterns.add(normalizedPattern);
|
|
97
|
+
root.insert(patternToNextFormat(normalizedPattern));
|
|
98
|
+
}
|
|
99
|
+
root.assertOptionalCatchAllSpecificity();
|
|
135
100
|
}
|
|
101
|
+
//#endregion
|
|
102
|
+
export { patternToNextFormat, validateRoutePatterns };
|
|
103
|
+
|
|
136
104
|
//# sourceMappingURL=route-validation.js.map
|