@wular/pnext 0.0.4 → 0.0.6
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 +11 -11
- package/bin/pnext +1 -1
- package/config/lint/base.js +7 -7
- package/config/ts/base.json +2 -4
- package/config/ts/react.json +2 -6
- package/package.json +23 -2
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/css.md +13 -9
- package/reference/dev.md +1 -1
- package/reference/metadata.md +7 -7
- package/reference/navigation.md +35 -28
- package/reference/performance.md +70 -70
- package/reference/rendering.md +17 -17
- package/reference/routing.md +17 -17
- package/reference/typegen.md +12 -8
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +113 -109
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +49 -52
- package/src/api/navigation.ts +59 -58
- package/src/api/server.ts +152 -144
- package/src/api/suspense.ts +4 -4
- package/src/cli/adapters/vercel-warm.ts +126 -121
- package/src/cli/adapters/vercel.ts +437 -443
- package/src/cli/analyze.ts +333 -144
- package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
- package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
- package/src/cli/build.ts +976 -978
- package/src/cli/create.ts +71 -63
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +88 -85
- package/src/cli/migrate/package-json.ts +73 -71
- package/src/cli/migrate/report.ts +32 -33
- package/src/cli/migrate/{index.ts → run.ts} +48 -49
- package/src/cli/migrate/scan.ts +46 -46
- package/src/cli/migrate/spinner.ts +9 -9
- package/src/cli/migrate/tsconfig.ts +35 -35
- package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
- package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
- package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
- package/src/cli/start.ts +65 -66
- package/src/{typegen.ts → cli/typegen.ts} +59 -59
- package/src/client/build.ts +794 -768
- package/src/client/chunk-fold.ts +245 -240
- package/src/client/{paths.ts → chunk-name.ts} +6 -6
- package/src/client/entry.ts +162 -147
- package/src/client/prebuilt.ts +231 -223
- package/src/client/profile.ts +29 -29
- package/src/client/react-compiler.ts +20 -15
- package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
- package/src/client/reference-stub.ts +51 -51
- package/src/client/reference.ts +19 -19
- package/src/{api → client}/router/events.ts +17 -17
- package/src/{api → client}/router/history.ts +16 -16
- package/src/{api → client}/router/hub.ts +52 -53
- package/src/{api/router.ts → client/router/index.ts} +61 -60
- package/src/{api → client}/router/policies.ts +24 -24
- package/src/{api → client}/router/runtime.ts +1988 -1992
- package/src/{api → client}/router/types.ts +93 -98
- package/src/compat/actions/client-plugin.ts +42 -43
- package/src/compat/actions/client-stub.ts +14 -14
- package/src/compat/actions/{action-client.ts → client.ts} +194 -193
- package/src/compat/actions/config.ts +63 -64
- package/src/compat/actions/detect.ts +68 -68
- package/src/compat/actions/discovery.ts +105 -105
- package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
- package/src/compat/actions/early-submit.ts +1 -1
- package/src/compat/actions/endpoint.ts +198 -198
- package/src/compat/actions/extensions.ts +811 -0
- package/src/compat/actions/flight.ts +23 -23
- package/src/compat/actions/form-state.ts +34 -34
- package/src/compat/actions/hoist.ts +382 -236
- package/src/compat/actions/ids.ts +7 -12
- package/src/compat/actions/index.ts +8 -8
- package/src/compat/actions/instances.ts +46 -46
- package/src/compat/actions/origin.ts +47 -48
- package/src/compat/actions/protocol.ts +22 -22
- package/src/compat/actions/registry.ts +19 -19
- package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
- package/src/compat/actions/rewrite.ts +125 -125
- package/src/compat/actions/{action-router.ts → router.ts} +10 -10
- package/src/compat/actions/serve.ts +132 -136
- package/src/compat/actions/server-tag.ts +4 -4
- package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
- package/src/compat/actions/unrecognized-error.ts +4 -4
- package/src/compat/{index.ts → aliases.ts} +112 -109
- package/src/compat/bundler/bun-externals.ts +18 -18
- package/src/compat/bundler/cjs-exports.ts +271 -223
- package/src/compat/bundler/config.ts +116 -111
- package/src/compat/bundler/externals.ts +12 -12
- package/src/compat/bundler/import-meta-url.ts +19 -19
- package/src/compat/bundler/modularize-imports.ts +36 -33
- package/src/compat/bundler/new-url-asset.ts +22 -24
- package/src/compat/bundler/optimize-package-imports.ts +111 -107
- package/src/compat/bundler/polyfill.ts +28 -28
- package/src/compat/bundler/react-compiler.ts +35 -29
- package/src/compat/bundler/react-profiler.tsx +11 -11
- package/src/compat/bundler/relay-transform.ts +48 -47
- package/src/compat/bundler/require-context.ts +119 -113
- package/src/compat/bundler/resolve-extensions.ts +19 -19
- package/src/compat/bundler/source-cache.ts +25 -25
- package/src/compat/bundler/static-imports.ts +7 -7
- package/src/compat/bundler/symlink-imports.ts +46 -46
- package/src/compat/bundler/tsconfig-paths.ts +13 -15
- package/src/compat/bundler/wasm.ts +58 -60
- package/src/compat/bundler/webpack-loaders.ts +254 -241
- package/src/compat/bundler/worker.ts +101 -104
- package/src/compat/cache/build-flags.ts +29 -29
- package/src/compat/cache/build-prerender-errors.ts +40 -44
- package/src/compat/cache/custom-handler.ts +60 -53
- package/src/compat/cache/fetch-patch.ts +240 -240
- package/src/compat/cache/handler.ts +27 -31
- package/src/compat/cache/modern-handler.ts +148 -126
- package/src/compat/cache/resume-data-cache.ts +47 -45
- package/src/compat/cache/revalidate.ts +233 -232
- package/src/compat/cache/runtime-error.ts +35 -35
- package/src/compat/cache/use-cache-transform.ts +442 -417
- package/src/compat/cache/use-cache.ts +650 -614
- package/src/compat/cache-control.ts +140 -142
- package/src/compat/client/base-path.ts +21 -20
- package/src/compat/client/css-order.ts +18 -18
- package/src/compat/client/errors/bare-boundary.ts +11 -11
- package/src/compat/client/errors/control-flow.ts +23 -23
- package/src/compat/client/errors/error-boundary.ts +61 -61
- package/src/compat/client/errors/global-error.ts +101 -91
- package/src/compat/client/errors/install.ts +71 -72
- package/src/compat/client/errors/lazy.ts +23 -23
- package/src/compat/client/errors/primitive-throw.ts +47 -45
- package/src/compat/client/errors/soft-refresh.ts +4 -4
- package/src/compat/client/link-status.ts +33 -33
- package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
- package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
- package/src/compat/client/navigation-scroll.ts +63 -63
- package/src/compat/client/optimistic-routing.ts +93 -88
- package/src/compat/client/prefetch-cache.ts +23 -24
- package/src/compat/client/route-announcer.ts +35 -35
- package/src/compat/client/segment-cache-policy.ts +20 -20
- package/src/compat/client/segment-cache.ts +309 -315
- package/src/compat/client/segment-prefetch.ts +127 -132
- package/src/compat/client/trailing-slash.ts +5 -4
- package/src/compat/css/chunking.ts +113 -116
- package/src/compat/css/inline-css.ts +21 -21
- package/src/compat/css/lightningcss.ts +37 -38
- package/src/compat/css/modules.ts +161 -175
- package/src/compat/css/nonce.ts +7 -7
- package/src/compat/css/sass-plugin.ts +18 -21
- package/src/compat/css/sass.ts +150 -152
- package/src/compat/css/styled-jsx-runtime.ts +27 -27
- package/src/compat/css/styled-jsx.ts +21 -21
- package/src/compat/edge-runtime.ts +27 -27
- package/src/compat/{adapter → export}/build-complete.ts +72 -75
- package/src/compat/export/client.ts +29 -31
- package/src/compat/export/{index.ts → emit.ts} +111 -110
- package/src/compat/export/standalone.ts +62 -54
- package/src/compat/image-optimizer/cache.ts +51 -49
- package/src/compat/image-optimizer/detect.ts +52 -52
- package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
- package/src/compat/image-optimizer/source.ts +77 -80
- package/src/compat/lifecycle/after-scope.ts +26 -26
- package/src/compat/lifecycle/after.ts +48 -45
- package/src/compat/lifecycle/error-funnel.ts +98 -102
- package/src/compat/lifecycle/error-serialize.ts +30 -26
- package/src/compat/lifecycle/error-ui.ts +67 -32
- package/src/compat/lifecycle/instrumentation-client.ts +36 -38
- package/src/compat/lifecycle/instrumentation.ts +85 -85
- package/src/compat/lifecycle/node-console.ts +11 -11
- package/src/compat/lifecycle/testmode.ts +160 -132
- package/src/compat/mdx/compile.ts +60 -57
- package/src/compat/mdx/plugin.ts +11 -11
- package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
- package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
- package/src/compat/metadata.ts +75 -81
- package/src/compat/next/cache.ts +68 -69
- package/src/compat/next/canonical-url.ts +9 -9
- package/src/compat/next/client-cache.ts +19 -19
- package/src/compat/next/client-navigation.ts +112 -116
- package/src/compat/next/client-only.ts +1 -1
- package/src/compat/next/client-script.tsx +99 -93
- package/src/compat/next/client-server.ts +10 -10
- package/src/compat/next/config-loader.ts +176 -173
- package/src/compat/next/config.ts +7 -7
- package/src/compat/next/constants.cjs +6 -6
- package/src/compat/next/constants.ts +6 -6
- package/src/compat/next/custom-server.ts +26 -24
- package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
- package/src/compat/next/dynamic.tsx +21 -18
- package/src/compat/next/error.tsx +52 -52
- package/src/compat/next/font/cache.ts +74 -74
- package/src/compat/next/font/google.ts +2 -2
- package/src/compat/next/font/index.ts +1 -1
- package/src/compat/next/font/local.ts +3 -3
- package/src/compat/next/font/runtime-client.ts +17 -15
- package/src/compat/next/font/runtime.ts +443 -408
- package/src/compat/next/font/shared.ts +120 -108
- package/src/compat/next/form.tsx +63 -63
- package/src/compat/next/head.tsx +2 -2
- package/src/compat/next/headers.ts +103 -95
- package/src/compat/next/image/client.tsx +220 -0
- package/src/compat/next/image/config.ts +56 -58
- package/src/compat/next/image/optimizer.ts +40 -36
- package/src/compat/next/image/patterns.ts +37 -40
- package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
- package/src/compat/next/image/shared.ts +65 -57
- package/src/compat/next/image/static-metadata.ts +98 -107
- package/src/compat/next/image/validate.ts +79 -88
- package/src/compat/next/image.tsx +19 -23
- package/src/compat/next/index.ts +1 -1
- package/src/compat/next/legacy-image.tsx +59 -60
- package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
- package/src/compat/next/link.tsx +158 -158
- package/src/compat/next/navigation.cjs +12 -3
- package/src/compat/next/navigation.ts +48 -50
- package/src/compat/next/offline.ts +27 -27
- package/src/compat/next/og.ts +121 -124
- package/src/compat/next/preferred-region.ts +13 -14
- package/src/compat/next/redirects.ts +58 -56
- package/src/compat/next/resource-hints.ts +73 -76
- package/src/compat/next/rewrites.ts +130 -133
- package/src/compat/next/root-params.ts +45 -45
- package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
- package/src/compat/next/router.cjs +4 -2
- package/src/compat/next/router.ts +58 -61
- package/src/compat/next/script.tsx +108 -108
- package/src/compat/next/server-only.ts +1 -1
- package/src/compat/next/server.ts +19 -19
- package/src/compat/next/svgr.ts +18 -17
- package/src/compat/next/telemetry.ts +24 -24
- package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
- package/src/compat/next/user-agent.ts +53 -49
- package/src/compat/next/web-vitals.ts +22 -24
- package/src/compat/otel/api.ts +41 -41
- package/src/compat/otel/client-trace-metadata.ts +25 -27
- package/src/compat/otel/fetch-span.ts +29 -29
- package/src/compat/otel/tracer.ts +331 -331
- package/src/compat/pages/api.ts +456 -0
- package/src/compat/pages/client-plugin.ts +36 -36
- package/src/compat/pages/router-state.ts +34 -34
- package/src/compat/pages/{index.ts → router.ts} +130 -135
- package/src/compat/ppr/io.ts +12 -12
- package/src/compat/ppr/missing-root-params.ts +34 -38
- package/src/compat/ppr/root-params-scan.ts +66 -66
- package/src/compat/ppr/root-params-transform.ts +24 -26
- package/src/compat/ppr/root-params.ts +30 -30
- package/src/compat/ppr/segment-config-incompat.ts +6 -7
- package/src/compat/protocol.ts +71 -70
- package/src/compat/react/action-state.ts +47 -48
- package/src/compat/react/client-lite.ts +15 -15
- package/src/compat/react/client.ts +4 -4
- package/src/compat/react/compiler-runtime.ts +11 -11
- package/src/compat/react/dom-client.ts +44 -44
- package/src/compat/react/dom-react-server.ts +10 -16
- package/src/compat/react/dom-server.ts +10 -10
- package/src/compat/react/dom.ts +52 -52
- package/src/compat/react/hooks-extra.ts +34 -35
- package/src/compat/react/parity.ts +64 -61
- package/src/compat/react/preact.ts +81 -82
- package/src/compat/react/react-server.ts +28 -28
- package/src/compat/react/router-shim.ts +1 -1
- package/src/compat/react/server-component-use.ts +8 -8
- package/src/compat/react/server-inserted-html.ts +30 -31
- package/src/compat/react/server.ts +53 -55
- package/src/compat/react/use.ts +32 -32
- package/src/compat/react/view-transition.ts +20 -20
- package/src/compat/register/actions.ts +35 -824
- package/src/compat/register/boot.ts +41 -41
- package/src/compat/register/build-tier.ts +5 -5
- package/src/compat/register/build.ts +74 -70
- package/src/compat/register/bundler.ts +161 -156
- package/src/compat/register/cache.ts +20 -20
- package/src/compat/register/client-errors.ts +3 -3
- package/src/compat/register/config.ts +6 -6
- package/src/compat/register/css-extras.ts +30 -34
- package/src/compat/register/edge-runtime.ts +3 -3
- package/src/compat/register/errors.ts +10 -12
- package/src/compat/register/export.ts +16 -16
- package/src/compat/register/font.ts +11 -11
- package/src/compat/register/hooks.ts +2 -2
- package/src/compat/register/image.ts +40 -40
- package/src/compat/register/index.ts +59 -62
- package/src/compat/register/instrumentation-client.ts +10 -10
- package/src/compat/register/lifecycle.ts +25 -28
- package/src/compat/register/mdx.ts +10 -10
- package/src/compat/register/middleware.ts +226 -16
- package/src/compat/register/otel.ts +80 -88
- package/src/compat/register/pages-api.ts +10 -463
- package/src/compat/register/ppr.ts +16 -16
- package/src/compat/register/protocol.ts +17 -18
- package/src/compat/register/proxy.ts +49 -51
- package/src/compat/register/render.ts +79 -76
- package/src/compat/register/routing.ts +162 -159
- package/src/compat/register/segment.ts +24 -1897
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +69 -69
- package/src/css/build.ts +230 -227
- package/src/css/postcss.ts +79 -80
- package/src/css/worker.ts +14 -15
- package/src/dev/client-actions.ts +10 -10
- package/src/dev/client-chunk-store.ts +27 -27
- package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
- package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
- package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
- package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
- package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
- package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
- package/src/dev/server.ts +804 -820
- package/src/env.ts +46 -43
- package/src/extensions.ts +491 -478
- package/src/index.ts +8 -8
- package/src/internal.ts +20 -23
- package/src/{islands → render}/boundary-error.ts +3 -3
- package/src/render/hooks.ts +71 -71
- package/src/render/island-context.ts +14 -14
- package/src/render/metadata.ts +310 -310
- package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
- package/src/{ppr.ts → render/ppr.ts} +244 -245
- package/src/render/renderer.ts +2076 -2082
- package/src/render/resource-hints.ts +16 -17
- package/src/render/slots.tsx +224 -235
- package/src/{islands → render}/static-children.ts +9 -12
- package/src/{islands → render}/static-slots.ts +37 -37
- package/src/{cache/context.ts → request/cache.ts} +20 -20
- package/src/request/context.ts +107 -107
- package/src/{dynamic/source.ts → resolve/dynamic.ts} +139 -139
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +318 -296
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +69 -70
- package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
- package/src/{proxy.ts → routing/proxy.ts} +306 -312
- package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
- package/src/routing/routes.ts +827 -815
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +952 -0
- package/src/{dev → runtime}/module-cache.ts +309 -287
- package/src/{dev → runtime}/module-generations.ts +9 -9
- package/src/{dev → runtime}/module-transform.ts +81 -72
- package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
- package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
- package/src/runtime/vendor.ts +425 -404
- package/src/styles.d.ts +9 -0
- package/src/types.ts +320 -335
- package/src/utils/ansi.ts +5 -5
- package/src/utils/{source.ts → code.ts} +15 -12
- package/src/utils/content-type.ts +3 -3
- package/src/utils/decode.ts +2 -2
- package/src/utils/dev-profile.ts +13 -13
- package/src/utils/error-log.ts +6 -6
- package/src/utils/esbuild.ts +18 -18
- package/src/utils/fs-cache.ts +13 -13
- package/src/utils/fs.ts +57 -49
- package/src/utils/html.ts +20 -24
- package/src/utils/native-require.ts +8 -8
- package/src/utils/serialize.ts +139 -146
- package/src/utils/verbose.ts +18 -18
- package/src/cli/analyze-print.ts +0 -181
- package/src/compat/middleware/manifest.ts +0 -210
- package/src/compat/next/image-client.tsx +0 -215
- package/src/compat/next/link-usage.ts +0 -29
- package/src/css/index.ts +0 -2
- package/src/render/index.ts +0 -1
- package/src/style-modules.d.ts +0 -9
|
@@ -1,83 +1,84 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { nextCompatEnabled } from '../compat'
|
|
4
|
-
import type { ResolvedConfig } from '../config'
|
|
5
|
-
import type { ResponseFinalizer, ResponseFinalizerContext } from '../extensions'
|
|
6
|
-
import { getNextConfig } from './next/config-loader'
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { nextCompatEnabled } from '../compat/aliases'
|
|
4
|
+
import type { ResolvedConfig } from '../config'
|
|
5
|
+
import type { ResponseFinalizer, ResponseFinalizerContext } from '../extensions'
|
|
6
|
+
import { getNextConfig } from './next/config-loader'
|
|
7
|
+
import { escapeRegex } from '../utils/code'
|
|
7
8
|
import {
|
|
8
9
|
evaluateConditions,
|
|
9
10
|
parseConditions,
|
|
10
11
|
substitute,
|
|
11
12
|
type RewriteCondition,
|
|
12
13
|
type RewriteRequestContext,
|
|
13
|
-
} from './next/rewrites'
|
|
14
|
+
} from './next/rewrites'
|
|
14
15
|
|
|
15
|
-
const DEFAULT_EXPIRE_TIME = 31536000
|
|
16
|
+
const DEFAULT_EXPIRE_TIME = 31536000
|
|
16
17
|
|
|
17
18
|
interface HeaderRule {
|
|
18
|
-
regex: RegExp
|
|
19
|
-
paramNames: string[]
|
|
20
|
-
headers: [string, string][]
|
|
21
|
-
has: RewriteCondition[]
|
|
22
|
-
missing: RewriteCondition[]
|
|
19
|
+
regex: RegExp
|
|
20
|
+
paramNames: string[]
|
|
21
|
+
headers: [string, string][]
|
|
22
|
+
has: RewriteCondition[]
|
|
23
|
+
missing: RewriteCondition[]
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
interface HeaderEntry {
|
|
26
|
-
source?: string
|
|
27
|
-
headers?: unknown
|
|
28
|
-
has?: unknown
|
|
29
|
-
missing?: unknown
|
|
27
|
+
source?: string
|
|
28
|
+
headers?: unknown
|
|
29
|
+
has?: unknown
|
|
30
|
+
missing?: unknown
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
interface RevalidateRule {
|
|
33
|
-
regex: RegExp
|
|
34
|
-
revalidateSeconds: number
|
|
34
|
+
regex: RegExp
|
|
35
|
+
revalidateSeconds: number
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
interface ConfigHeader {
|
|
38
|
-
key?: unknown
|
|
39
|
-
value?: unknown
|
|
39
|
+
key?: unknown
|
|
40
|
+
value?: unknown
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
export function cacheControlFinalizers(config: ResolvedConfig): ResponseFinalizer[] {
|
|
43
|
-
if (!nextCompatEnabled(config)) return []
|
|
44
|
+
if (!nextCompatEnabled(config)) return []
|
|
44
45
|
|
|
45
|
-
let rules: Promise<HeaderRule[]> | undefined
|
|
46
|
-
let pagesRevalidateRules: RevalidateRule[] | undefined
|
|
46
|
+
let rules: Promise<HeaderRule[]> | undefined
|
|
47
|
+
let pagesRevalidateRules: RevalidateRule[] | undefined
|
|
47
48
|
const finalizer: ResponseFinalizer = async ctx => {
|
|
48
|
-
rules ??= loadHeaderRules()
|
|
49
|
-
applyConfigHeaders(ctx, await rules)
|
|
50
|
-
pagesRevalidateRules ??= loadPagesRevalidateRules(config.root)
|
|
51
|
-
applyDefaultIsrHeader(ctx, pagesRevalidateRules)
|
|
52
|
-
}
|
|
53
|
-
return [finalizer]
|
|
49
|
+
rules ??= loadHeaderRules()
|
|
50
|
+
applyConfigHeaders(ctx, await rules)
|
|
51
|
+
pagesRevalidateRules ??= loadPagesRevalidateRules(config.root)
|
|
52
|
+
applyDefaultIsrHeader(ctx, pagesRevalidateRules)
|
|
53
|
+
}
|
|
54
|
+
return [finalizer]
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
async function loadHeaderRules(): Promise<HeaderRule[]> {
|
|
57
|
-
const producer = getNextConfig().headers
|
|
58
|
-
if (typeof producer !== 'function') return []
|
|
58
|
+
const producer = getNextConfig().headers
|
|
59
|
+
if (typeof producer !== 'function') return []
|
|
59
60
|
|
|
60
|
-
let entries: unknown
|
|
61
|
+
let entries: unknown
|
|
61
62
|
try {
|
|
62
|
-
entries = await (producer as () => unknown)()
|
|
63
|
+
entries = await (producer as () => unknown)()
|
|
63
64
|
} catch {
|
|
64
|
-
return []
|
|
65
|
+
return []
|
|
65
66
|
}
|
|
66
|
-
if (!Array.isArray(entries)) return []
|
|
67
|
+
if (!Array.isArray(entries)) return []
|
|
67
68
|
|
|
68
|
-
const rules: HeaderRule[] = []
|
|
69
|
+
const rules: HeaderRule[] = []
|
|
69
70
|
for (const entry of entries as HeaderEntry[]) {
|
|
70
|
-
if (!entry?.source || !Array.isArray(entry.headers)) continue
|
|
71
|
-
const compiled = compileHeaderSource(entry.source)
|
|
72
|
-
if (!compiled) continue
|
|
73
|
-
const has = parseConditions(entry.has)
|
|
74
|
-
const missing = parseConditions(entry.missing)
|
|
75
|
-
if (!has || !missing) continue
|
|
76
|
-
const headers = headerPairs(entry.headers)
|
|
77
|
-
if (headers.length === 0) continue
|
|
78
|
-
rules.push({ ...compiled, headers, has, missing })
|
|
71
|
+
if (!entry?.source || !Array.isArray(entry.headers)) continue
|
|
72
|
+
const compiled = compileHeaderSource(entry.source)
|
|
73
|
+
if (!compiled) continue
|
|
74
|
+
const has = parseConditions(entry.has)
|
|
75
|
+
const missing = parseConditions(entry.missing)
|
|
76
|
+
if (!has || !missing) continue
|
|
77
|
+
const headers = headerPairs(entry.headers)
|
|
78
|
+
if (headers.length === 0) continue
|
|
79
|
+
rules.push({ ...compiled, headers, has, missing })
|
|
79
80
|
}
|
|
80
|
-
return rules
|
|
81
|
+
return rules
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
/**
|
|
@@ -87,86 +88,86 @@ async function loadHeaderRules(): Promise<HeaderRule[]> {
|
|
|
87
88
|
* path-to-regexp treats those as literals. Raw regex bodies still only appear inside `:param(...)`.
|
|
88
89
|
*/
|
|
89
90
|
function compileHeaderSource(source: string): { regex: RegExp; paramNames: string[] } | null {
|
|
90
|
-
const paramNames: string[] = []
|
|
91
|
-
const parts: string[] = []
|
|
91
|
+
const paramNames: string[] = []
|
|
92
|
+
const parts: string[] = []
|
|
92
93
|
for (const segment of source.split('/').filter(Boolean)) {
|
|
93
|
-
const custom = /^:([A-Za-z_$][\w$]*)\((.*)\)$/.exec(segment)
|
|
94
|
+
const custom = /^:([A-Za-z_$][\w$]*)\((.*)\)$/.exec(segment)
|
|
94
95
|
if (custom?.[1] !== undefined && custom[2] !== undefined) {
|
|
95
|
-
paramNames.push(custom[1])
|
|
96
|
-
parts.push(`(${custom[2]})`)
|
|
97
|
-
continue
|
|
96
|
+
paramNames.push(custom[1])
|
|
97
|
+
parts.push(`(${custom[2]})`)
|
|
98
|
+
continue
|
|
98
99
|
}
|
|
99
|
-
const catchAll = /^:([A-Za-z_$][\w$]*)[*+]$/.exec(segment)
|
|
100
|
+
const catchAll = /^:([A-Za-z_$][\w$]*)[*+]$/.exec(segment)
|
|
100
101
|
if (catchAll?.[1]) {
|
|
101
|
-
paramNames.push(catchAll[1])
|
|
102
|
-
parts.push('(.*)')
|
|
103
|
-
continue
|
|
102
|
+
paramNames.push(catchAll[1])
|
|
103
|
+
parts.push('(.*)')
|
|
104
|
+
continue
|
|
104
105
|
}
|
|
105
|
-
const optional = /^:([A-Za-z_$][\w$]*)\?$/.exec(segment)
|
|
106
|
+
const optional = /^:([A-Za-z_$][\w$]*)\?$/.exec(segment)
|
|
106
107
|
if (optional?.[1]) {
|
|
107
|
-
paramNames.push(optional[1])
|
|
108
|
-
parts.push('([^/]*)')
|
|
109
|
-
continue
|
|
108
|
+
paramNames.push(optional[1])
|
|
109
|
+
parts.push('([^/]*)')
|
|
110
|
+
continue
|
|
110
111
|
}
|
|
111
|
-
const param = /^:([A-Za-z_$][\w$]*)$/.exec(segment)
|
|
112
|
+
const param = /^:([A-Za-z_$][\w$]*)$/.exec(segment)
|
|
112
113
|
if (param?.[1]) {
|
|
113
|
-
paramNames.push(param[1])
|
|
114
|
-
parts.push('([^/]+)')
|
|
115
|
-
continue
|
|
114
|
+
paramNames.push(param[1])
|
|
115
|
+
parts.push('([^/]+)')
|
|
116
|
+
continue
|
|
116
117
|
}
|
|
117
118
|
// Plain literal segment: escape regex-special characters so `.` etc. match
|
|
118
119
|
// literally rather than acting as regex metacharacters.
|
|
119
|
-
parts.push(segment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
120
|
+
parts.push(segment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
120
121
|
}
|
|
121
|
-
return { regex: new RegExp(`^/${parts.join('/')}/?$`), paramNames }
|
|
122
|
+
return { regex: new RegExp(`^/${parts.join('/')}/?$`), paramNames }
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
function headerPairs(headers: unknown[]): [string, string][] {
|
|
125
|
-
const pairs: [string, string][] = []
|
|
126
|
+
const pairs: [string, string][] = []
|
|
126
127
|
for (const header of headers as ConfigHeader[]) {
|
|
127
|
-
if (typeof header?.key !== 'string' || typeof header.value !== 'string') continue
|
|
128
|
-
pairs.push([header.key, header.value])
|
|
128
|
+
if (typeof header?.key !== 'string' || typeof header.value !== 'string') continue
|
|
129
|
+
pairs.push([header.key, header.value])
|
|
129
130
|
}
|
|
130
|
-
return pairs
|
|
131
|
+
return pairs
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
function applyConfigHeaders(ctx: ResponseFinalizerContext, rules: readonly HeaderRule[]): void {
|
|
134
|
-
if (rules.length === 0) return
|
|
135
|
-
const url = ctx.request.url
|
|
135
|
+
if (rules.length === 0) return
|
|
136
|
+
const url = ctx.request.url
|
|
136
137
|
const requestCtx: RewriteRequestContext = {
|
|
137
138
|
host: url.host,
|
|
138
139
|
headers: ctx.request.headers,
|
|
139
140
|
cookies: parseCookieHeader(ctx.request.headers.get('cookie')),
|
|
140
141
|
query: url.searchParams,
|
|
141
|
-
}
|
|
142
|
+
}
|
|
142
143
|
|
|
143
144
|
// Config `Set-Cookie` headers must be appended (each entry is its own header,
|
|
144
145
|
// never overwriting) and must precede the response's own Set-Cookie headers —
|
|
145
146
|
// Next applies config headers at the router layer before the route's own
|
|
146
147
|
// cookies (set-cookies suite asserts [...nextConfigHeaders, ...cookies]).
|
|
147
|
-
const configSetCookies: string[] = []
|
|
148
|
+
const configSetCookies: string[] = []
|
|
148
149
|
for (const rule of rules) {
|
|
149
|
-
const match = rule.regex.exec(url.pathname)
|
|
150
|
-
if (!match) continue
|
|
151
|
-
const params: Record<string, string> = {}
|
|
150
|
+
const match = rule.regex.exec(url.pathname)
|
|
151
|
+
if (!match) continue
|
|
152
|
+
const params: Record<string, string> = {}
|
|
152
153
|
rule.paramNames.forEach((name, index) => {
|
|
153
|
-
params[name] = match[index + 1] ?? ''
|
|
154
|
-
})
|
|
155
|
-
const conditionParams = evaluateConditions(rule, requestCtx)
|
|
156
|
-
if (conditionParams === null) continue
|
|
157
|
-
Object.assign(params, conditionParams)
|
|
154
|
+
params[name] = match[index + 1] ?? ''
|
|
155
|
+
})
|
|
156
|
+
const conditionParams = evaluateConditions(rule, requestCtx)
|
|
157
|
+
if (conditionParams === null) continue
|
|
158
|
+
Object.assign(params, conditionParams)
|
|
158
159
|
for (const [key, value] of rule.headers) {
|
|
159
|
-
const resolved = substitute(value, params).pathname
|
|
160
|
-
if (key.toLowerCase() === 'set-cookie') configSetCookies.push(resolved)
|
|
161
|
-
else ctx.headers.set(key, resolved)
|
|
160
|
+
const resolved = substitute(value, params).pathname
|
|
161
|
+
if (key.toLowerCase() === 'set-cookie') configSetCookies.push(resolved)
|
|
162
|
+
else ctx.headers.set(key, resolved)
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
if (configSetCookies.length > 0) {
|
|
165
166
|
const existing =
|
|
166
|
-
(ctx.headers as Headers & { getSetCookie?: () => string[] }).getSetCookie?.() ?? []
|
|
167
|
-
ctx.headers.delete('set-cookie')
|
|
168
|
-
for (const cookie of configSetCookies) ctx.headers.append('set-cookie', cookie)
|
|
169
|
-
for (const cookie of existing) ctx.headers.append('set-cookie', cookie)
|
|
167
|
+
(ctx.headers as Headers & { getSetCookie?: () => string[] }).getSetCookie?.() ?? []
|
|
168
|
+
ctx.headers.delete('set-cookie')
|
|
169
|
+
for (const cookie of configSetCookies) ctx.headers.append('set-cookie', cookie)
|
|
170
|
+
for (const cookie of existing) ctx.headers.append('set-cookie', cookie)
|
|
170
171
|
}
|
|
171
172
|
}
|
|
172
173
|
|
|
@@ -176,94 +177,91 @@ function applyDefaultIsrHeader(
|
|
|
176
177
|
): void {
|
|
177
178
|
const pagesRevalidateSeconds = pagesRevalidateRules.find(rule =>
|
|
178
179
|
rule.regex.test(ctx.request.url.pathname),
|
|
179
|
-
)?.revalidateSeconds
|
|
180
|
-
const existing = ctx.headers.get('cache-control')
|
|
180
|
+
)?.revalidateSeconds
|
|
181
|
+
const existing = ctx.headers.get('cache-control')
|
|
181
182
|
// An RSC payload is never browser-cacheable: the flight response embeds the
|
|
182
183
|
// render's data, so a cached copy replays stale content after a revalidation
|
|
183
184
|
// (actions "should invalidate client cache when path is revalidated"). Match
|
|
184
185
|
// the RSC document path in register-segment, which stamps `private, no-store`.
|
|
185
186
|
if (isRscPayload(ctx)) {
|
|
186
187
|
if (existing === null || isBrowserCacheable(existing)) {
|
|
187
|
-
ctx.headers.set('cache-control', 'private, no-store')
|
|
188
|
+
ctx.headers.set('cache-control', 'private, no-store')
|
|
188
189
|
}
|
|
189
|
-
return
|
|
190
|
+
return
|
|
190
191
|
}
|
|
191
|
-
if (existing && (pagesRevalidateSeconds === undefined || existing !== 'no-store')) return
|
|
192
|
+
if (existing && (pagesRevalidateSeconds === undefined || existing !== 'no-store')) return
|
|
192
193
|
const revalidateSeconds =
|
|
193
|
-
pagesRevalidateSeconds ??
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
const expireTime
|
|
198
|
-
|
|
199
|
-
const swr = Math.max(0, expireTime - revalidateSeconds);
|
|
200
|
-
ctx.headers.set('cache-control', `s-maxage=${revalidateSeconds}, stale-while-revalidate=${swr}`);
|
|
194
|
+
pagesRevalidateSeconds ?? (ctx.routeMode === 'isr' ? ctx.hints?.revalidateSeconds : undefined)
|
|
195
|
+
if (typeof revalidateSeconds !== 'number' || revalidateSeconds <= 0) return
|
|
196
|
+
const config = getNextConfig()
|
|
197
|
+
const expireTime = typeof config.expireTime === 'number' ? config.expireTime : DEFAULT_EXPIRE_TIME
|
|
198
|
+
const swr = Math.max(0, expireTime - revalidateSeconds)
|
|
199
|
+
ctx.headers.set('cache-control', `s-maxage=${revalidateSeconds}, stale-while-revalidate=${swr}`)
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
/** A flight response: core's `data` route kind, or an `_rsc` cache-busted URL. */
|
|
204
203
|
function isRscPayload(ctx: ResponseFinalizerContext): boolean {
|
|
205
|
-
return ctx.routeKind === 'data' || ctx.request.url.searchParams.has('_rsc')
|
|
204
|
+
return ctx.routeKind === 'data' || ctx.request.url.searchParams.has('_rsc')
|
|
206
205
|
}
|
|
207
206
|
|
|
208
207
|
/** True for a cache-control a browser may reuse (no `no-store`/`no-cache`). */
|
|
209
208
|
function isBrowserCacheable(value: string): boolean {
|
|
210
|
-
return !/\bno-store\b|\bno-cache\b/i.test(value)
|
|
209
|
+
return !/\bno-store\b|\bno-cache\b/i.test(value)
|
|
211
210
|
}
|
|
212
211
|
|
|
213
212
|
function loadPagesRevalidateRules(root: string): RevalidateRule[] {
|
|
214
|
-
const pagesDir = path.join(root, 'pages')
|
|
215
|
-
if (!existsSync(pagesDir)) return []
|
|
216
|
-
const rules: RevalidateRule[] = []
|
|
213
|
+
const pagesDir = path.join(root, 'pages')
|
|
214
|
+
if (!existsSync(pagesDir)) return []
|
|
215
|
+
const rules: RevalidateRule[] = []
|
|
217
216
|
for (const file of walkFiles(pagesDir)) {
|
|
218
|
-
const source = readFileSync(file, 'utf8')
|
|
219
|
-
if (!/\bgetStaticProps\b/.test(source)) continue
|
|
220
|
-
const match = /\brevalidate\s*:\s*(\d+)/.exec(source)
|
|
221
|
-
if (!match?.[1]) continue
|
|
222
|
-
const regex = pagesRouteRegex(path.relative(pagesDir, file))
|
|
223
|
-
if (!regex) continue
|
|
224
|
-
rules.push({ regex, revalidateSeconds: Number(match[1]) })
|
|
217
|
+
const source = readFileSync(file, 'utf8')
|
|
218
|
+
if (!/\bgetStaticProps\b/.test(source)) continue
|
|
219
|
+
const match = /\brevalidate\s*:\s*(\d+)/.exec(source)
|
|
220
|
+
if (!match?.[1]) continue
|
|
221
|
+
const regex = pagesRouteRegex(path.relative(pagesDir, file))
|
|
222
|
+
if (!regex) continue
|
|
223
|
+
rules.push({ regex, revalidateSeconds: Number(match[1]) })
|
|
225
224
|
}
|
|
226
|
-
return rules
|
|
225
|
+
return rules
|
|
227
226
|
}
|
|
228
227
|
|
|
229
228
|
function walkFiles(dir: string): string[] {
|
|
230
|
-
const files: string[] = []
|
|
229
|
+
const files: string[] = []
|
|
231
230
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
232
|
-
const file = path.join(dir, entry.name)
|
|
233
|
-
if (entry.isDirectory()) files.push(...walkFiles(file))
|
|
234
|
-
else if (/\.(?:tsx|ts|jsx|js|mjs)$/.test(entry.name)) files.push(file)
|
|
231
|
+
const file = path.join(dir, entry.name)
|
|
232
|
+
if (entry.isDirectory()) files.push(...walkFiles(file))
|
|
233
|
+
else if (/\.(?:tsx|ts|jsx|js|mjs)$/.test(entry.name)) files.push(file)
|
|
235
234
|
}
|
|
236
|
-
return files
|
|
235
|
+
return files
|
|
237
236
|
}
|
|
238
237
|
|
|
239
238
|
function pagesRouteRegex(relative: string): RegExp | undefined {
|
|
240
|
-
const withoutExt = relative
|
|
241
|
-
|
|
242
|
-
|
|
239
|
+
const withoutExt = relative
|
|
240
|
+
.replace(/\.(?:tsx|ts|jsx|js|mjs)$/, '')
|
|
241
|
+
.split(path.sep)
|
|
242
|
+
.join('/')
|
|
243
|
+
const route = withoutExt === 'index' ? '' : withoutExt.replace(/\/index$/, '')
|
|
244
|
+
const parts = route.split('/').filter(Boolean)
|
|
243
245
|
const pattern = parts
|
|
244
246
|
.map(part => {
|
|
245
|
-
if (/^\[\[\.\.\.[^\]]+\]\]$/.test(part)) return '(?:/.*)?'
|
|
246
|
-
if (/^\[\.\.\.[^\]]+\]$/.test(part)) return '/.+'
|
|
247
|
-
if (/^\[[^\]]+\]$/.test(part)) return '/[^/]+'
|
|
248
|
-
return `/${escapeRegex(part)}
|
|
247
|
+
if (/^\[\[\.\.\.[^\]]+\]\]$/.test(part)) return '(?:/.*)?'
|
|
248
|
+
if (/^\[\.\.\.[^\]]+\]$/.test(part)) return '/.+'
|
|
249
|
+
if (/^\[[^\]]+\]$/.test(part)) return '/[^/]+'
|
|
250
|
+
return `/${escapeRegex(part)}`
|
|
249
251
|
})
|
|
250
|
-
.join('')
|
|
251
|
-
return new RegExp(`^${pattern || '/'}\\/?$`)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function escapeRegex(value: string): string {
|
|
255
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
252
|
+
.join('')
|
|
253
|
+
return new RegExp(`^${pattern || '/'}\\/?$`)
|
|
256
254
|
}
|
|
257
255
|
|
|
258
256
|
function parseCookieHeader(header: string | null): Record<string, string> {
|
|
259
|
-
const cookies: Record<string, string> = {}
|
|
260
|
-
if (!header) return cookies
|
|
257
|
+
const cookies: Record<string, string> = {}
|
|
258
|
+
if (!header) return cookies
|
|
261
259
|
for (const part of header.split(';')) {
|
|
262
|
-
const index = part.indexOf('=')
|
|
263
|
-
if (index === -1) continue
|
|
264
|
-
const name = part.slice(0, index).trim()
|
|
265
|
-
if (!name) continue
|
|
266
|
-
cookies[name] = decodeURIComponent(part.slice(index + 1).trim())
|
|
260
|
+
const index = part.indexOf('=')
|
|
261
|
+
if (index === -1) continue
|
|
262
|
+
const name = part.slice(0, index).trim()
|
|
263
|
+
if (!name) continue
|
|
264
|
+
cookies[name] = decodeURIComponent(part.slice(index + 1).trim())
|
|
267
265
|
}
|
|
268
|
-
return cookies
|
|
266
|
+
return cookies
|
|
269
267
|
}
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
declare global {
|
|
12
12
|
interface Window {
|
|
13
|
-
__PNEXT_BASE_PATH__?: string
|
|
13
|
+
__PNEXT_BASE_PATH__?: string
|
|
14
14
|
}
|
|
15
|
-
var __PNEXT_BASE_PATH__: string | undefined
|
|
15
|
+
var __PNEXT_BASE_PATH__: string | undefined
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -23,8 +23,8 @@ declare global {
|
|
|
23
23
|
* config loader, so this stays safe to ship to the browser.
|
|
24
24
|
*/
|
|
25
25
|
export function basePath(): string {
|
|
26
|
-
if (process.browser || typeof window !== 'undefined') return window.__PNEXT_BASE_PATH__ ?? ''
|
|
27
|
-
return globalThis.__PNEXT_BASE_PATH__ ?? ''
|
|
26
|
+
if (process.browser || typeof window !== 'undefined') return window.__PNEXT_BASE_PATH__ ?? ''
|
|
27
|
+
return globalThis.__PNEXT_BASE_PATH__ ?? ''
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -34,21 +34,21 @@ export function basePath(): string {
|
|
|
34
34
|
* no-basePath app is always a no-op.
|
|
35
35
|
*/
|
|
36
36
|
export function addBasePath(path: string): string {
|
|
37
|
-
const base = basePath()
|
|
38
|
-
if (!base) return path
|
|
39
|
-
if (!path.startsWith('/') || path.startsWith('//')) return path
|
|
40
|
-
if (path === '/') return base
|
|
41
|
-
if (path === base || path.startsWith(`${base}/`)) return path
|
|
42
|
-
return `${base}${path}
|
|
37
|
+
const base = basePath()
|
|
38
|
+
if (!base) return path
|
|
39
|
+
if (!path.startsWith('/') || path.startsWith('//')) return path
|
|
40
|
+
if (path === '/') return base
|
|
41
|
+
if (path === base || path.startsWith(`${base}/`)) return path
|
|
42
|
+
return `${base}${path}`
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/** Strip the configured basePath prefix from an in-app path (inverse of addBasePath). */
|
|
46
46
|
export function stripBasePath(path: string): string {
|
|
47
|
-
const base = basePath()
|
|
48
|
-
if (!base) return path
|
|
49
|
-
if (path === base) return '/'
|
|
50
|
-
if (path.startsWith(`${base}/`)) return path.slice(base.length)
|
|
51
|
-
return path
|
|
47
|
+
const base = basePath()
|
|
48
|
+
if (!base) return path
|
|
49
|
+
if (path === base) return '/'
|
|
50
|
+
if (path.startsWith(`${base}/`)) return path.slice(base.length)
|
|
51
|
+
return path
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/**
|
|
@@ -56,9 +56,10 @@ export function stripBasePath(path: string): string {
|
|
|
56
56
|
* hard-navigate to it (a `basePath:false` target). Always false when no basePath is configured.
|
|
57
57
|
*/
|
|
58
58
|
export function isOutsideBasePath(url: URL): boolean {
|
|
59
|
-
const base = basePath()
|
|
60
|
-
if (!base) return false
|
|
61
|
-
if ((process.browser || typeof window !== 'undefined') && url.origin !== window.location.origin)
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
const base = basePath()
|
|
60
|
+
if (!base) return false
|
|
61
|
+
if ((process.browser || typeof window !== 'undefined') && url.origin !== window.location.origin)
|
|
62
|
+
return false
|
|
63
|
+
const path = url.pathname
|
|
64
|
+
return path !== base && !path.startsWith(`${base}/`)
|
|
64
65
|
}
|
|
@@ -2,35 +2,35 @@
|
|
|
2
2
|
// Shared links otherwise retain their old position while newly-needed links
|
|
3
3
|
// append, which reverses ties in the CSS cascade after a route transition.
|
|
4
4
|
export function reconcileNextStylesheets(incoming: Document) {
|
|
5
|
-
const order = new Map<string, number>()
|
|
5
|
+
const order = new Map<string, number>()
|
|
6
6
|
for (const link of incoming.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"][href]')) {
|
|
7
|
-
const href = absoluteHref(link)
|
|
8
|
-
if (href && nextStylesheet(href) && !order.has(href)) order.set(href, order.size)
|
|
7
|
+
const href = absoluteHref(link)
|
|
8
|
+
if (href && nextStylesheet(href) && !order.has(href)) order.set(href, order.size)
|
|
9
9
|
}
|
|
10
|
-
if (order.size < 2) return
|
|
10
|
+
if (order.size < 2) return
|
|
11
11
|
|
|
12
|
-
const current = [
|
|
13
|
-
|
|
14
|
-
)
|
|
15
|
-
if (current.length < 2) return
|
|
12
|
+
const current = [
|
|
13
|
+
...document.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"][href]'),
|
|
14
|
+
].filter(link => order.has(link.href))
|
|
15
|
+
if (current.length < 2) return
|
|
16
16
|
|
|
17
|
-
const rank = (link: HTMLLinkElement) => order.get(link.href) ?? 0
|
|
18
|
-
if (current.every((link, index) => index === 0 || rank(current[index - 1]!) <= rank(link))) return
|
|
17
|
+
const rank = (link: HTMLLinkElement) => order.get(link.href) ?? 0
|
|
18
|
+
if (current.every((link, index) => index === 0 || rank(current[index - 1]!) <= rank(link))) return
|
|
19
19
|
|
|
20
|
-
const sorted = [...current].sort((left, right) => rank(left) - rank(right))
|
|
21
|
-
let previous = sorted[0]
|
|
20
|
+
const sorted = [...current].sort((left, right) => rank(left) - rank(right))
|
|
21
|
+
let previous = sorted[0]!
|
|
22
22
|
for (const link of sorted.slice(1)) {
|
|
23
|
-
if (previous.nextSibling !== link) previous.after(link)
|
|
24
|
-
previous = link
|
|
23
|
+
if (previous.nextSibling !== link) previous.after(link)
|
|
24
|
+
previous = link
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function absoluteHref(link: HTMLLinkElement) {
|
|
29
|
-
const href = link.getAttribute('href')
|
|
30
|
-
return href ? new URL(href, location.href).href : undefined
|
|
29
|
+
const href = link.getAttribute('href')
|
|
30
|
+
return href ? new URL(href, location.href).href : undefined
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function nextStylesheet(href: string) {
|
|
34
|
-
const url = new URL(href, location.href)
|
|
35
|
-
return url.origin === location.origin && url.pathname.startsWith('/assets/')
|
|
34
|
+
const url = new URL(href, location.href)
|
|
35
|
+
return url.origin === location.origin && url.pathname.startsWith('/assets/')
|
|
36
36
|
}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
// Bare tier of the client error boundary (see ./error-boundary): a route with no error.*/not-found.*
|
|
2
2
|
// still needs one so hydration throws reach the window last resort (not preact's diff) and primitive
|
|
3
3
|
// throws keep their raw value en route to global-error. Exactly those two behaviors, ~0.5 KB raw.
|
|
4
|
-
import { Component, type ComponentChildren } from 'preact'
|
|
5
|
-
import { normalizeBoundaryError } from './primitive-throw'
|
|
4
|
+
import { Component, type ComponentChildren } from 'preact'
|
|
5
|
+
import { normalizeBoundaryError } from './primitive-throw'
|
|
6
6
|
|
|
7
7
|
interface BareBoundaryState {
|
|
8
|
-
error: unknown
|
|
9
|
-
hasError: boolean
|
|
8
|
+
error: unknown
|
|
9
|
+
hasError: boolean
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export class BareErrorBoundary extends Component<{ children?: unknown }, BareBoundaryState> {
|
|
13
|
-
state: BareBoundaryState = { error: null, hasError: false }
|
|
13
|
+
state: BareBoundaryState = { error: null, hasError: false }
|
|
14
14
|
|
|
15
15
|
static getDerivedStateFromError(error: unknown): BareBoundaryState {
|
|
16
|
-
return { error: normalizeBoundaryError(error), hasError: true }
|
|
16
|
+
return { error: normalizeBoundaryError(error), hasError: true }
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
render(): ComponentChildren {
|
|
20
|
-
if (!this.state.hasError) return this.props.children
|
|
21
|
-
const { error } = this.state
|
|
20
|
+
if (!this.state.hasError) return this.props.children
|
|
21
|
+
const { error } = this.state
|
|
22
22
|
// A primitive would arrive at the window handler as a synthesized Error, so
|
|
23
23
|
// escalate it to global-error directly (deferred tier) with its raw value.
|
|
24
24
|
// Everything else re-throws: unmarked, so the window last resort still sees
|
|
25
25
|
// a genuinely uncaught error and drives it.
|
|
26
26
|
if (error === null || typeof error !== 'object') {
|
|
27
|
-
void import('./global-error').then(module => module.escalateToGlobalError(error))
|
|
28
|
-
return null
|
|
27
|
+
void import('./global-error').then(module => module.escalateToGlobalError(error))
|
|
28
|
+
return null
|
|
29
29
|
}
|
|
30
|
-
throw error as Error
|
|
30
|
+
throw error as Error
|
|
31
31
|
}
|
|
32
32
|
}
|