@wular/pnext 0.0.3 → 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 -1961
- 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 -1887
- 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} +152 -143
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +442 -186
- 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 +833 -848
- 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
package/src/compat/metadata.ts
CHANGED
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from '../types';
|
|
8
|
-
import { staticMetadataForPathFromFiles, type StaticMetadataFile } from '../routing/metadata';
|
|
9
|
-
import { coerceString } from '../render/metadata';
|
|
10
|
-
import { readSourceText } from '../resolve/source-text';
|
|
11
|
-
import { SPAN_TYPE, withChildSpan } from './otel/tracer';
|
|
12
|
-
import { settledPromise } from '../render/renderer';
|
|
1
|
+
import type { Metadata, MetadataOpenGraph, PageProps, RouteManifestEntry, Viewport } from '../types'
|
|
2
|
+
import { staticMetadataForPathFromFiles, type StaticMetadataFile } from '../routing/metadata-files'
|
|
3
|
+
import { coerceString } from '../render/metadata'
|
|
4
|
+
import { readSourceText } from '../resolve/source-text'
|
|
5
|
+
import { SPAN_TYPE, withChildSpan } from './otel/tracer'
|
|
6
|
+
import { settledPromise } from '../render/renderer'
|
|
13
7
|
import {
|
|
14
8
|
createVaryingParams,
|
|
15
9
|
createVaryingSearchParams,
|
|
16
10
|
getMetadataVaryParamsAccumulator,
|
|
17
11
|
varyTrackingInfo,
|
|
18
12
|
type VaryTrackingInfo,
|
|
19
|
-
} from './segment/vary-params'
|
|
13
|
+
} from './segment/vary-params'
|
|
20
14
|
|
|
21
15
|
type NextGenerateMetadata = (
|
|
22
16
|
props: Pick<PageProps, 'params' | 'searchParams'>,
|
|
23
17
|
parent: Promise<Metadata>,
|
|
24
|
-
) => Metadata | Promise<Metadata
|
|
18
|
+
) => Metadata | Promise<Metadata>
|
|
25
19
|
|
|
26
20
|
type NextGenerateViewport = (
|
|
27
21
|
props: Pick<PageProps, 'params' | 'searchParams'>,
|
|
28
|
-
) => Viewport | Promise<Viewport
|
|
22
|
+
) => Viewport | Promise<Viewport>
|
|
29
23
|
|
|
30
24
|
export async function readNextModuleMetadata(
|
|
31
25
|
module: Record<string, unknown>,
|
|
@@ -34,17 +28,17 @@ export async function readNextModuleMetadata(
|
|
|
34
28
|
modulePath?: string,
|
|
35
29
|
): Promise<Metadata | undefined> {
|
|
36
30
|
if (typeof module.generateMetadata === 'function') {
|
|
37
|
-
const generate = module.generateMetadata as NextGenerateMetadata
|
|
31
|
+
const generate = module.generateMetadata as NextGenerateMetadata
|
|
38
32
|
// `generateMetadata <page>` OTel span (ResolveMetadata.generateMetadata),
|
|
39
33
|
// named by the route-relative module path (e.g. `/app/[param]/layout`).
|
|
40
34
|
// Inert when otel-api is unavailable or no root span is open.
|
|
41
|
-
const headProps = headVaryTrackedProps(props)
|
|
35
|
+
const headProps = headVaryTrackedProps(props)
|
|
42
36
|
const run = () =>
|
|
43
37
|
generate(
|
|
44
38
|
{ params: headProps.params, searchParams: headProps.searchParams },
|
|
45
39
|
Promise.resolve(resolvedParentMetadata(parent)),
|
|
46
|
-
)
|
|
47
|
-
const name = metadataSpanName(modulePath)
|
|
40
|
+
)
|
|
41
|
+
const name = metadataSpanName(modulePath)
|
|
48
42
|
return await (name
|
|
49
43
|
? withChildSpan(
|
|
50
44
|
name,
|
|
@@ -52,9 +46,9 @@ export async function readNextModuleMetadata(
|
|
|
52
46
|
{ 'next.page': name.slice('generateMetadata '.length) },
|
|
53
47
|
run,
|
|
54
48
|
)
|
|
55
|
-
: run())
|
|
49
|
+
: run())
|
|
56
50
|
}
|
|
57
|
-
return module.metadata as Metadata | undefined
|
|
51
|
+
return module.metadata as Metadata | undefined
|
|
58
52
|
}
|
|
59
53
|
|
|
60
54
|
// Route-relative module path for a `generateMetadata` span name: an absolute `<root>/app/[param]/
|
|
@@ -62,12 +56,12 @@ export async function readNextModuleMetadata(
|
|
|
62
56
|
// relative path prefixed by the `/app` segment. Returns undefined when the path cannot be derived, in
|
|
63
57
|
// which case the span is skipped rather than failing.
|
|
64
58
|
function metadataSpanName(modulePath: string | undefined): string | undefined {
|
|
65
|
-
if (!modulePath) return undefined
|
|
66
|
-
const normalized = modulePath.replace(/\\/g, '/').replace(/\.[cm]?[jt]sx?$/, '')
|
|
59
|
+
if (!modulePath) return undefined
|
|
60
|
+
const normalized = modulePath.replace(/\\/g, '/').replace(/\.[cm]?[jt]sx?$/, '')
|
|
67
61
|
// Keep everything from the LAST `/app/` segment onward (handles src/app too).
|
|
68
|
-
const idx = normalized.lastIndexOf('/app/')
|
|
69
|
-
const rel = idx >= 0 ? normalized.slice(idx) : `/${normalized.replace(/^\/+/, '')}
|
|
70
|
-
return `generateMetadata ${rel}
|
|
62
|
+
const idx = normalized.lastIndexOf('/app/')
|
|
63
|
+
const rel = idx >= 0 ? normalized.slice(idx) : `/${normalized.replace(/^\/+/, '')}`
|
|
64
|
+
return `generateMetadata ${rel}`
|
|
71
65
|
}
|
|
72
66
|
|
|
73
67
|
export async function readNextModuleViewport(
|
|
@@ -75,13 +69,13 @@ export async function readNextModuleViewport(
|
|
|
75
69
|
props: PageProps,
|
|
76
70
|
): Promise<Viewport | undefined> {
|
|
77
71
|
if (typeof module.generateViewport === 'function') {
|
|
78
|
-
const headProps = headVaryTrackedProps(props)
|
|
72
|
+
const headProps = headVaryTrackedProps(props)
|
|
79
73
|
return (module.generateViewport as NextGenerateViewport)({
|
|
80
74
|
params: headProps.params,
|
|
81
75
|
searchParams: headProps.searchParams,
|
|
82
|
-
})
|
|
76
|
+
})
|
|
83
77
|
}
|
|
84
|
-
return module.viewport as Viewport | undefined
|
|
78
|
+
return module.viewport as Viewport | undefined
|
|
85
79
|
}
|
|
86
80
|
|
|
87
81
|
/**
|
|
@@ -95,14 +89,14 @@ export async function readNextModuleViewport(
|
|
|
95
89
|
* postpone machinery still sees it.
|
|
96
90
|
*/
|
|
97
91
|
function headVaryTrackedProps(props: PageProps): Pick<PageProps, 'params' | 'searchParams'> {
|
|
98
|
-
const head = getMetadataVaryParamsAccumulator()
|
|
99
|
-
if (!head) return { params: props.params, searchParams: props.searchParams }
|
|
92
|
+
const head = getMetadataVaryParamsAccumulator()
|
|
93
|
+
if (!head) return { params: props.params, searchParams: props.searchParams }
|
|
100
94
|
return {
|
|
101
95
|
params: retrackSettled(props.params, (raw, info) =>
|
|
102
96
|
createVaryingParams(head, raw, info.optionalCatchAllParam),
|
|
103
97
|
),
|
|
104
98
|
searchParams: retrackSettled(props.searchParams, raw => createVaryingSearchParams(head, raw)),
|
|
105
|
-
}
|
|
99
|
+
}
|
|
106
100
|
}
|
|
107
101
|
|
|
108
102
|
/**
|
|
@@ -114,29 +108,29 @@ function retrackSettled<T extends Record<string, unknown>>(
|
|
|
114
108
|
promise: Promise<T>,
|
|
115
109
|
wrap: (raw: T, info: VaryTrackingInfo) => T,
|
|
116
110
|
): Promise<T> {
|
|
117
|
-
const settled = promise as Promise<T> & { status?: string; value?: T }
|
|
118
|
-
if (settled.status !== 'fulfilled' || settled.value === undefined) return promise
|
|
119
|
-
const info = varyTrackingInfo(settled.value)
|
|
120
|
-
if (!info) return promise
|
|
121
|
-
return settledPromise(wrap(info.raw as T, info))
|
|
111
|
+
const settled = promise as Promise<T> & { status?: string; value?: T }
|
|
112
|
+
if (settled.status !== 'fulfilled' || settled.value === undefined) return promise
|
|
113
|
+
const info = varyTrackingInfo(settled.value)
|
|
114
|
+
if (!info) return promise
|
|
115
|
+
return settledPromise(wrap(info.raw as T, info))
|
|
122
116
|
}
|
|
123
117
|
|
|
124
118
|
export function hasRuntimeMetadata(module: Record<string, unknown>) {
|
|
125
|
-
return typeof module.generateMetadata === 'function'
|
|
119
|
+
return typeof module.generateMetadata === 'function'
|
|
126
120
|
}
|
|
127
121
|
|
|
128
122
|
export function shouldRenderMetadataInBody({
|
|
129
123
|
config,
|
|
130
124
|
request,
|
|
131
125
|
}: {
|
|
132
|
-
config: { htmlLimitedBots?: RegExp }
|
|
133
|
-
request?: Request
|
|
126
|
+
config: { htmlLimitedBots?: RegExp }
|
|
127
|
+
request?: Request
|
|
134
128
|
}) {
|
|
135
|
-
const userAgent = request?.headers.get('user-agent') ?? ''
|
|
129
|
+
const userAgent = request?.headers.get('user-agent') ?? ''
|
|
136
130
|
const limitedBot =
|
|
137
131
|
config.htmlLimitedBots ??
|
|
138
|
-
/Twitterbot|Slackbot|Bingbot|Discordbot|LinkedInBot|Google-PageRenderer|Chrome-Lighthouse|Lighthouse/i
|
|
139
|
-
return !limitedBot.test(userAgent)
|
|
132
|
+
/Twitterbot|Slackbot|Bingbot|Discordbot|LinkedInBot|Google-PageRenderer|Chrome-Lighthouse|Lighthouse/i
|
|
133
|
+
return !limitedBot.test(userAgent)
|
|
140
134
|
}
|
|
141
135
|
|
|
142
136
|
function resolvedParentMetadata(parent: Metadata): Metadata {
|
|
@@ -149,11 +143,11 @@ function resolvedParentMetadata(parent: Metadata): Metadata {
|
|
|
149
143
|
robots: parent.robots ?? {},
|
|
150
144
|
alternates: parent.alternates ?? {},
|
|
151
145
|
icons: parent.icons ?? {},
|
|
152
|
-
}
|
|
146
|
+
}
|
|
153
147
|
}
|
|
154
148
|
|
|
155
149
|
function resolvedParentOpenGraph(openGraph: MetadataOpenGraph | undefined): MetadataOpenGraph {
|
|
156
|
-
if (!openGraph) return {}
|
|
150
|
+
if (!openGraph) return {}
|
|
157
151
|
return {
|
|
158
152
|
...openGraph,
|
|
159
153
|
title:
|
|
@@ -167,12 +161,12 @@ function resolvedParentOpenGraph(openGraph: MetadataOpenGraph | undefined): Meta
|
|
|
167
161
|
: Array.isArray(openGraph.images)
|
|
168
162
|
? openGraph.images
|
|
169
163
|
: [openGraph.images],
|
|
170
|
-
}
|
|
164
|
+
}
|
|
171
165
|
}
|
|
172
166
|
|
|
173
167
|
function normalizeKeywordList(value: Metadata['keywords']): (string | number)[] | undefined {
|
|
174
|
-
if (value === undefined) return undefined
|
|
175
|
-
return Array.isArray(value) ? value : [value]
|
|
168
|
+
if (value === undefined) return undefined
|
|
169
|
+
return Array.isArray(value) ? value : [value]
|
|
176
170
|
}
|
|
177
171
|
|
|
178
172
|
export async function warnNextMetadataBuildIssues(
|
|
@@ -180,44 +174,44 @@ export async function warnNextMetadataBuildIssues(
|
|
|
180
174
|
routes: RouteManifestEntry[],
|
|
181
175
|
staticMetadataFiles: StaticMetadataFile[],
|
|
182
176
|
) {
|
|
183
|
-
const warned = new Set<string>()
|
|
177
|
+
const warned = new Set<string>()
|
|
184
178
|
// A route's own file plus its layout chain: on a 23-route app with one shell
|
|
185
179
|
// that is the same handful of layouts 23 times over. Each file's four verdicts
|
|
186
180
|
// are derived once and reused, and the reads come from the build's shared
|
|
187
181
|
// source cache (the route-fact walk has already read every one of them).
|
|
188
|
-
const facts = new Map<string, MetadataSourceFacts>()
|
|
182
|
+
const facts = new Map<string, MetadataSourceFacts>()
|
|
189
183
|
const factsFor = async (file: string) => {
|
|
190
|
-
let cached = facts.get(file)
|
|
184
|
+
let cached = facts.get(file)
|
|
191
185
|
if (!cached) {
|
|
192
|
-
cached = metadataSourceFacts(await readSourceTextOrEmpty(file))
|
|
193
|
-
facts.set(file, cached)
|
|
186
|
+
cached = metadataSourceFacts(await readSourceTextOrEmpty(file))
|
|
187
|
+
facts.set(file, cached)
|
|
194
188
|
}
|
|
195
|
-
return cached
|
|
196
|
-
}
|
|
189
|
+
return cached
|
|
190
|
+
}
|
|
197
191
|
for (const route of routes) {
|
|
198
|
-
if (route.kind !== 'page') continue
|
|
199
|
-
const routeFacts = await Promise.all(routeSourceFiles(appPath, route).map(factsFor))
|
|
200
|
-
const some = (pick: (fact: MetadataSourceFacts) => boolean) => routeFacts.some(pick)
|
|
192
|
+
if (route.kind !== 'page') continue
|
|
193
|
+
const routeFacts = await Promise.all(routeSourceFiles(appPath, route).map(factsFor))
|
|
194
|
+
const some = (pick: (fact: MetadataSourceFacts) => boolean) => routeFacts.some(pick)
|
|
201
195
|
if (some(fact => fact.themeColor)) {
|
|
202
196
|
warnOnce(
|
|
203
197
|
warned,
|
|
204
198
|
`themeColor:${route.route}`,
|
|
205
199
|
`Unsupported metadata themeColor is configured in metadata export in ${route.route || '/'}. Please move it to viewport\nRead more: https://nextjs.org/docs/app/api-reference/functions/generate-viewport`,
|
|
206
|
-
)
|
|
200
|
+
)
|
|
207
201
|
}
|
|
208
202
|
if (some(fact => fact.appleTouchFullscreen)) {
|
|
209
203
|
warnOnce(
|
|
210
204
|
warned,
|
|
211
205
|
'apple-touch-fullscreen',
|
|
212
206
|
'Unsupported metadata other.apple-touch-fullscreen is configured in metadata export. Use appleWebApp instead.',
|
|
213
|
-
)
|
|
207
|
+
)
|
|
214
208
|
}
|
|
215
209
|
if (some(fact => fact.appleTouchIconPrecomposed)) {
|
|
216
210
|
warnOnce(
|
|
217
211
|
warned,
|
|
218
212
|
'apple-touch-icon-precomposed',
|
|
219
213
|
'Unsupported metadata other.apple-touch-icon-precomposed is configured in metadata export. Use icons.apple instead.',
|
|
220
|
-
)
|
|
214
|
+
)
|
|
221
215
|
}
|
|
222
216
|
if (
|
|
223
217
|
!some(fact => fact.metadataBase) &&
|
|
@@ -227,22 +221,22 @@ export async function warnNextMetadataBuildIssues(
|
|
|
227
221
|
warned,
|
|
228
222
|
'metadataBase',
|
|
229
223
|
'metadataBase property in metadata export is not set for resolving social open graph or twitter images, using "http://localhost:3000". See https://nextjs.org/docs/app/api-reference/functions/generate-metadata#metadatabase',
|
|
230
|
-
)
|
|
224
|
+
)
|
|
231
225
|
}
|
|
232
226
|
}
|
|
233
227
|
}
|
|
234
228
|
|
|
235
229
|
/** The app-dir files whose metadata exports apply to this route. */
|
|
236
230
|
function routeSourceFiles(appPath: string, route: RouteManifestEntry) {
|
|
237
|
-
const root = `${appPath}
|
|
238
|
-
return route.sourceFiles.filter(file => file === appPath || file.startsWith(root))
|
|
231
|
+
const root = `${appPath}/`
|
|
232
|
+
return route.sourceFiles.filter(file => file === appPath || file.startsWith(root))
|
|
239
233
|
}
|
|
240
234
|
|
|
241
235
|
async function readSourceTextOrEmpty(file: string) {
|
|
242
236
|
try {
|
|
243
|
-
return await readSourceText(file)
|
|
237
|
+
return await readSourceText(file)
|
|
244
238
|
} catch {
|
|
245
|
-
return ''
|
|
239
|
+
return ''
|
|
246
240
|
}
|
|
247
241
|
}
|
|
248
242
|
|
|
@@ -252,11 +246,11 @@ async function readSourceTextOrEmpty(file: string) {
|
|
|
252
246
|
* nearly every file has none of these keys.
|
|
253
247
|
*/
|
|
254
248
|
interface MetadataSourceFacts {
|
|
255
|
-
themeColor: boolean
|
|
256
|
-
appleTouchFullscreen: boolean
|
|
257
|
-
appleTouchIconPrecomposed: boolean
|
|
258
|
-
metadataBase: boolean
|
|
259
|
-
relativeSocialImage: boolean
|
|
249
|
+
themeColor: boolean
|
|
250
|
+
appleTouchFullscreen: boolean
|
|
251
|
+
appleTouchIconPrecomposed: boolean
|
|
252
|
+
metadataBase: boolean
|
|
253
|
+
relativeSocialImage: boolean
|
|
260
254
|
}
|
|
261
255
|
|
|
262
256
|
function metadataSourceFacts(source: string): MetadataSourceFacts {
|
|
@@ -269,7 +263,7 @@ function metadataSourceFacts(source: string): MetadataSourceFacts {
|
|
|
269
263
|
/['"]apple-touch-icon-precomposed['"]/.test(source),
|
|
270
264
|
metadataBase: source.includes('metadataBase') && /\bmetadataBase\s*:/.test(source),
|
|
271
265
|
relativeSocialImage: hasRelativeSocialImage(source),
|
|
272
|
-
}
|
|
266
|
+
}
|
|
273
267
|
}
|
|
274
268
|
|
|
275
269
|
function routeUsesRelativeSocialImage(
|
|
@@ -277,19 +271,19 @@ function routeUsesRelativeSocialImage(
|
|
|
277
271
|
facts: MetadataSourceFacts[],
|
|
278
272
|
staticMetadataFiles: StaticMetadataFile[],
|
|
279
273
|
) {
|
|
280
|
-
if (facts.some(fact => fact.relativeSocialImage)) return true
|
|
281
|
-
if (route.params.length > 0) return false
|
|
282
|
-
const staticMetadata = staticMetadataForPathFromFiles(staticMetadataFiles, route.route)
|
|
283
|
-
return Boolean(staticMetadata.openGraphImage || staticMetadata.twitterImage)
|
|
274
|
+
if (facts.some(fact => fact.relativeSocialImage)) return true
|
|
275
|
+
if (route.params.length > 0) return false
|
|
276
|
+
const staticMetadata = staticMetadataForPathFromFiles(staticMetadataFiles, route.route)
|
|
277
|
+
return Boolean(staticMetadata.openGraphImage || staticMetadata.twitterImage)
|
|
284
278
|
}
|
|
285
279
|
|
|
286
280
|
function hasRelativeSocialImage(source: string) {
|
|
287
|
-
if (!source.includes('images')) return false
|
|
288
|
-
return /(?:openGraph|twitter)\s*:\s*\{[\s\S]*?\bimages\s*:\s*['"`](?:\/|\.\.?\/)/m.test(source)
|
|
281
|
+
if (!source.includes('images')) return false
|
|
282
|
+
return /(?:openGraph|twitter)\s*:\s*\{[\s\S]*?\bimages\s*:\s*['"`](?:\/|\.\.?\/)/m.test(source)
|
|
289
283
|
}
|
|
290
284
|
|
|
291
285
|
function warnOnce(warned: Set<string>, key: string, message: string) {
|
|
292
|
-
if (warned.has(key)) return
|
|
293
|
-
warned.add(key)
|
|
294
|
-
console.warn(message)
|
|
286
|
+
if (warned.has(key)) return
|
|
287
|
+
warned.add(key)
|
|
288
|
+
console.warn(message)
|
|
295
289
|
}
|
package/src/compat/next/cache.ts
CHANGED
|
@@ -10,22 +10,22 @@ import {
|
|
|
10
10
|
recordCacheNoStore,
|
|
11
11
|
recordCacheRevalidate,
|
|
12
12
|
recordCacheTags,
|
|
13
|
-
} from '../cache/revalidate'
|
|
14
|
-
import { recordUseCacheLife, recordUseCacheTags } from '../cache/use-cache'
|
|
15
|
-
import { currentRequest, getWorkUnit } from '../../request/context'
|
|
16
|
-
import { getNextConfig } from './config-loader'
|
|
17
|
-
import { isPrerendering, PostponeError } from '../../ppr'
|
|
18
|
-
export { io } from '../ppr/io'
|
|
13
|
+
} from '../cache/revalidate'
|
|
14
|
+
import { recordUseCacheLife, recordUseCacheTags } from '../cache/use-cache'
|
|
15
|
+
import { currentRequest, getWorkUnit } from '../../request/context'
|
|
16
|
+
import { getNextConfig } from './config-loader'
|
|
17
|
+
import { isPrerendering, PostponeError } from '../../render/ppr'
|
|
18
|
+
export { io } from '../ppr/io'
|
|
19
19
|
|
|
20
20
|
export function refresh() {
|
|
21
|
-
const phase = getWorkUnit()?.phase
|
|
21
|
+
const phase = getWorkUnit()?.phase
|
|
22
22
|
if (phase !== 'action' || insideDataCacheProducer()) {
|
|
23
|
-
throw new Error('refresh can only be called from within a Server Action')
|
|
23
|
+
throw new Error('refresh can only be called from within a Server Action')
|
|
24
24
|
}
|
|
25
|
-
bumpRevalidationEvent()
|
|
25
|
+
bumpRevalidationEvent()
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const unstable_refresh = refresh
|
|
28
|
+
export const unstable_refresh = refresh
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Revalidation is a side effect and must never run during a render or inside a cached function. At
|
|
@@ -34,38 +34,38 @@ export const unstable_refresh = refresh;
|
|
|
34
34
|
* (postpone). Actions, route handlers and after() are the supported call sites and pass through.
|
|
35
35
|
*/
|
|
36
36
|
function assertRevalidateOutsideRender(expression: string): void {
|
|
37
|
-
const route = currentRenderCacheMeta()?.route ?? '/'
|
|
37
|
+
const route = currentRenderCacheMeta()?.route ?? '/'
|
|
38
38
|
const suffix =
|
|
39
39
|
'which is unsupported. To ensure revalidation is performed consistently it must always ' +
|
|
40
40
|
'happen outside of renders and cached functions. See more info here: ' +
|
|
41
|
-
'https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering'
|
|
41
|
+
'https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering'
|
|
42
42
|
if (insideDataCacheProducer()) {
|
|
43
43
|
throw new Error(
|
|
44
44
|
insideUnstableCacheProducer()
|
|
45
45
|
? `Route ${route} used "${expression}" inside a function cached with "unstable_cache(...)" ${suffix}`
|
|
46
46
|
: `Route ${route} used "${expression}" inside a "use cache" ${suffix}`,
|
|
47
|
-
)
|
|
47
|
+
)
|
|
48
48
|
}
|
|
49
49
|
// Live request renders only: build prerenders (and their after() drains,
|
|
50
50
|
// which run with the work-unit phase still 'render') keep their existing
|
|
51
51
|
// skip-to-dynamic behavior rather than throwing here.
|
|
52
|
-
if (getWorkUnit()?.phase !== 'render' || isPrerendering()) return
|
|
53
|
-
throw new Error(`Route ${route} used "${expression}" during render ${suffix}`)
|
|
52
|
+
if (getWorkUnit()?.phase !== 'render' || isPrerendering()) return
|
|
53
|
+
throw new Error(`Route ${route} used "${expression}" during render ${suffix}`)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export function revalidatePath(path: string, type?: 'page' | 'layout') {
|
|
57
|
-
assertRevalidateOutsideRender(`revalidatePath ${path}`)
|
|
58
|
-
markPathRevalidated(path, type)
|
|
57
|
+
assertRevalidateOutsideRender(`revalidatePath ${path}`)
|
|
58
|
+
markPathRevalidated(path, type)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export function revalidateTag(tag: string, profile?: string | CacheLifeProfile) {
|
|
62
|
-
assertRevalidateOutsideRender(`revalidateTag ${tag}`)
|
|
62
|
+
assertRevalidateOutsideRender(`revalidateTag ${tag}`)
|
|
63
63
|
if (profile === undefined) {
|
|
64
64
|
console.warn(
|
|
65
65
|
'Warning: "revalidateTag" without the second argument is now deprecated. Use updateTag(tag) for read-your-writes semantics, or pass a cache profile (e.g. revalidateTag(tag, \'max\')).',
|
|
66
|
-
)
|
|
67
|
-
markTagRevalidated(tag)
|
|
68
|
-
return
|
|
66
|
+
)
|
|
67
|
+
markTagRevalidated(tag)
|
|
68
|
+
return
|
|
69
69
|
}
|
|
70
70
|
// A cache-life profile whose expiry has already elapsed (the built-in `expireNow`, or any profile with
|
|
71
71
|
// expire/revalidate 0) is an immediate hard expiry, not stale-while-revalidate: the next read must
|
|
@@ -74,39 +74,39 @@ export function revalidateTag(tag: string, profile?: string | CacheLifeProfile)
|
|
|
74
74
|
// The profile is either a cacheLife name or an inline `{ expire }` object. An unknown name is treated
|
|
75
75
|
// as immediate expiry too - Next only softens the invalidation when the profile RESOLVES to a nonzero
|
|
76
76
|
// expiry, so failing hard keeps revalidation observable.
|
|
77
|
-
const resolved = typeof profile === 'string' ? resolveCacheLifeProfile(profile) : profile
|
|
77
|
+
const resolved = typeof profile === 'string' ? resolveCacheLifeProfile(profile) : profile
|
|
78
78
|
if (!resolved || resolved.expire === 0 || resolved.revalidate === 0) {
|
|
79
|
-
markTagRevalidated(tag)
|
|
80
|
-
return
|
|
79
|
+
markTagRevalidated(tag)
|
|
80
|
+
return
|
|
81
81
|
}
|
|
82
|
-
markTagStale(tag)
|
|
82
|
+
markTagStale(tag)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/** updateTag is Server-Action-only in Next (read-your-writes expiry). */
|
|
86
86
|
export function updateTag(tag: string) {
|
|
87
|
-
const request = currentRequest()
|
|
87
|
+
const request = currentRequest()
|
|
88
88
|
const inServerAction =
|
|
89
|
-
request?.method?.toUpperCase?.() === 'POST' && Boolean(request.headers?.get?.('next-action'))
|
|
89
|
+
request?.method?.toUpperCase?.() === 'POST' && Boolean(request.headers?.get?.('next-action'))
|
|
90
90
|
if (!inServerAction) {
|
|
91
91
|
throw new Error(
|
|
92
92
|
'updateTag can only be called from within a Server Action. Use revalidateTag or expireTag for other contexts.',
|
|
93
|
-
)
|
|
93
|
+
)
|
|
94
94
|
}
|
|
95
|
-
markTagRevalidated(tag)
|
|
95
|
+
markTagRevalidated(tag)
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// Newer names for the same operations.
|
|
99
|
-
export const unstable_expirePath = revalidatePath
|
|
99
|
+
export const unstable_expirePath = revalidatePath
|
|
100
100
|
export const unstable_expireTag = (tag: string) => {
|
|
101
|
-
assertRevalidateOutsideRender(`expireTag ${tag}`)
|
|
102
|
-
markTagRevalidated(tag)
|
|
103
|
-
}
|
|
104
|
-
export const expirePath = revalidatePath
|
|
105
|
-
export const expireTag = unstable_expireTag
|
|
101
|
+
assertRevalidateOutsideRender(`expireTag ${tag}`)
|
|
102
|
+
markTagRevalidated(tag)
|
|
103
|
+
}
|
|
104
|
+
export const expirePath = revalidatePath
|
|
105
|
+
export const expireTag = unstable_expireTag
|
|
106
106
|
|
|
107
107
|
export interface UnstableCacheOptions {
|
|
108
|
-
revalidate?: number | false
|
|
109
|
-
tags?: string[]
|
|
108
|
+
revalidate?: number | false
|
|
109
|
+
tags?: string[]
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
export function unstable_cache<Args extends unknown[], Result>(
|
|
@@ -114,7 +114,7 @@ export function unstable_cache<Args extends unknown[], Result>(
|
|
|
114
114
|
keyParts?: string[],
|
|
115
115
|
options: UnstableCacheOptions = {},
|
|
116
116
|
): (...args: Args) => Promise<Result> {
|
|
117
|
-
const { revalidate } = options
|
|
117
|
+
const { revalidate } = options
|
|
118
118
|
if (
|
|
119
119
|
revalidate !== undefined &&
|
|
120
120
|
revalidate !== false &&
|
|
@@ -122,43 +122,43 @@ export function unstable_cache<Args extends unknown[], Result>(
|
|
|
122
122
|
) {
|
|
123
123
|
throw new Error(
|
|
124
124
|
`Invalid revalidate value "${String(revalidate)}" on "unstable_cache(${fn.toString().slice(0, 60)})", must be a non-negative number or false`,
|
|
125
|
-
)
|
|
125
|
+
)
|
|
126
126
|
}
|
|
127
|
-
const baseKey = keyParts?.length ? keyParts.join(',') : fn.toString()
|
|
127
|
+
const baseKey = keyParts?.length ? keyParts.join(',') : fn.toString()
|
|
128
128
|
return (...args: Args) => {
|
|
129
129
|
// Surrounding prerender/ISR writes inherit this entry's tags and TTL.
|
|
130
|
-
recordCacheTags(options.tags ?? [])
|
|
131
|
-
if (typeof options.revalidate === 'number') recordCacheRevalidate(options.revalidate)
|
|
130
|
+
recordCacheTags(options.tags ?? [])
|
|
131
|
+
if (typeof options.revalidate === 'number') recordCacheRevalidate(options.revalidate)
|
|
132
132
|
return cachedData(`${baseKey}:${JSON.stringify(args)}`, () => fn(...args), {
|
|
133
133
|
tags: options.tags,
|
|
134
134
|
revalidateSeconds: typeof options.revalidate === 'number' ? options.revalidate : undefined,
|
|
135
|
-
}) as Promise<Result
|
|
136
|
-
}
|
|
135
|
+
}) as Promise<Result>
|
|
136
|
+
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
/** Opt the surrounding render out of prebuilt static output (Next semantics). */
|
|
140
140
|
export function unstable_noStore() {
|
|
141
|
-
recordCacheNoStore()
|
|
141
|
+
recordCacheNoStore()
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
// 'use cache' directive companions: tag/bound the active use-cache entry
|
|
145
145
|
// (see cache/use-cache.ts) and propagate to the surrounding render meta so
|
|
146
146
|
// prerendered pages inherit tags/TTL.
|
|
147
147
|
export function cacheTag(...tags: string[]) {
|
|
148
|
-
recordUseCacheTags(tags)
|
|
149
|
-
recordCacheTags(tags)
|
|
148
|
+
recordUseCacheTags(tags)
|
|
149
|
+
recordCacheTags(tags)
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
// Built-in cacheLife profiles (Next defaults). `expire` defaults to the
|
|
153
153
|
// config's `expireTime` (one year) when a profile omits it; `stale` feeds the
|
|
154
154
|
// `x-nextjs-stale-time` header.
|
|
155
155
|
interface CacheLifeProfile {
|
|
156
|
-
revalidate?: number
|
|
157
|
-
expire?: number
|
|
158
|
-
stale?: number
|
|
156
|
+
revalidate?: number
|
|
157
|
+
expire?: number
|
|
158
|
+
stale?: number
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
const DEFAULT_EXPIRE_TIME = 31536000
|
|
161
|
+
const DEFAULT_EXPIRE_TIME = 31536000 // one year, Next's default expireTime.
|
|
162
162
|
|
|
163
163
|
const builtInCacheLifeProfiles: Record<string, CacheLifeProfile> = {
|
|
164
164
|
default: { revalidate: 900, expire: DEFAULT_EXPIRE_TIME, stale: 300 },
|
|
@@ -168,22 +168,21 @@ const builtInCacheLifeProfiles: Record<string, CacheLifeProfile> = {
|
|
|
168
168
|
days: { revalidate: 86400, expire: 604800, stale: 300 },
|
|
169
169
|
weeks: { revalidate: 604800, expire: 2592000, stale: 300 },
|
|
170
170
|
max: { revalidate: 2592000, expire: DEFAULT_EXPIRE_TIME, stale: 300 },
|
|
171
|
-
}
|
|
171
|
+
}
|
|
172
172
|
|
|
173
173
|
/** Resolve a cacheLife profile name against config `cacheLife` overrides. */
|
|
174
174
|
function resolveCacheLifeProfile(name: string): CacheLifeProfile | undefined {
|
|
175
|
-
const config = getNextConfig()
|
|
176
|
-
const overrides = config.cacheLife as Record<string, CacheLifeProfile> | undefined
|
|
177
|
-
const custom = overrides?.[name]
|
|
178
|
-
const builtIn = builtInCacheLifeProfiles[name]
|
|
179
|
-
if (!custom && !builtIn) return undefined
|
|
180
|
-
const expireTime =
|
|
181
|
-
|
|
182
|
-
const merged = { ...builtIn, ...custom };
|
|
175
|
+
const config = getNextConfig()
|
|
176
|
+
const overrides = config.cacheLife as Record<string, CacheLifeProfile> | undefined
|
|
177
|
+
const custom = overrides?.[name]
|
|
178
|
+
const builtIn = builtInCacheLifeProfiles[name]
|
|
179
|
+
if (!custom && !builtIn) return undefined
|
|
180
|
+
const expireTime = typeof config.expireTime === 'number' ? config.expireTime : DEFAULT_EXPIRE_TIME
|
|
181
|
+
const merged = { ...builtIn, ...custom }
|
|
183
182
|
return {
|
|
184
183
|
...merged,
|
|
185
184
|
expire: merged.expire ?? expireTime,
|
|
186
|
-
}
|
|
185
|
+
}
|
|
187
186
|
}
|
|
188
187
|
|
|
189
188
|
export function cacheLife(
|
|
@@ -196,16 +195,16 @@ export function cacheLife(
|
|
|
196
195
|
revalidate: typeof profile?.revalidate === 'number' ? profile.revalidate : undefined,
|
|
197
196
|
expire: typeof profile?.expire === 'number' ? profile.expire : undefined,
|
|
198
197
|
stale: typeof profile?.stale === 'number' ? profile.stale : undefined,
|
|
199
|
-
}
|
|
200
|
-
if (!resolved) return
|
|
201
|
-
const { revalidate, expire, stale } = resolved
|
|
198
|
+
}
|
|
199
|
+
if (!resolved) return
|
|
200
|
+
const { revalidate, expire, stale } = resolved
|
|
202
201
|
recordUseCacheLife({
|
|
203
202
|
...(revalidate !== undefined ? { revalidateSeconds: revalidate } : {}),
|
|
204
203
|
...(expire !== undefined ? { expireSeconds: expire } : {}),
|
|
205
204
|
...(stale !== undefined ? { staleSeconds: stale } : {}),
|
|
206
|
-
})
|
|
207
|
-
if (revalidate !== undefined) recordCacheRevalidate(revalidate)
|
|
208
|
-
if (isPrerendering() && stale === 0) throw new PostponeError('cacheLife')
|
|
205
|
+
})
|
|
206
|
+
if (revalidate !== undefined) recordCacheRevalidate(revalidate)
|
|
207
|
+
if (isPrerendering() && stale === 0) throw new PostponeError('cacheLife')
|
|
209
208
|
}
|
|
210
|
-
export const unstable_cacheTag = cacheTag
|
|
211
|
-
export const unstable_cacheLife = cacheLife
|
|
209
|
+
export const unstable_cacheTag = cacheTag
|
|
210
|
+
export const unstable_cacheLife = cacheLife
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
// The setter is invoked from the rewrite observer: when a same-origin rewrite fires, the original URL is
|
|
9
9
|
// remembered here. When nothing sets it, the hooks fall back to the request URL.
|
|
10
10
|
|
|
11
|
-
import { getWorkUnit } from '../../request/context'
|
|
11
|
+
import { getWorkUnit } from '../../request/context'
|
|
12
12
|
|
|
13
|
-
const CANONICAL_URL_KEY = Symbol.for('pnext.compat.navigation.canonicalUrl')
|
|
13
|
+
const CANONICAL_URL_KEY = Symbol.for('pnext.compat.navigation.canonicalUrl')
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Record the canonical (original, as-requested) URL for the active request,
|
|
@@ -18,18 +18,18 @@ const CANONICAL_URL_KEY = Symbol.for('pnext.compat.navigation.canonicalUrl');
|
|
|
18
18
|
* work unit. `from` is the URL the client asked for.
|
|
19
19
|
*/
|
|
20
20
|
export function recordCanonicalUrl(from: URL): void {
|
|
21
|
-
const unit = getWorkUnit()
|
|
22
|
-
if (!unit) return
|
|
23
|
-
const compat = (unit.compat ??= {})
|
|
21
|
+
const unit = getWorkUnit()
|
|
22
|
+
if (!unit) return
|
|
23
|
+
const compat = (unit.compat ??= {})
|
|
24
24
|
// Chained rewrites (middleware → next.config) record in sequence; the
|
|
25
25
|
// canonical URL is what the BROWSER asked for, so only the first wins — a
|
|
26
26
|
// later record's `from` is itself a rewrite destination.
|
|
27
|
-
if (typeof compat[CANONICAL_URL_KEY] === 'string') return
|
|
28
|
-
compat[CANONICAL_URL_KEY] = from.href
|
|
27
|
+
if (typeof compat[CANONICAL_URL_KEY] === 'string') return
|
|
28
|
+
compat[CANONICAL_URL_KEY] = from.href
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/** The canonical URL recorded for the active request, or undefined. */
|
|
32
32
|
export function canonicalUrlHref(): string | undefined {
|
|
33
|
-
const value = getWorkUnit()?.compat?.[CANONICAL_URL_KEY]
|
|
34
|
-
return typeof value === 'string' ? value : undefined
|
|
33
|
+
const value = getWorkUnit()?.compat?.[CANONICAL_URL_KEY]
|
|
34
|
+
return typeof value === 'string' ? value : undefined
|
|
35
35
|
}
|