@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
|
@@ -5,24 +5,24 @@
|
|
|
5
5
|
// wrapper also serializes the state into a `<script type="application/json">` node so the browser-side
|
|
6
6
|
// shim reads the same values after hydration and after soft navigations.
|
|
7
7
|
|
|
8
|
-
import type { RouteParamValue } from '../../types'
|
|
8
|
+
import type { RouteParamValue } from '../../types'
|
|
9
9
|
|
|
10
10
|
export interface PagesRouterSsrState {
|
|
11
11
|
/** Pages-route pattern, e.g. `/blog/[slug]`. */
|
|
12
|
-
pathname: string
|
|
12
|
+
pathname: string
|
|
13
13
|
/** The as-requested URL (path + original search), pre-rewrite. */
|
|
14
|
-
asPath: string
|
|
14
|
+
asPath: string
|
|
15
15
|
/** Rewrite-destination search params merged with dynamic route params. */
|
|
16
|
-
query: Record<string, string | string[]
|
|
16
|
+
query: Record<string, string | string[]>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const STATE_KEY = Symbol.for('pnext.pagesRouterState')
|
|
20
|
-
const REQUEST_STORAGE = Symbol.for('pnext.requestStorage')
|
|
21
|
-
const WORK_UNIT_STORAGE = Symbol.for('pnext.workUnitStorage')
|
|
22
|
-
const CANONICAL_URL_KEY = Symbol.for('pnext.compat.navigation.canonicalUrl')
|
|
19
|
+
const STATE_KEY = Symbol.for('pnext.pagesRouterState')
|
|
20
|
+
const REQUEST_STORAGE = Symbol.for('pnext.requestStorage')
|
|
21
|
+
const WORK_UNIT_STORAGE = Symbol.for('pnext.workUnitStorage')
|
|
22
|
+
const CANONICAL_URL_KEY = Symbol.for('pnext.compat.navigation.canonicalUrl')
|
|
23
23
|
|
|
24
24
|
interface StorageLike {
|
|
25
|
-
getStore(): Record<PropertyKey, unknown> | undefined
|
|
25
|
+
getStore(): Record<PropertyKey, unknown> | undefined
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// All reads go through the globalThis-anchored storages (never module-local
|
|
@@ -30,21 +30,21 @@ interface StorageLike {
|
|
|
30
30
|
// their own compiled copy of this module, and only the anchored instances are
|
|
31
31
|
// shared between them.
|
|
32
32
|
function anchoredScope(key: symbol): Record<PropertyKey, unknown> | undefined {
|
|
33
|
-
const storage = (globalThis as Record<PropertyKey, unknown>)[key] as StorageLike | undefined
|
|
34
|
-
return storage?.getStore?.()
|
|
33
|
+
const storage = (globalThis as Record<PropertyKey, unknown>)[key] as StorageLike | undefined
|
|
34
|
+
return storage?.getStore?.()
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function currentRequestUrl(): string | undefined {
|
|
38
|
-
const scope = anchoredScope(REQUEST_STORAGE)
|
|
39
|
-
const request = scope?.request as { url?: string } | undefined
|
|
40
|
-
return typeof request?.url === 'string' ? request.url : undefined
|
|
38
|
+
const scope = anchoredScope(REQUEST_STORAGE)
|
|
39
|
+
const request = scope?.request as { url?: string } | undefined
|
|
40
|
+
return typeof request?.url === 'string' ? request.url : undefined
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function canonicalHref(): string | undefined {
|
|
44
|
-
const unit = anchoredScope(WORK_UNIT_STORAGE)
|
|
45
|
-
const compat = unit?.compat as Record<symbol, unknown> | undefined
|
|
46
|
-
const value = compat?.[CANONICAL_URL_KEY]
|
|
47
|
-
return typeof value === 'string' ? value : undefined
|
|
44
|
+
const unit = anchoredScope(WORK_UNIT_STORAGE)
|
|
45
|
+
const compat = unit?.compat as Record<symbol, unknown> | undefined
|
|
46
|
+
const value = compat?.[CANONICAL_URL_KEY]
|
|
47
|
+
return typeof value === 'string' ? value : undefined
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -57,38 +57,38 @@ export function pagesRouterSsrState(
|
|
|
57
57
|
pattern: string,
|
|
58
58
|
params: Record<string, RouteParamValue> | undefined,
|
|
59
59
|
): PagesRouterSsrState {
|
|
60
|
-
const requestUrl = currentRequestUrl()
|
|
61
|
-
const canonical = canonicalHref() ?? requestUrl
|
|
62
|
-
const query: Record<string, string | string[]> = {}
|
|
60
|
+
const requestUrl = currentRequestUrl()
|
|
61
|
+
const canonical = canonicalHref() ?? requestUrl
|
|
62
|
+
const query: Record<string, string | string[]> = {}
|
|
63
63
|
if (requestUrl) {
|
|
64
64
|
for (const [key, value] of new URL(requestUrl).searchParams) {
|
|
65
65
|
// The router-fetch cache key rides soft-navigation request URLs; it is
|
|
66
66
|
// never part of the page's query.
|
|
67
|
-
if (key !== '_rsc') query[key] = value
|
|
67
|
+
if (key !== '_rsc') query[key] = value
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
for (const [key, value] of Object.entries(params ?? {})) {
|
|
71
|
-
if (value !== undefined) query[key] = value
|
|
71
|
+
if (value !== undefined) query[key] = value
|
|
72
72
|
}
|
|
73
|
-
let asPath = pattern
|
|
73
|
+
let asPath = pattern
|
|
74
74
|
if (canonical) {
|
|
75
|
-
const url = new URL(canonical)
|
|
76
|
-
asPath = `${url.pathname}${url.search}
|
|
75
|
+
const url = new URL(canonical)
|
|
76
|
+
asPath = `${url.pathname}${url.search}`
|
|
77
77
|
}
|
|
78
|
-
const state: PagesRouterSsrState = { pathname: pattern, asPath, query }
|
|
79
|
-
const scope = anchoredScope(REQUEST_STORAGE)
|
|
80
|
-
if (scope) scope[STATE_KEY] = state
|
|
81
|
-
return state
|
|
78
|
+
const state: PagesRouterSsrState = { pathname: pattern, asPath, query }
|
|
79
|
+
const scope = anchoredScope(REQUEST_STORAGE)
|
|
80
|
+
if (scope) scope[STATE_KEY] = state
|
|
81
|
+
return state
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/** The state stashed by the active render's page wrapper, if any. */
|
|
85
85
|
export function currentPagesRouterState(): PagesRouterSsrState | undefined {
|
|
86
|
-
const scope = anchoredScope(REQUEST_STORAGE)
|
|
87
|
-
const state = scope?.[STATE_KEY]
|
|
88
|
-
return state ? (state as PagesRouterSsrState) : undefined
|
|
86
|
+
const scope = anchoredScope(REQUEST_STORAGE)
|
|
87
|
+
const state = scope?.[STATE_KEY]
|
|
88
|
+
return state ? (state as PagesRouterSsrState) : undefined
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/** Serialize state for the inline JSON node (script-safe: `<` escaped). */
|
|
92
92
|
export function serializePagesRouterState(state: PagesRouterSsrState): string {
|
|
93
|
-
return JSON.stringify(state).replace(/</g, '\\u003c')
|
|
93
|
+
return JSON.stringify(state).replace(/</g, '\\u003c')
|
|
94
94
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
import { existsSync, statSync } from 'node:fs'
|
|
3
|
-
import { copyFile, mkdir, readFile, rm, symlink, writeFile } from 'node:fs/promises'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
import { tmpdir } from 'node:os'
|
|
6
|
-
import { hasUseClientDirective } from '../../client/reference-stub'
|
|
7
|
-
import { listFiles, toPosixPath } from '../../utils/fs'
|
|
8
|
-
import { getNextConfig } from '../next/config-loader'
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { existsSync, statSync } from 'node:fs'
|
|
3
|
+
import { copyFile, mkdir, readFile, rm, symlink, writeFile } from 'node:fs/promises'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { tmpdir } from 'node:os'
|
|
6
|
+
import { hasUseClientDirective } from '../../client/reference-stub'
|
|
7
|
+
import { listFiles, toPosixPath } from '../../utils/fs'
|
|
8
|
+
import { getNextConfig } from '../next/config-loader'
|
|
9
9
|
|
|
10
|
-
const basePageExtensions = ['tsx', 'ts', 'jsx', 'js', 'mjs']
|
|
10
|
+
const basePageExtensions = ['tsx', 'ts', 'jsx', 'js', 'mjs']
|
|
11
11
|
|
|
12
12
|
// The app's configured pageExtensions (e.g. @next/mdx appending mdx/md) must
|
|
13
13
|
// apply to materialization too, or hybrid apps lose their .mdx routes — this
|
|
14
14
|
// runs during config resolution, before registerMdxExtensions.
|
|
15
15
|
function materializeExtensions(): string[] {
|
|
16
|
-
const configured = getNextConfig().pageExtensions
|
|
16
|
+
const configured = getNextConfig().pageExtensions
|
|
17
17
|
const extras = Array.isArray(configured)
|
|
18
18
|
? configured.filter((ext): ext is string => typeof ext === 'string' && ext.length > 0)
|
|
19
|
-
: []
|
|
20
|
-
return [...new Set([...basePageExtensions, ...extras])]
|
|
19
|
+
: []
|
|
20
|
+
return [...new Set([...basePageExtensions, ...extras])]
|
|
21
21
|
}
|
|
22
22
|
const appConventions = new Set([
|
|
23
23
|
'default',
|
|
@@ -31,15 +31,15 @@ const appConventions = new Set([
|
|
|
31
31
|
'route',
|
|
32
32
|
'template',
|
|
33
33
|
'unauthorized',
|
|
34
|
-
])
|
|
34
|
+
])
|
|
35
35
|
|
|
36
36
|
// Metadata code routes (manifest.js, opengraph-image.tsx, icon2.tsx, ...) are
|
|
37
37
|
// app conventions too and must survive materialization in hybrid apps.
|
|
38
38
|
const metadataConventionPattern =
|
|
39
|
-
/^(robots|sitemap|manifest|icon\d*|apple-icon\d*|opengraph-image\d*|twitter-image\d*)
|
|
39
|
+
/^(robots|sitemap|manifest|icon\d*|apple-icon\d*|opengraph-image\d*|twitter-image\d*)$/
|
|
40
40
|
|
|
41
41
|
function isAppConvention(name: string): boolean {
|
|
42
|
-
return appConventions.has(name) || metadataConventionPattern.test(name)
|
|
42
|
+
return appConventions.has(name) || metadataConventionPattern.test(name)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
@@ -48,62 +48,61 @@ function isAppConvention(name: string): boolean {
|
|
|
48
48
|
* conflict validation; linked sources and node_modules keep normal resolution.
|
|
49
49
|
*/
|
|
50
50
|
export async function materializePagesApp(root: string): Promise<string | undefined> {
|
|
51
|
-
const pagesPath = path.join(root, 'pages')
|
|
52
|
-
if (!existsSync(pagesPath)) return undefined
|
|
51
|
+
const pagesPath = path.join(root, 'pages')
|
|
52
|
+
if (!existsSync(pagesPath)) return undefined
|
|
53
53
|
|
|
54
54
|
const generatedRoot = path.join(
|
|
55
55
|
tmpdir(),
|
|
56
56
|
'pnext-pages-compat',
|
|
57
57
|
createHash('sha256').update(root).digest('hex').slice(0, 16),
|
|
58
|
-
)
|
|
59
|
-
const appPath = path.join(generatedRoot, 'app')
|
|
60
|
-
const sourcePages = path.join(generatedRoot, 'source-pages')
|
|
61
|
-
const sourceApp = path.join(generatedRoot, 'source-app')
|
|
62
|
-
const pages = await discoverPages(pagesPath)
|
|
63
|
-
const apiRoutes = await discoverPagesApi(pagesPath)
|
|
64
|
-
if (pages.length === 0 && apiRoutes.length === 0) return undefined
|
|
58
|
+
)
|
|
59
|
+
const appPath = path.join(generatedRoot, 'app')
|
|
60
|
+
const sourcePages = path.join(generatedRoot, 'source-pages')
|
|
61
|
+
const sourceApp = path.join(generatedRoot, 'source-app')
|
|
62
|
+
const pages = await discoverPages(pagesPath)
|
|
63
|
+
const apiRoutes = await discoverPagesApi(pagesPath)
|
|
64
|
+
if (pages.length === 0 && apiRoutes.length === 0) return undefined
|
|
65
65
|
|
|
66
|
-
await rm(generatedRoot, { recursive: true, force: true })
|
|
67
|
-
await mkdir(appPath, { recursive: true })
|
|
68
|
-
await symlink(pagesPath, sourcePages, 'dir')
|
|
69
|
-
const nodeModules = path.join(root, 'node_modules')
|
|
66
|
+
await rm(generatedRoot, { recursive: true, force: true })
|
|
67
|
+
await mkdir(appPath, { recursive: true })
|
|
68
|
+
await symlink(pagesPath, sourcePages, 'dir')
|
|
69
|
+
const nodeModules = path.join(root, 'node_modules')
|
|
70
70
|
if (existsSync(nodeModules))
|
|
71
|
-
await symlink(nodeModules, path.join(generatedRoot, 'node_modules'), 'dir')
|
|
71
|
+
await symlink(nodeModules, path.join(generatedRoot, 'node_modules'), 'dir')
|
|
72
72
|
|
|
73
73
|
// Static assets referenced from materialized routes (e.g. an app route's
|
|
74
74
|
// `new URL('../../public/vercel.png', import.meta.url)` or a `public/*` asset
|
|
75
75
|
// import) resolve relative to the generated root; without the symlink the
|
|
76
76
|
// bundler can't find them and the route 500s.
|
|
77
|
-
const publicDir = path.join(root, 'public')
|
|
78
|
-
if (existsSync(publicDir))
|
|
79
|
-
await symlink(publicDir, path.join(generatedRoot, 'public'), 'dir');
|
|
77
|
+
const publicDir = path.join(root, 'public')
|
|
78
|
+
if (existsSync(publicDir)) await symlink(publicDir, path.join(generatedRoot, 'public'), 'dir')
|
|
80
79
|
|
|
81
|
-
const nativeApp = path.join(root, 'app')
|
|
80
|
+
const nativeApp = path.join(root, 'app')
|
|
82
81
|
if (existsSync(nativeApp)) {
|
|
83
|
-
await symlink(nativeApp, sourceApp, 'dir')
|
|
84
|
-
await materializeNativeApp(sourceApp, appPath)
|
|
82
|
+
await symlink(nativeApp, sourceApp, 'dir')
|
|
83
|
+
await materializeNativeApp(sourceApp, appPath)
|
|
85
84
|
}
|
|
86
85
|
if (!existsSync(path.join(appPath, 'layout.js'))) {
|
|
87
86
|
await writeFile(
|
|
88
87
|
path.join(appPath, 'layout.js'),
|
|
89
88
|
'export default function PagesLayout({ children }) {\n return <html><body>{children}</body></html>\n}\n',
|
|
90
|
-
)
|
|
89
|
+
)
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
for (const page of pages) {
|
|
94
|
-
const destination = path.join(appPath, ...encodePrivateSegments(page.segments), 'page.js')
|
|
95
|
-
if (existsSync(destination)) continue
|
|
96
|
-
await mkdir(path.dirname(destination), { recursive: true })
|
|
97
|
-
const pagesPattern = `/${page.segments.join('/')}`.replace(/\/+$/, '') || '/'
|
|
98
|
-
const sourceSpecifier = relativeImport(destination, path.join(sourcePages, page.relative))
|
|
99
|
-
let clientSpecifier: string | undefined
|
|
93
|
+
const destination = path.join(appPath, ...encodePrivateSegments(page.segments), 'page.js')
|
|
94
|
+
if (existsSync(destination)) continue
|
|
95
|
+
await mkdir(path.dirname(destination), { recursive: true })
|
|
96
|
+
const pagesPattern = `/${page.segments.join('/')}`.replace(/\/+$/, '') || '/'
|
|
97
|
+
const sourceSpecifier = relativeImport(destination, path.join(sourcePages, page.relative))
|
|
98
|
+
let clientSpecifier: string | undefined
|
|
100
99
|
if (page.hasStaticProps || page.hasServerSideProps) {
|
|
101
|
-
const clientDestination = path.join(path.dirname(destination), 'pnext-page-client.js')
|
|
100
|
+
const clientDestination = path.join(path.dirname(destination), 'pnext-page-client.js')
|
|
102
101
|
await writeFile(
|
|
103
102
|
clientDestination,
|
|
104
103
|
`'use client';\nexport { default } from ${JSON.stringify(sourceSpecifier)};\n`,
|
|
105
|
-
)
|
|
106
|
-
clientSpecifier = './pnext-page-client.js'
|
|
104
|
+
)
|
|
105
|
+
clientSpecifier = './pnext-page-client.js'
|
|
107
106
|
}
|
|
108
107
|
await writeFile(
|
|
109
108
|
destination,
|
|
@@ -122,44 +121,44 @@ export async function materializePagesApp(root: string): Promise<string | undefi
|
|
|
122
121
|
page.maxDuration,
|
|
123
122
|
pagesPattern,
|
|
124
123
|
),
|
|
125
|
-
)
|
|
124
|
+
)
|
|
126
125
|
}
|
|
127
126
|
for (const apiRoute of apiRoutes) {
|
|
128
|
-
const destination = path.join(appPath, 'api', ...apiRoute.segments, 'route.js')
|
|
129
|
-
if (existsSync(destination)) continue
|
|
130
|
-
await mkdir(path.dirname(destination), { recursive: true })
|
|
127
|
+
const destination = path.join(appPath, 'api', ...apiRoute.segments, 'route.js')
|
|
128
|
+
if (existsSync(destination)) continue
|
|
129
|
+
await mkdir(path.dirname(destination), { recursive: true })
|
|
131
130
|
await writeFile(
|
|
132
131
|
destination,
|
|
133
132
|
pagesApiWrapperSource(
|
|
134
133
|
relativeImport(destination, path.join(sourcePages, apiRoute.relative)),
|
|
135
134
|
apiRoute.runtime,
|
|
136
135
|
),
|
|
137
|
-
)
|
|
136
|
+
)
|
|
138
137
|
}
|
|
139
138
|
|
|
140
|
-
return appPath
|
|
139
|
+
return appPath
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
async function materializeNativeApp(sourceApp: string, appPath: string): Promise<void> {
|
|
144
143
|
for (const file of await listFiles(sourceApp)) {
|
|
145
|
-
const relative = toPosixPath(path.relative(sourceApp, file))
|
|
146
|
-
const parsed = path.parse(relative)
|
|
144
|
+
const relative = toPosixPath(path.relative(sourceApp, file))
|
|
145
|
+
const parsed = path.parse(relative)
|
|
147
146
|
// Non-code files (favicon.ico, robots.txt, sitemap.xml, og images, ...)
|
|
148
147
|
// are static metadata routes discovered by scanning the app dir — carry
|
|
149
148
|
// them into the merged view or they 404 in hybrid apps. Copied, not
|
|
150
149
|
// symlinked: the file listers skip symlink dirents.
|
|
151
150
|
if (!materializeExtensions().includes(parsed.ext.slice(1))) {
|
|
152
|
-
const destination = path.join(appPath, relative)
|
|
153
|
-
await mkdir(path.dirname(destination), { recursive: true })
|
|
154
|
-
await copyFile(file, destination)
|
|
155
|
-
continue
|
|
151
|
+
const destination = path.join(appPath, relative)
|
|
152
|
+
await mkdir(path.dirname(destination), { recursive: true })
|
|
153
|
+
await copyFile(file, destination)
|
|
154
|
+
continue
|
|
156
155
|
}
|
|
157
|
-
if (!isAppConvention(parsed.name)) continue
|
|
158
|
-
const destination = path.join(appPath, parsed.dir, `${parsed.name}.js`)
|
|
159
|
-
await mkdir(path.dirname(destination), { recursive: true })
|
|
160
|
-
const source = await readFile(file, 'utf8')
|
|
156
|
+
if (!isAppConvention(parsed.name)) continue
|
|
157
|
+
const destination = path.join(appPath, parsed.dir, `${parsed.name}.js`)
|
|
158
|
+
await mkdir(path.dirname(destination), { recursive: true })
|
|
159
|
+
const source = await readFile(file, 'utf8')
|
|
161
160
|
const client =
|
|
162
|
-
hasUseClientDirective(source) || (await defaultExportImportsClientModule(file, source))
|
|
161
|
+
hasUseClientDirective(source) || (await defaultExportImportsClientModule(file, source))
|
|
163
162
|
await writeFile(
|
|
164
163
|
destination,
|
|
165
164
|
wrapperSource(
|
|
@@ -170,31 +169,31 @@ async function materializeNativeApp(sourceApp: string, appPath: string): Promise
|
|
|
170
169
|
undefined,
|
|
171
170
|
runtimeFromSource(source),
|
|
172
171
|
),
|
|
173
|
-
)
|
|
172
|
+
)
|
|
174
173
|
}
|
|
175
174
|
}
|
|
176
175
|
|
|
177
176
|
async function defaultExportImportsClientModule(file: string, source: string): Promise<boolean> {
|
|
178
|
-
const defaultExport = /export\s+default\s+([A-Za-z_$][\w$]*)\s*;?/.exec(source)
|
|
179
|
-
if (!defaultExport?.[1]) return false
|
|
177
|
+
const defaultExport = /export\s+default\s+([A-Za-z_$][\w$]*)\s*;?/.exec(source)
|
|
178
|
+
if (!defaultExport?.[1]) return false
|
|
180
179
|
|
|
181
|
-
const binding = defaultExport[1]
|
|
182
|
-
const imports = /import\s*\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g
|
|
183
|
-
let match: RegExpExecArray | null
|
|
180
|
+
const binding = defaultExport[1]
|
|
181
|
+
const imports = /import\s*\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g
|
|
182
|
+
let match: RegExpExecArray | null
|
|
184
183
|
while ((match = imports.exec(source))) {
|
|
185
184
|
const importsBinding = (match[1] ?? '').split(',').some(value => {
|
|
186
|
-
const names = /^\s*([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?\s*$/.exec(value)
|
|
187
|
-
return (names?.[2] ?? names?.[1]) === binding
|
|
188
|
-
})
|
|
189
|
-
if (!importsBinding || !match[2]?.startsWith('.')) continue
|
|
190
|
-
const imported = resolveSourceImport(file, match[2])
|
|
191
|
-
if (imported && hasUseClientDirective(await readFile(imported, 'utf8'))) return true
|
|
185
|
+
const names = /^\s*([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?\s*$/.exec(value)
|
|
186
|
+
return (names?.[2] ?? names?.[1]) === binding
|
|
187
|
+
})
|
|
188
|
+
if (!importsBinding || !match[2]?.startsWith('.')) continue
|
|
189
|
+
const imported = resolveSourceImport(file, match[2])
|
|
190
|
+
if (imported && hasUseClientDirective(await readFile(imported, 'utf8'))) return true
|
|
192
191
|
}
|
|
193
|
-
return false
|
|
192
|
+
return false
|
|
194
193
|
}
|
|
195
194
|
|
|
196
195
|
function resolveSourceImport(file: string, specifier: string): string | undefined {
|
|
197
|
-
const base = path.resolve(path.dirname(file), specifier)
|
|
196
|
+
const base = path.resolve(path.dirname(file), specifier)
|
|
198
197
|
for (const candidate of [
|
|
199
198
|
base,
|
|
200
199
|
...materializeExtensions().flatMap(extension => [
|
|
@@ -202,24 +201,24 @@ function resolveSourceImport(file: string, specifier: string): string | undefine
|
|
|
202
201
|
path.join(base, `index.${extension}`),
|
|
203
202
|
]),
|
|
204
203
|
]) {
|
|
205
|
-
if (existsSync(candidate) && statSync(candidate).isFile()) return candidate
|
|
204
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) return candidate
|
|
206
205
|
}
|
|
207
|
-
return undefined
|
|
206
|
+
return undefined
|
|
208
207
|
}
|
|
209
208
|
|
|
210
209
|
interface PagesRoute {
|
|
211
|
-
relative: string
|
|
212
|
-
segments: string[]
|
|
213
|
-
hasServerSideProps: boolean
|
|
214
|
-
hasStaticProps: boolean
|
|
215
|
-
runtime?: 'edge' | 'nodejs'
|
|
216
|
-
maxDuration?: number
|
|
210
|
+
relative: string
|
|
211
|
+
segments: string[]
|
|
212
|
+
hasServerSideProps: boolean
|
|
213
|
+
hasStaticProps: boolean
|
|
214
|
+
runtime?: 'edge' | 'nodejs'
|
|
215
|
+
maxDuration?: number
|
|
217
216
|
}
|
|
218
217
|
|
|
219
218
|
interface PagesApiRoute {
|
|
220
|
-
relative: string
|
|
221
|
-
segments: string[]
|
|
222
|
-
runtime?: 'edge' | 'nodejs'
|
|
219
|
+
relative: string
|
|
220
|
+
segments: string[]
|
|
221
|
+
runtime?: 'edge' | 'nodejs'
|
|
223
222
|
}
|
|
224
223
|
|
|
225
224
|
// A pages-router segment beginning with `_` is a real route (pages has no private-folder convention),
|
|
@@ -227,38 +226,36 @@ interface PagesApiRoute {
|
|
|
227
226
|
// private. Encoding the leading underscore to `%5F` keeps the materialized directory routable - the
|
|
228
227
|
// scanner decodes it back.
|
|
229
228
|
function encodePrivateSegments(segments: string[]): string[] {
|
|
230
|
-
return segments.map(segment =>
|
|
231
|
-
segment.startsWith('_') ? `%5F${segment.slice(1)}` : segment,
|
|
232
|
-
);
|
|
229
|
+
return segments.map(segment => (segment.startsWith('_') ? `%5F${segment.slice(1)}` : segment))
|
|
233
230
|
}
|
|
234
231
|
|
|
235
232
|
async function discoverPages(pagesPath: string): Promise<PagesRoute[]> {
|
|
236
|
-
const routes = new Map<string, PagesRoute>()
|
|
237
|
-
const files = await listFiles(pagesPath)
|
|
233
|
+
const routes = new Map<string, PagesRoute>()
|
|
234
|
+
const files = await listFiles(pagesPath)
|
|
238
235
|
for (const extension of materializeExtensions()) {
|
|
239
236
|
for (const file of files) {
|
|
240
|
-
if (!file.endsWith(`.${extension}`)) continue
|
|
241
|
-
const relative = toPosixPath(path.relative(pagesPath, file))
|
|
242
|
-
const withoutExtension = relative.slice(0, -extension.length - 1)
|
|
243
|
-
const sourceSegments = withoutExtension.split('/')
|
|
237
|
+
if (!file.endsWith(`.${extension}`)) continue
|
|
238
|
+
const relative = toPosixPath(path.relative(pagesPath, file))
|
|
239
|
+
const withoutExtension = relative.slice(0, -extension.length - 1)
|
|
240
|
+
const sourceSegments = withoutExtension.split('/')
|
|
244
241
|
// The pages router has no private-folder convention (that is app-router
|
|
245
242
|
// only): a nested `_dashboard/index.tsx` routes at `/_dashboard`. Only the
|
|
246
243
|
// reserved root components (`_app`/`_document`/`_error`) and the `api`
|
|
247
244
|
// segment are excluded from route materialization.
|
|
248
|
-
if (sourceSegments[0] === 'api') continue
|
|
245
|
+
if (sourceSegments[0] === 'api') continue
|
|
249
246
|
if (
|
|
250
247
|
sourceSegments.length === 1 &&
|
|
251
248
|
(sourceSegments[0] === '_app' ||
|
|
252
249
|
sourceSegments[0] === '_document' ||
|
|
253
250
|
sourceSegments[0] === '_error')
|
|
254
251
|
) {
|
|
255
|
-
continue
|
|
252
|
+
continue
|
|
256
253
|
}
|
|
257
254
|
const segments =
|
|
258
|
-
sourceSegments.at(-1) === 'index' ? sourceSegments.slice(0, -1) : sourceSegments
|
|
259
|
-
const key = segments.join('/')
|
|
255
|
+
sourceSegments.at(-1) === 'index' ? sourceSegments.slice(0, -1) : sourceSegments
|
|
256
|
+
const key = segments.join('/')
|
|
260
257
|
if (!routes.has(key)) {
|
|
261
|
-
const source = await readFile(file, 'utf8')
|
|
258
|
+
const source = await readFile(file, 'utf8')
|
|
262
259
|
routes.set(key, {
|
|
263
260
|
relative,
|
|
264
261
|
segments,
|
|
@@ -266,35 +263,35 @@ async function discoverPages(pagesPath: string): Promise<PagesRoute[]> {
|
|
|
266
263
|
hasStaticProps: /\bgetStaticProps\b/.test(source),
|
|
267
264
|
runtime: runtimeFromSource(source),
|
|
268
265
|
maxDuration: maxDurationFromSource(source),
|
|
269
|
-
})
|
|
266
|
+
})
|
|
270
267
|
}
|
|
271
268
|
}
|
|
272
269
|
}
|
|
273
|
-
return [...routes.values()]
|
|
270
|
+
return [...routes.values()]
|
|
274
271
|
}
|
|
275
272
|
|
|
276
273
|
async function discoverPagesApi(pagesPath: string): Promise<PagesApiRoute[]> {
|
|
277
|
-
const routes = new Map<string, PagesApiRoute>()
|
|
278
|
-
const files = await listFiles(path.join(pagesPath, 'api'))
|
|
274
|
+
const routes = new Map<string, PagesApiRoute>()
|
|
275
|
+
const files = await listFiles(path.join(pagesPath, 'api'))
|
|
279
276
|
for (const extension of materializeExtensions()) {
|
|
280
277
|
for (const file of files) {
|
|
281
|
-
if (!file.endsWith(`.${extension}`)) continue
|
|
282
|
-
const relative = toPosixPath(path.relative(pagesPath, file))
|
|
278
|
+
if (!file.endsWith(`.${extension}`)) continue
|
|
279
|
+
const relative = toPosixPath(path.relative(pagesPath, file))
|
|
283
280
|
const segments = relative
|
|
284
281
|
.slice(0, -extension.length - 1)
|
|
285
282
|
.split('/')
|
|
286
|
-
.slice(1)
|
|
287
|
-
if (segments.some(segment => segment.startsWith('_'))) continue
|
|
288
|
-
const key = segments.join('/')
|
|
289
|
-
if (routes.has(key)) continue
|
|
283
|
+
.slice(1)
|
|
284
|
+
if (segments.some(segment => segment.startsWith('_'))) continue
|
|
285
|
+
const key = segments.join('/')
|
|
286
|
+
if (routes.has(key)) continue
|
|
290
287
|
routes.set(key, {
|
|
291
288
|
relative,
|
|
292
289
|
segments,
|
|
293
290
|
runtime: runtimeFromSource(await readFile(file, 'utf8')),
|
|
294
|
-
})
|
|
291
|
+
})
|
|
295
292
|
}
|
|
296
293
|
}
|
|
297
|
-
return [...routes.values()]
|
|
294
|
+
return [...routes.values()]
|
|
298
295
|
}
|
|
299
296
|
|
|
300
297
|
// The compat runtime module the data wrappers import (by absolute path — the
|
|
@@ -302,18 +299,18 @@ async function discoverPagesApi(pagesPath: string): Promise<PagesApiRoute[]> {
|
|
|
302
299
|
// cannot reach it). It computes + stashes the SSR useRouter() state and
|
|
303
300
|
// serializes it for the inline __PNEXT_PAGES_DATA__ JSON node.
|
|
304
301
|
function routerStateModulePath(): string {
|
|
305
|
-
return path.join(import.meta.dirname, 'router-state.ts')
|
|
302
|
+
return path.join(import.meta.dirname, 'router-state.ts')
|
|
306
303
|
}
|
|
307
304
|
|
|
308
305
|
// The shared prologue/epilogue for data wrappers: emit the pages-router state
|
|
309
306
|
// node alongside the page so the next/router shim (SSR and browser) sees the
|
|
310
307
|
// pages-route pattern, canonical asPath, and merged query.
|
|
311
308
|
function routerStateSnippet(pagesPattern: string | undefined): {
|
|
312
|
-
imports: string
|
|
313
|
-
render: string
|
|
309
|
+
imports: string
|
|
310
|
+
render: string
|
|
314
311
|
} {
|
|
315
312
|
if (!pagesPattern) {
|
|
316
|
-
return { imports: '', render: 'return createElement(Page, result?.props ?? {});' }
|
|
313
|
+
return { imports: '', render: 'return createElement(Page, result?.props ?? {});' }
|
|
317
314
|
}
|
|
318
315
|
return {
|
|
319
316
|
imports: `import { pagesRouterSsrState, serializePagesRouterState } from ${JSON.stringify(
|
|
@@ -330,7 +327,7 @@ function routerStateSnippet(pagesPattern: string | undefined): {
|
|
|
330
327
|
}),
|
|
331
328
|
createElement(Page, result?.props ?? {}),
|
|
332
329
|
);`,
|
|
333
|
-
}
|
|
330
|
+
}
|
|
334
331
|
}
|
|
335
332
|
|
|
336
333
|
function wrapperSource(
|
|
@@ -343,10 +340,10 @@ function wrapperSource(
|
|
|
343
340
|
maxDuration?: number,
|
|
344
341
|
pagesPattern?: string,
|
|
345
342
|
): string {
|
|
346
|
-
const runtimeExport = runtime ? `export const runtime = ${JSON.stringify(runtime)};\n` : ''
|
|
343
|
+
const runtimeExport = runtime ? `export const runtime = ${JSON.stringify(runtime)};\n` : ''
|
|
347
344
|
const maxDurationExport =
|
|
348
|
-
maxDuration === undefined ? '' : `export const maxDuration = ${maxDuration};\n
|
|
349
|
-
const routerState = routerStateSnippet(pagesPattern)
|
|
345
|
+
maxDuration === undefined ? '' : `export const maxDuration = ${maxDuration};\n`
|
|
346
|
+
const routerState = routerStateSnippet(pagesPattern)
|
|
350
347
|
if (hasStaticProps && clientSpecifier) {
|
|
351
348
|
return `import { createElement, Fragment } from 'react';
|
|
352
349
|
import { notFound, redirect } from 'next/navigation';
|
|
@@ -363,18 +360,18 @@ ${runtimeExport}${maxDurationExport}export default async function PagesCompatSta
|
|
|
363
360
|
if (result?.redirect) redirect(result.redirect.destination);
|
|
364
361
|
${routerState.render}
|
|
365
362
|
}
|
|
366
|
-
|
|
363
|
+
`
|
|
367
364
|
}
|
|
368
365
|
if (!hasServerSideProps) {
|
|
369
366
|
if (client) {
|
|
370
367
|
return `'use client';
|
|
371
368
|
export { default } from ${JSON.stringify(specifier)};
|
|
372
|
-
${runtimeExport}${maxDurationExport}
|
|
369
|
+
${runtimeExport}${maxDurationExport}`
|
|
373
370
|
}
|
|
374
371
|
return `import * as __pnext_page_ns from ${JSON.stringify(specifier)};
|
|
375
372
|
export default __pnext_page_ns.default;
|
|
376
373
|
export * from ${JSON.stringify(specifier)};
|
|
377
|
-
${runtimeExport}${maxDurationExport}
|
|
374
|
+
${runtimeExport}${maxDurationExport}`
|
|
378
375
|
}
|
|
379
376
|
return `import { createElement, Fragment } from 'react';
|
|
380
377
|
import { notFound, redirect } from 'next/navigation';
|
|
@@ -423,23 +420,21 @@ ${runtimeExport}${maxDurationExport}export default async function PagesCompatPag
|
|
|
423
420
|
if (result?.redirect) redirect(result.redirect.destination);
|
|
424
421
|
${routerState.render}
|
|
425
422
|
}
|
|
426
|
-
|
|
423
|
+
`
|
|
427
424
|
}
|
|
428
425
|
|
|
429
426
|
function runtimeFromSource(source: string): 'edge' | 'nodejs' | undefined {
|
|
430
|
-
const runtime = /\bruntime\b\s*[:=]\s*(['"`])(edge|nodejs|experimental-edge)\1/.exec(
|
|
431
|
-
|
|
432
|
-
)?.[2];
|
|
433
|
-
return runtime === 'experimental-edge' ? 'edge' : (runtime as 'edge' | 'nodejs' | undefined);
|
|
427
|
+
const runtime = /\bruntime\b\s*[:=]\s*(['"`])(edge|nodejs|experimental-edge)\1/.exec(source)?.[2]
|
|
428
|
+
return runtime === 'experimental-edge' ? 'edge' : (runtime as 'edge' | 'nodejs' | undefined)
|
|
434
429
|
}
|
|
435
430
|
|
|
436
431
|
function maxDurationFromSource(source: string): number | undefined {
|
|
437
|
-
const value = /\bmaxDuration\s*:\s*(\d+)\b/.exec(source)?.[1]
|
|
438
|
-
return value === undefined ? undefined : Number(value)
|
|
432
|
+
const value = /\bmaxDuration\s*:\s*(\d+)\b/.exec(source)?.[1]
|
|
433
|
+
return value === undefined ? undefined : Number(value)
|
|
439
434
|
}
|
|
440
435
|
|
|
441
436
|
function pagesApiWrapperSource(specifier: string, runtime?: 'edge' | 'nodejs'): string {
|
|
442
|
-
const runtimeExport = runtime ? `export const runtime = ${JSON.stringify(runtime)};\n` : ''
|
|
437
|
+
const runtimeExport = runtime ? `export const runtime = ${JSON.stringify(runtime)};\n` : ''
|
|
443
438
|
return `import handler from ${JSON.stringify(specifier)};
|
|
444
439
|
import { NextRequest } from 'next/server';
|
|
445
440
|
import { Writable } from 'node:stream';
|
|
@@ -518,10 +513,10 @@ async function run(handler, request) {
|
|
|
518
513
|
}
|
|
519
514
|
return new Response(body, { status: state.status, headers: state.headers });
|
|
520
515
|
}
|
|
521
|
-
|
|
516
|
+
`
|
|
522
517
|
}
|
|
523
518
|
|
|
524
519
|
function relativeImport(fromFile: string, targetFile: string): string {
|
|
525
|
-
const relative = toPosixPath(path.relative(path.dirname(fromFile), targetFile))
|
|
526
|
-
return relative.startsWith('.') ? relative : `./${relative}
|
|
520
|
+
const relative = toPosixPath(path.relative(path.dirname(fromFile), targetFile))
|
|
521
|
+
return relative.startsWith('.') ? relative : `./${relative}`
|
|
527
522
|
}
|
package/src/compat/ppr/io.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// scope it is a no-op (the cache is filled at build, so post-io content is buildtime), and without
|
|
5
5
|
// cacheComponents it is a no-op entirely.
|
|
6
6
|
|
|
7
|
-
import { cacheComponents, hangingPromise, isPrerendering } from '../../ppr'
|
|
8
|
-
import { insideDataCacheProducer } from '../cache/revalidate'
|
|
7
|
+
import { cacheComponents, hangingPromise, isPrerendering } from '../../render/ppr'
|
|
8
|
+
import { insideDataCacheProducer } from '../cache/revalidate'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A resolved promise pre-tagged with React's tracked-thenable state (`status: 'fulfilled'`).
|
|
@@ -16,12 +16,12 @@ import { insideDataCacheProducer } from '../cache/revalidate';
|
|
|
16
16
|
*/
|
|
17
17
|
function resolvedIo(): Promise<void> {
|
|
18
18
|
const promise = Promise.resolve() as Promise<void> & {
|
|
19
|
-
status?: string
|
|
20
|
-
value?: undefined
|
|
21
|
-
}
|
|
22
|
-
promise.status = 'fulfilled'
|
|
23
|
-
promise.value = undefined
|
|
24
|
-
return promise
|
|
19
|
+
status?: string
|
|
20
|
+
value?: undefined
|
|
21
|
+
}
|
|
22
|
+
promise.status = 'fulfilled'
|
|
23
|
+
promise.value = undefined
|
|
24
|
+
return promise
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -29,10 +29,10 @@ function resolvedIo(): Promise<void> {
|
|
|
29
29
|
* prerender / request / use-cache / no-cacheComponents matrix.
|
|
30
30
|
*/
|
|
31
31
|
export function io(): Promise<void> {
|
|
32
|
-
if (!cacheComponents()) return resolvedIo()
|
|
32
|
+
if (!cacheComponents()) return resolvedIo()
|
|
33
33
|
// Inside a `use cache` / unstable_cache producer the cache boundary wins: the
|
|
34
34
|
// value is produced at build, so io() does not postpone.
|
|
35
|
-
if (insideDataCacheProducer()) return resolvedIo()
|
|
36
|
-
if (isPrerendering()) return hangingPromise<void>('io()')
|
|
37
|
-
return resolvedIo()
|
|
35
|
+
if (insideDataCacheProducer()) return resolvedIo()
|
|
36
|
+
if (isPrerendering()) return hangingPromise<void>('io()')
|
|
37
|
+
return resolvedIo()
|
|
38
38
|
}
|