@wular/pnext 0.1.6 → 0.1.8
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/bin/pnext +9 -2
- package/dist/server/_chunks/aliases-pycbtjt1.js +46 -0
- package/dist/server/_chunks/analyze-4d9e00g9.js +449 -0
- package/dist/server/_chunks/boot-bhemypxz.js +38 -0
- package/dist/server/_chunks/build-c991dv65.js +86 -0
- package/dist/server/_chunks/build-kh5e3x48.js +3341 -0
- package/dist/server/_chunks/build-tier-0a96kmx3.js +2456 -0
- package/dist/server/_chunks/compile-040r79gj.js +22 -0
- package/dist/server/_chunks/config-0tvz03a6.js +24 -0
- package/dist/server/_chunks/config-27rj7830.js +36 -0
- package/dist/server/_chunks/create-9rvwshsp.js +135 -0
- package/dist/server/_chunks/dev-ex9exynt.js +220 -0
- package/dist/server/_chunks/esbuild-yyktfrtt.js +15 -0
- package/dist/server/_chunks/generate-myw9hef7.js +22 -0
- package/dist/server/_chunks/index-0r5eqfc7.js +279 -0
- package/dist/server/_chunks/index-0yjv5v47.js +105 -0
- package/dist/server/_chunks/index-11xpbfej.js +17 -0
- package/dist/server/_chunks/index-141vcwk6.js +109 -0
- package/dist/server/_chunks/index-1pzm1hdy.js +4130 -0
- package/dist/server/_chunks/index-29pq0kax.js +590 -0
- package/dist/server/_chunks/index-2vz0wzdn.js +59 -0
- package/dist/server/_chunks/index-2wfv4kvx.js +182 -0
- package/dist/server/_chunks/index-38xpdxwd.js +194 -0
- package/dist/server/_chunks/index-3e075kny.js +128 -0
- package/dist/server/_chunks/index-3ycf5ckv.js +472 -0
- package/dist/server/_chunks/index-4399bvd2.js +18 -0
- package/dist/server/_chunks/index-4da76t62.js +297 -0
- package/dist/server/_chunks/index-4t92hdxd.js +172 -0
- package/dist/server/_chunks/index-4zzebszd.js +10 -0
- package/dist/server/_chunks/index-52k54ykj.js +95 -0
- package/dist/server/_chunks/index-5hr4062s.js +70 -0
- package/dist/server/_chunks/index-68m3mwbd.js +84 -0
- package/dist/server/_chunks/index-6b009mt0.js +56 -0
- package/dist/server/_chunks/index-6gex3pfa.js +15 -0
- package/dist/server/_chunks/index-6kp9r0d9.js +11 -0
- package/dist/server/_chunks/index-6q7zvrap.js +134 -0
- package/dist/server/_chunks/index-71885zaq.js +284 -0
- package/dist/server/_chunks/index-73z4esab.js +38 -0
- package/dist/server/_chunks/index-79ngvam8.js +60 -0
- package/dist/server/_chunks/index-7wc9n8be.js +25 -0
- package/dist/server/_chunks/index-8ct7rqy3.js +198 -0
- package/dist/server/_chunks/index-8kcxdfya.js +206 -0
- package/dist/server/_chunks/index-9ch50vtq.js +18 -0
- package/dist/server/_chunks/index-9f49w76j.js +213 -0
- package/dist/server/_chunks/index-9hz3s0m8.js +851 -0
- package/dist/server/_chunks/index-akkrvjn6.js +535 -0
- package/dist/server/_chunks/index-b6wtkdp4.js +24 -0
- package/dist/server/_chunks/index-b7j671dj.js +207 -0
- package/dist/server/_chunks/index-bcws5eh2.js +35 -0
- package/dist/server/_chunks/index-bzd2ef7t.js +10 -0
- package/dist/server/_chunks/index-cjgqs13g.js +65 -0
- package/dist/server/_chunks/index-ckkdpht5.js +41 -0
- package/dist/server/_chunks/index-cn86z041.js +296 -0
- package/dist/server/_chunks/index-cvr4z22m.js +92 -0
- package/dist/server/_chunks/index-cyfednwb.js +87 -0
- package/dist/server/_chunks/index-d158y67j.js +152 -0
- package/dist/server/_chunks/index-d1jsmhhk.js +955 -0
- package/dist/server/_chunks/index-dg0f05zs.js +199 -0
- package/dist/server/_chunks/index-dgr390q7.js +9438 -0
- package/dist/server/_chunks/index-drwv61cc.js +185 -0
- package/dist/server/_chunks/index-e3a6yx84.js +18 -0
- package/dist/server/_chunks/index-e88tyv35.js +45 -0
- package/dist/server/_chunks/index-en7n9f7m.js +22 -0
- package/dist/server/_chunks/index-entm8bmz.js +28 -0
- package/dist/server/_chunks/index-evhd413j.js +57 -0
- package/dist/server/_chunks/index-ezgj0tr1.js +88 -0
- package/dist/server/_chunks/index-fjv96re1.js +5295 -0
- package/dist/server/_chunks/index-fn1chkkd.js +214 -0
- package/dist/server/_chunks/index-fp8r0sqs.js +64 -0
- package/dist/server/_chunks/index-gcmj16xy.js +92 -0
- package/dist/server/_chunks/index-gkndxkxf.js +736 -0
- package/dist/server/_chunks/index-grta8ap3.js +238 -0
- package/dist/server/_chunks/index-h2a70tg4.js +7 -0
- package/dist/server/_chunks/index-h4xy648y.js +51 -0
- package/dist/server/_chunks/index-hdbwtdv2.js +352 -0
- package/dist/server/_chunks/index-he6n2bvp.js +1270 -0
- package/dist/server/_chunks/index-j0m1jxqa.js +1253 -0
- package/dist/server/_chunks/index-j2zrcp1k.js +66 -0
- package/dist/server/_chunks/index-j681c48a.js +2530 -0
- package/dist/server/_chunks/index-jbj7ehef.js +50 -0
- package/dist/server/_chunks/index-jcsjq3d1.js +20 -0
- package/dist/server/_chunks/index-jks0x0a1.js +14 -0
- package/dist/server/_chunks/index-jn9rbhrx.js +1599 -0
- package/dist/server/_chunks/index-jt8e1pje.js +12 -0
- package/dist/server/_chunks/index-kdhxpwyq.js +483 -0
- package/dist/server/_chunks/index-knp0s912.js +7 -0
- package/dist/server/_chunks/index-kqyy1d4f.js +50 -0
- package/dist/server/_chunks/index-kresp2n8.js +445 -0
- package/dist/server/_chunks/index-m63czgq5.js +590 -0
- package/dist/server/_chunks/index-ms9v9tnx.js +31 -0
- package/dist/server/_chunks/index-n4hxpng2.js +11 -0
- package/dist/server/_chunks/index-n629dy38.js +1071 -0
- package/dist/server/_chunks/index-nf3df4jy.js +266 -0
- package/dist/server/_chunks/index-nqh3xhdc.js +57 -0
- package/dist/server/_chunks/index-pym1cezq.js +39 -0
- package/dist/server/_chunks/index-q3r9z8mq.js +213 -0
- package/dist/server/_chunks/index-q738kkhj.js +100 -0
- package/dist/server/_chunks/index-qcrvt6er.js +112 -0
- package/dist/server/_chunks/index-qjj6gddn.js +54 -0
- package/dist/server/_chunks/index-qpwsgt3a.js +158 -0
- package/dist/server/_chunks/index-r97ptz1q.js +97 -0
- package/dist/server/_chunks/index-ras0sdab.js +26 -0
- package/dist/server/_chunks/index-rcs322t1.js +19 -0
- package/dist/server/_chunks/index-rgj5mx84.js +101 -0
- package/dist/server/_chunks/index-rjegyfx4.js +1435 -0
- package/dist/server/_chunks/index-rt9qq1va.js +4 -0
- package/dist/server/_chunks/index-rthrsed5.js +356 -0
- package/dist/server/_chunks/index-sq3kvz3g.js +200 -0
- package/dist/server/_chunks/index-stbk3jhn.js +31 -0
- package/dist/server/_chunks/index-tf4j19ge.js +130 -0
- package/dist/server/_chunks/index-tgcakdxc.js +125 -0
- package/dist/server/_chunks/index-tgsfjmep.js +74 -0
- package/dist/server/_chunks/index-tq1f96v7.js +51 -0
- package/dist/server/_chunks/index-tq3b39a5.js +107 -0
- package/dist/server/_chunks/index-typcbcsv.js +819 -0
- package/dist/server/_chunks/index-v1ags1na.js +132 -0
- package/dist/server/_chunks/index-vmr35jjw.js +170 -0
- package/dist/server/_chunks/index-vvq7rqtn.js +329 -0
- package/dist/server/_chunks/index-vz0km5qk.js +33 -0
- package/dist/server/_chunks/index-w6h8m6vp.js +138 -0
- package/dist/server/_chunks/index-web361b8.js +138 -0
- package/dist/server/_chunks/index-wm36rj4v.js +311 -0
- package/dist/server/_chunks/index-x0y005nh.js +283 -0
- package/dist/server/_chunks/index-x2m17v9c.js +6166 -0
- package/dist/server/_chunks/index-x3yn4ywm.js +22 -0
- package/dist/server/_chunks/index-x9c55pzy.js +871 -0
- package/dist/server/_chunks/index-xh1nbk46.js +1299 -0
- package/dist/server/_chunks/index-xvj80c3a.js +30 -0
- package/dist/server/_chunks/index-xywjg2vc.js +100 -0
- package/dist/server/_chunks/index-y4d02znn.js +66 -0
- package/dist/server/_chunks/index-y7mzvq2q.js +110 -0
- package/dist/server/_chunks/index-ye9hmsvf.js +47 -0
- package/dist/server/_chunks/index-yhxkxghe.js +56 -0
- package/dist/server/_chunks/index-yrjkqtfj.js +86 -0
- package/dist/server/_chunks/index-z88qv16t.js +11 -0
- package/dist/server/_chunks/index-zfrwq472.js +154 -0
- package/dist/server/_chunks/index-zqpqyg8p.js +666 -0
- package/dist/server/_chunks/loader-5en7wpt5.js +80 -0
- package/dist/server/_chunks/modules-t92favpj.js +76 -0
- package/dist/server/_chunks/pipeline-4t9q43ht.js +836 -0
- package/dist/server/_chunks/production-385bw8df.js +55 -0
- package/dist/server/_chunks/proxy-config-60gprphe.js +23 -0
- package/dist/server/_chunks/proxy-gfhmktbk.js +35 -0
- package/dist/server/_chunks/router-xnrva921.js +501 -0
- package/dist/server/_chunks/routes-ht868pdc.js +66 -0
- package/dist/server/_chunks/run-d40d63ag.js +697 -0
- package/dist/server/_chunks/server-2p8fgqq2.js +1839 -0
- package/dist/server/_chunks/tsconfig-defaults-bcn34eqb.js +21 -0
- package/dist/server/_chunks/typegen-dvtcjtaw.js +37 -0
- package/dist/server/api/client-cache.js +14 -0
- package/dist/server/cli/index.js +375 -0
- package/dist/server/cli/start.js +158 -0
- package/dist/server/client/reference.js +16 -0
- package/dist/server/compat/next/cache.js +56 -0
- package/dist/server/compat/next/canonical-url.js +13 -0
- package/dist/server/compat/next/client-cache.js +57 -0
- package/dist/server/compat/next/client-navigation.js +232 -0
- package/dist/server/compat/next/client-only.js +1 -0
- package/dist/server/compat/next/client-script.js +178 -0
- package/dist/server/compat/next/client-server.js +34 -0
- package/dist/server/compat/next/config-headers.js +34 -0
- package/dist/server/compat/next/config-loader.js +25 -0
- package/dist/server/compat/next/config.js +10 -0
- package/dist/server/compat/next/constants.js +18 -0
- package/dist/server/compat/next/custom-server.js +10 -0
- package/dist/server/compat/next/dist/client/components/app-router-headers.js +48 -0
- package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +27 -0
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +25 -0
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +25 -0
- package/dist/server/compat/next/dynamic.js +21 -0
- package/dist/server/compat/next/error.js +112 -0
- package/dist/server/compat/next/font/cache.js +16 -0
- package/dist/server/compat/next/font/google.js +3 -0
- package/dist/server/compat/next/font/index.js +1 -0
- package/dist/server/compat/next/font/local.js +24 -0
- package/dist/server/compat/next/font/runtime-client.js +33 -0
- package/dist/server/compat/next/font/runtime.js +43 -0
- package/dist/server/compat/next/font/shared.js +22 -0
- package/dist/server/compat/next/form.js +129 -0
- package/dist/server/compat/next/head.js +10 -0
- package/dist/server/compat/next/headers.js +30 -0
- package/dist/server/compat/next/image/client.js +11 -0
- package/dist/server/compat/next/image/config.js +18 -0
- package/dist/server/compat/next/image/optimizer.js +25 -0
- package/dist/server/compat/next/image/patterns.js +12 -0
- package/dist/server/compat/next/image/props.js +16 -0
- package/dist/server/compat/next/image/shared.js +86 -0
- package/dist/server/compat/next/image/static-metadata.js +32 -0
- package/dist/server/compat/next/image/validate.js +8 -0
- package/dist/server/compat/next/image.js +59 -0
- package/dist/server/compat/next/index.js +1 -0
- package/dist/server/compat/next/legacy-image.js +78 -0
- package/dist/server/compat/next/legacy-request-apis.js +24 -0
- package/dist/server/compat/next/link-transform.js +15 -0
- package/dist/server/compat/next/link.js +14 -0
- package/dist/server/compat/next/navigation.js +191 -0
- package/dist/server/compat/next/offline.js +45 -0
- package/dist/server/compat/next/og.js +8 -0
- package/dist/server/compat/next/preferred-region.js +8 -0
- package/dist/server/compat/next/redirects.js +32 -0
- package/dist/server/compat/next/resource-hints.js +30 -0
- package/dist/server/compat/next/rewrites.js +43 -0
- package/dist/server/compat/next/root-params.js +121 -0
- package/dist/server/compat/next/route-state.js +23 -0
- package/dist/server/compat/next/router.js +103 -0
- package/dist/server/compat/next/script.js +37 -0
- package/dist/server/compat/next/server-only.js +1 -0
- package/dist/server/compat/next/server.js +131 -0
- package/dist/server/compat/next/svgr.js +14 -0
- package/dist/server/compat/next/telemetry.js +10 -0
- package/dist/server/compat/next/usage.js +13 -0
- package/dist/server/compat/next/user-agent.js +12 -0
- package/dist/server/compat/next/web-vitals.js +35 -0
- package/dist/server/compat/react/action-state.js +11 -0
- package/dist/server/compat/react/client-lite.js +83 -0
- package/dist/server/compat/react/client.js +131 -0
- package/dist/server/compat/react/compiler-runtime.js +42 -0
- package/dist/server/compat/react/dom-client.js +106 -0
- package/dist/server/compat/react/dom-react-server.js +37 -0
- package/dist/server/compat/react/dom-server.js +40 -0
- package/dist/server/compat/react/dom.js +52 -0
- package/dist/server/compat/react/hooks-extra.js +12 -0
- package/dist/server/compat/react/internals.js +14 -0
- package/dist/server/compat/react/parity.js +11 -0
- package/dist/server/compat/react/preact.js +113 -0
- package/dist/server/compat/react/react-server.js +133 -0
- package/dist/server/compat/react/router-shim.js +8 -0
- package/dist/server/compat/react/server-component-use.js +14 -0
- package/dist/server/compat/react/server-inserted-html.js +14 -0
- package/dist/server/compat/react/server.js +194 -0
- package/dist/server/compat/react/style-values.js +10 -0
- package/dist/server/compat/react/use.js +10 -0
- package/dist/server/compat/react/view-transition.js +12 -0
- package/dist/server/generation.json +1 -0
- package/package.json +4 -1
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/dev.md +1 -1
- package/reference/getting-started.md +1 -1
- package/reference/rendering.md +4 -4
- package/src/api/dynamic.tsx +86 -4
- package/src/api/server.ts +24 -6
- package/src/cli/adapters/vercel-warm.ts +327 -62
- package/src/cli/adapters/vercel.ts +164 -1054
- package/src/cli/analyze.ts +3 -2
- package/src/cli/build/cache.ts +6 -6
- package/src/cli/build.ts +78 -45
- package/src/cli/index.ts +21 -3
- package/src/cli/serve/immutable.ts +31 -0
- package/src/cli/serve/pipeline.ts +97 -93
- package/src/cli/serve/standalone-worker.ts +8 -0
- package/src/cli/serve/standalone.ts +703 -0
- package/src/cli/start.ts +31 -8
- package/src/client/build.ts +1 -1
- package/src/client/chunk-fold.ts +19 -6
- package/src/client/react-tier.ts +3 -2
- package/src/client/reference-stub.ts +23 -36
- package/src/compat/actions/client-plugin.ts +4 -2
- package/src/compat/actions/config.ts +6 -5
- package/src/compat/actions/extensions.ts +5 -5
- package/src/compat/aliases.ts +8 -1
- package/src/compat/bundler/config.ts +88 -0
- package/src/compat/bundler/optimize-package-imports.ts +86 -26
- package/src/compat/bundler/relay-transform.ts +15 -3
- package/src/compat/bundler/require-context.ts +2 -1
- package/src/compat/bundler/webpack-loaders.ts +3 -2
- package/src/compat/bundler/worker.ts +2 -2
- package/src/compat/cache-control.ts +16 -8
- package/src/compat/css/inline-css.ts +1 -1
- package/src/compat/css/modules.ts +18 -5
- package/src/compat/export/build-complete.ts +1 -1
- package/src/compat/export/emit.ts +4 -4
- package/src/compat/export/standalone.ts +30 -65
- package/src/compat/image-optimizer/optimize.ts +1 -1
- package/src/compat/lifecycle/error-funnel.ts +1 -1
- package/src/compat/lifecycle/instrumentation-client.ts +4 -3
- package/src/compat/lifecycle/instrumentation.ts +117 -24
- package/src/compat/lifecycle/testmode.ts +3 -2
- package/src/compat/metadata-artifacts.ts +1 -1
- package/src/compat/next/config-loader.ts +140 -13
- package/src/compat/next/dynamic.tsx +10 -23
- package/src/compat/next/font/cache.ts +2 -1
- package/src/compat/next/font/runtime.ts +23 -3
- package/src/compat/next/og.ts +3 -3
- package/src/compat/next/usage.ts +3 -2
- package/src/compat/pages/api.ts +83 -14
- package/src/compat/pages/router.ts +30 -14
- package/src/compat/register/bundler.ts +3 -1
- package/src/compat/register/image.ts +1 -1
- package/src/compat/register/middleware.ts +1 -1
- package/src/compat/register/otel.ts +5 -9
- package/src/compat/register/render.ts +3 -1
- package/src/compat/register/use-cache.ts +3 -1
- package/src/compat/release.ts +46 -0
- package/src/compat/segment/serve.ts +1 -1
- package/src/compat/typecheck/check.ts +6 -4
- package/src/compat/validation/validate.ts +10 -7
- package/src/config.ts +76 -9
- package/src/css/assets.ts +213 -0
- package/src/css/build.ts +190 -247
- package/src/dev/client-chunk-store.ts +2 -1
- package/src/dev/restart/client-key.ts +2 -1
- package/src/dev/restart/global-css.ts +2 -1
- package/src/dev/restart/route-bundle-key.ts +2 -1
- package/src/dev/restart/route-facts.ts +2 -1
- package/src/dev/server.ts +34 -14
- package/src/extensions.ts +4 -0
- package/src/out-paths.ts +10 -0
- package/src/render/hooks.ts +13 -0
- package/src/render/renderer.ts +53 -33
- package/src/request/context.ts +9 -0
- package/src/resolve/dynamic.ts +7 -1
- package/src/resolve/engine.ts +2 -12
- package/src/resolve/imports.ts +12 -52
- package/src/resolve/package-json.ts +56 -0
- package/src/resolve/scan-facts.ts +250 -1
- package/src/routing/href.ts +10 -3
- package/src/routing/match.ts +287 -0
- package/src/routing/metadata-files.ts +20 -6
- package/src/routing/proxy-config.ts +137 -0
- package/src/routing/proxy.ts +35 -134
- package/src/routing/routes.ts +22 -281
- package/src/runtime/fingerprint.ts +23 -8
- package/src/runtime/load.ts +170 -0
- package/src/runtime/loader.ts +218 -44
- package/src/runtime/module-cache.ts +15 -1
- package/src/runtime/modules.ts +405 -82
- package/src/runtime/prebundle.ts +101 -0
- package/src/runtime/production.ts +456 -0
- package/src/runtime/release-graph.ts +342 -0
- package/src/runtime/vendor-build.ts +750 -17
- package/src/runtime/vendor.ts +16 -3
- package/src/types.ts +4 -3
- package/src/utils/directive.ts +40 -0
- package/src/utils/fs.ts +95 -4
- package/src/utils/resource-query.ts +12 -0
- package/src/cli/serve/entry.ts +0 -45
|
@@ -18,9 +18,8 @@ import { currentRequest, getWorkUnit } from '../../request/context'
|
|
|
18
18
|
// readonly property." `require()` returns the real, mutable CJS exports
|
|
19
19
|
// object that node/http/https resolve `.get` calls through at runtime, so
|
|
20
20
|
// patch that instead of the namespace binding.
|
|
21
|
+
// Required on install, not at import: loading node:http/https costs every build ~10 ms.
|
|
21
22
|
const requireNode = createRequire(import.meta.url)
|
|
22
|
-
const httpModule = requireNode('node:http') as typeof http
|
|
23
|
-
const httpsModule = requireNode('node:https') as typeof https
|
|
24
23
|
|
|
25
24
|
interface TestProxyInfo {
|
|
26
25
|
proxyPort: number
|
|
@@ -284,6 +283,8 @@ export function installTestProxyFetch(): void {
|
|
|
284
283
|
;(testFetch as typeof fetch).preconnect = originalFetch.preconnect?.bind(originalFetch)
|
|
285
284
|
globalThis.fetch = testFetch as typeof fetch
|
|
286
285
|
|
|
286
|
+
const httpModule = requireNode('node:http') as typeof http
|
|
287
|
+
const httpsModule = requireNode('node:https') as typeof https
|
|
287
288
|
const originalHttpGet = httpModule.get
|
|
288
289
|
const originalHttpsGet = httpsModule.get
|
|
289
290
|
httpModule.get = patchableGet(originalHttpGet, originalFetch)
|
|
@@ -329,7 +329,7 @@ async function writeStaticMetadataArtifacts(
|
|
|
329
329
|
metadata: StaticFileMetadata | undefined,
|
|
330
330
|
): Promise<void> {
|
|
331
331
|
if (!metadata) return
|
|
332
|
-
const source = path.join(outPath, '
|
|
332
|
+
const source = path.join(outPath, 'static', relative)
|
|
333
333
|
const outputBase = path.join(root, 'server', 'app', toPosixPath(relative))
|
|
334
334
|
await mkdir(path.dirname(outputBase), { recursive: true })
|
|
335
335
|
const routeMeta = JSON.stringify(toRouteMeta(metadata))
|
|
@@ -13,7 +13,15 @@
|
|
|
13
13
|
// export / top-level await / dynamic import() and CJS+ESM authoring styles.
|
|
14
14
|
// ---------------------------------------------------------------------------
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
existsSync,
|
|
18
|
+
mkdirSync,
|
|
19
|
+
readFileSync,
|
|
20
|
+
readdirSync,
|
|
21
|
+
renameSync,
|
|
22
|
+
rmSync,
|
|
23
|
+
writeFileSync,
|
|
24
|
+
} from 'node:fs'
|
|
17
25
|
import { createRequire } from 'node:module'
|
|
18
26
|
import path from 'node:path'
|
|
19
27
|
import { pathToFileURL } from 'node:url'
|
|
@@ -43,6 +51,12 @@ const CONFIG_BASENAMES = [
|
|
|
43
51
|
]
|
|
44
52
|
|
|
45
53
|
let store: NextConfigObject = {}
|
|
54
|
+
let storeReleased = false
|
|
55
|
+
|
|
56
|
+
/** Whether the stored config came from a production release, which no consumer may re-read from source. */
|
|
57
|
+
export function nextConfigReleased(): boolean {
|
|
58
|
+
return storeReleased
|
|
59
|
+
}
|
|
46
60
|
|
|
47
61
|
/** The full loaded next.config object; empty until loadNextConfig runs. */
|
|
48
62
|
export function getNextConfig(): NextConfigObject {
|
|
@@ -188,19 +202,104 @@ async function importConfigModule(
|
|
|
188
202
|
return importConfigBundle(outfile, cjs)
|
|
189
203
|
}
|
|
190
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Compile the app's next.config into `outDir`, plus the cache handlers it names, so a production server
|
|
207
|
+
* imports neither from source. Names carry a content hash: a rebuilt release never reuses the previous
|
|
208
|
+
* generation's module instance. Paths are relative to the bundle, so the release can move.
|
|
209
|
+
*/
|
|
210
|
+
export async function emitNextConfigBundle(root: string, outDir: string) {
|
|
211
|
+
const configPath = findConfigPath(root)
|
|
212
|
+
if (!configPath) return undefined
|
|
213
|
+
const cjs = cjsConfigFormat(configPath, root)
|
|
214
|
+
const [file, ...handlerFiles] = await Promise.all([
|
|
215
|
+
hashedOutput(outDir, 'next.config', cjs ? '.cjs' : '.mjs', outfile =>
|
|
216
|
+
bundleConfig({ configPath, root, outDir, outfile, cjs, relocatable: true }),
|
|
217
|
+
),
|
|
218
|
+
...cacheHandlerFiles(store).map(([name, source]) =>
|
|
219
|
+
hashedOutput(outDir, name, '.cjs', outfile =>
|
|
220
|
+
build({
|
|
221
|
+
entryPoints: [source],
|
|
222
|
+
outfile,
|
|
223
|
+
bundle: true,
|
|
224
|
+
platform: 'node',
|
|
225
|
+
format: 'cjs',
|
|
226
|
+
target: 'esnext',
|
|
227
|
+
packages: 'external',
|
|
228
|
+
logLevel: 'silent',
|
|
229
|
+
}),
|
|
230
|
+
).then(output => [name, output] as const),
|
|
231
|
+
),
|
|
232
|
+
])
|
|
233
|
+
return { file, handlers: Object.fromEntries(handlerFiles as [string, string][]) }
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Write through `emit` to a temporary name, then publish as `<name>.<content hash><ext>`. */
|
|
237
|
+
async function hashedOutput(
|
|
238
|
+
outDir: string,
|
|
239
|
+
name: string,
|
|
240
|
+
ext: string,
|
|
241
|
+
emit: (outfile: string) => Promise<unknown>,
|
|
242
|
+
) {
|
|
243
|
+
const temporary = path.join(outDir, `${name}.${process.pid}.tmp${ext}`)
|
|
244
|
+
await emit(temporary)
|
|
245
|
+
const hash = bun.hash(readFileSync(temporary)).toString(36)
|
|
246
|
+
const outfile = path.join(outDir, `${name}.${hash}${ext}`)
|
|
247
|
+
renameSync(temporary, outfile)
|
|
248
|
+
return outfile
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** The configured cache handler sources, by the name their release bundle takes. */
|
|
252
|
+
function cacheHandlerFiles(config: NextConfigObject): [string, string][] {
|
|
253
|
+
const handlers = config.cacheHandlers as Record<string, unknown> | undefined
|
|
254
|
+
return [
|
|
255
|
+
['cache-handler', config.cacheHandler],
|
|
256
|
+
[
|
|
257
|
+
'cache-handler-default',
|
|
258
|
+
handlers && typeof handlers === 'object' ? handlers.default : undefined,
|
|
259
|
+
],
|
|
260
|
+
].filter(
|
|
261
|
+
(entry): entry is [string, string] =>
|
|
262
|
+
typeof entry[1] === 'string' && path.isAbsolute(entry[1]) && existsSync(entry[1]),
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** Point a released config's cache handlers at the bundles its build emitted. */
|
|
267
|
+
function releasedCacheHandlers(
|
|
268
|
+
config: NextConfigObject,
|
|
269
|
+
handlers: Record<string, string>,
|
|
270
|
+
): NextConfigObject {
|
|
271
|
+
const handler = handlers['cache-handler']
|
|
272
|
+
const fallback = handlers['cache-handler-default']
|
|
273
|
+
return {
|
|
274
|
+
...config,
|
|
275
|
+
...(handler ? { cacheHandler: handler } : {}),
|
|
276
|
+
...(fallback
|
|
277
|
+
? { cacheHandlers: { ...(config.cacheHandlers as object), default: fallback } }
|
|
278
|
+
: {}),
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const toPosix = (file: string) => file.split(path.sep).join('/')
|
|
283
|
+
|
|
191
284
|
function bundleConfig({
|
|
192
285
|
configPath,
|
|
193
286
|
root,
|
|
194
287
|
outDir,
|
|
195
288
|
outfile,
|
|
196
289
|
cjs,
|
|
290
|
+
relocatable = false,
|
|
197
291
|
}: {
|
|
198
292
|
configPath: string
|
|
199
293
|
root: string
|
|
200
294
|
outDir: string
|
|
201
295
|
outfile: string
|
|
202
296
|
cjs: boolean
|
|
297
|
+
/** A release bundle: locate the config from the bundle itself, never from the build machine's paths. */
|
|
298
|
+
relocatable?: boolean
|
|
203
299
|
}) {
|
|
300
|
+
const configUrl = relocatable
|
|
301
|
+
? `new URL(${JSON.stringify(toPosix(path.relative(outDir, configPath)))}, ${cjs ? '__pnextNodeRequire("node:url").pathToFileURL(__filename)' : 'import.meta.url'}).href`
|
|
302
|
+
: JSON.stringify(pathToFileURL(configPath).href)
|
|
204
303
|
return build({
|
|
205
304
|
entryPoints: [configPath],
|
|
206
305
|
outfile,
|
|
@@ -220,12 +319,20 @@ function bundleConfig({
|
|
|
220
319
|
? {
|
|
221
320
|
js:
|
|
222
321
|
'var __pnextNodeRequire = module.require.bind(module);\n' +
|
|
223
|
-
`var
|
|
322
|
+
`var __pnextConfigUrl = ${configUrl};\n` +
|
|
323
|
+
'var __pnextConfigFile = __pnextNodeRequire("node:url").fileURLToPath(__pnextConfigUrl);\n' +
|
|
324
|
+
'var __pnextConfigDir = __pnextNodeRequire("node:path").dirname(__pnextConfigFile);\n' +
|
|
325
|
+
'var require = __pnextNodeRequire("node:module").createRequire(__pnextConfigUrl);',
|
|
224
326
|
}
|
|
225
327
|
: {
|
|
226
328
|
js:
|
|
227
329
|
'import { createRequire as __pnextCreateRequire } from "node:module";\n' +
|
|
228
|
-
|
|
330
|
+
'import { fileURLToPath as __pnextFileURLToPath } from "node:url";\n' +
|
|
331
|
+
'import { dirname as __pnextDirname } from "node:path";\n' +
|
|
332
|
+
`const __pnextConfigUrl = ${configUrl};\n` +
|
|
333
|
+
'const __pnextConfigFile = __pnextFileURLToPath(__pnextConfigUrl);\n' +
|
|
334
|
+
'const __pnextConfigDir = __pnextDirname(__pnextConfigFile);\n' +
|
|
335
|
+
'const require = __pnextCreateRequire(__pnextConfigUrl);',
|
|
229
336
|
},
|
|
230
337
|
// Relative/absolute imports (incl. .ts/.cts/.mts/.cjs/.mjs and tsconfig
|
|
231
338
|
// `paths` aliases) are bundled in. esbuild reads `paths`/`extends` and
|
|
@@ -235,9 +342,9 @@ function bundleConfig({
|
|
|
235
342
|
// import.meta.url in ESM configs (node-api-esm) must point at the config's
|
|
236
343
|
// original location, not the emitted file under .pnext/config.
|
|
237
344
|
define: {
|
|
238
|
-
__dirname:
|
|
239
|
-
__filename:
|
|
240
|
-
'import.meta.url':
|
|
345
|
+
__dirname: '__pnextConfigDir',
|
|
346
|
+
__filename: '__pnextConfigFile',
|
|
347
|
+
'import.meta.url': '__pnextConfigUrl',
|
|
241
348
|
},
|
|
242
349
|
logLevel: 'silent',
|
|
243
350
|
sourcemap: false,
|
|
@@ -381,6 +488,9 @@ function mapOverrides(config: NextConfigObject): NextConfigCoreOverrides {
|
|
|
381
488
|
config.output !== 'export'
|
|
382
489
|
) {
|
|
383
490
|
overrides.outDir = config.distDir
|
|
491
|
+
} else if (config.output === 'standalone') {
|
|
492
|
+
// Next's `.next/standalone`: the folder its standalone contract names.
|
|
493
|
+
overrides.outDir = '.next'
|
|
384
494
|
}
|
|
385
495
|
return overrides
|
|
386
496
|
}
|
|
@@ -647,20 +757,36 @@ function validateDevIndicatorPosition(config: NextConfigObject): void {
|
|
|
647
757
|
*/
|
|
648
758
|
export async function loadNextConfig(
|
|
649
759
|
root: string,
|
|
650
|
-
options: {
|
|
760
|
+
options: {
|
|
761
|
+
dev?: boolean
|
|
762
|
+
serve?: boolean
|
|
763
|
+
warnings?: boolean
|
|
764
|
+
bundle?: string | null
|
|
765
|
+
handlers?: Record<string, string>
|
|
766
|
+
} = {},
|
|
651
767
|
): Promise<LoadNextConfigResult> {
|
|
652
|
-
|
|
768
|
+
// A production server names its compiled config, or null when the app had none.
|
|
769
|
+
storeReleased = options.bundle !== undefined
|
|
770
|
+
const configPath = options.bundle === undefined ? findConfigPath(root) : options.bundle
|
|
653
771
|
if (!configPath) {
|
|
654
772
|
setNextConfig({})
|
|
655
773
|
emitSessionStartedTelemetry({})
|
|
656
774
|
return { config: {}, overrides: {} }
|
|
657
775
|
}
|
|
776
|
+
if (options.bundle && !existsSync(options.bundle)) {
|
|
777
|
+
// The release names this file; serving defaults in its place would drop headers, redirects and more.
|
|
778
|
+
throw new Error(
|
|
779
|
+
`pnext: the build's compiled next.config (${options.bundle}) is missing. Run 'pnext build' again.`,
|
|
780
|
+
)
|
|
781
|
+
}
|
|
658
782
|
let exported: NextConfigExport
|
|
659
783
|
try {
|
|
660
|
-
exported =
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
784
|
+
exported = options.bundle
|
|
785
|
+
? await importConfigBundle(options.bundle, options.bundle.endsWith('.cjs'))
|
|
786
|
+
: await importConfigModule(configPath, root, {
|
|
787
|
+
dev: Boolean(options.dev),
|
|
788
|
+
serve: Boolean(options.serve),
|
|
789
|
+
})
|
|
664
790
|
} catch (error) {
|
|
665
791
|
// A next.config that pulls in an optional wrapper dependency not installed
|
|
666
792
|
// in this app (e.g. @next/mdx when deps are declared but not installed)
|
|
@@ -677,10 +803,11 @@ export async function loadNextConfig(
|
|
|
677
803
|
}
|
|
678
804
|
throw error
|
|
679
805
|
}
|
|
680
|
-
const
|
|
806
|
+
const resolved = normalizeCacheHandlerPath(
|
|
681
807
|
await resolveConfigExport(exported, Boolean(options.dev)),
|
|
682
808
|
root,
|
|
683
809
|
)
|
|
810
|
+
const config = options.bundle ? releasedCacheHandlers(resolved, options.handlers ?? {}) : resolved
|
|
684
811
|
// Internal build workers need the resolved config but must not surface a
|
|
685
812
|
// second copy of CLI warnings already emitted by the owning build process.
|
|
686
813
|
validateConfig(config, configPath, options.warnings !== false)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/** @jsxImportSource preact */
|
|
2
2
|
import { h, type ComponentType } from 'preact'
|
|
3
|
-
import { lazy, Suspense } from 'preact/compat'
|
|
4
3
|
import {
|
|
5
4
|
dynamic as pnextDynamic,
|
|
6
5
|
dynamicReferenceSymbol,
|
|
@@ -19,25 +18,17 @@ export default function dynamic<Props extends object = object>(
|
|
|
19
18
|
// Injected by the server compile; see rewriteDynamicCallTargets.
|
|
20
19
|
target?: DynamicTarget,
|
|
21
20
|
) {
|
|
22
|
-
if (typeof loader === 'string') return pnextDynamic(loader, options, target)
|
|
23
|
-
|
|
24
21
|
const coreDynamic = pnextDynamic(loader, options, target) as DynamicWithReference<Props>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{ style: { display: 'contents' } },
|
|
36
|
-
!process.browser && typeof window === 'undefined' ? null : h(coreDynamic, props),
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
return h(Suspense, { fallback: Loading ? h(Loading, props) : null }, h(Lazy, props))
|
|
40
|
-
}) as DynamicWithReference<Props>
|
|
22
|
+
// Core's component server-renders and hydrates like Next, waiting for a chunk still loading.
|
|
23
|
+
if (typeof loader === 'string' || options.ssr !== false) return coreDynamic
|
|
24
|
+
|
|
25
|
+
// ssr:false renders nothing on the server; the client renders `loading`, then the component.
|
|
26
|
+
const DynamicComponent = ((props: Props) =>
|
|
27
|
+
h(
|
|
28
|
+
'pnext-dynamic',
|
|
29
|
+
{ style: { display: 'contents' } },
|
|
30
|
+
!process.browser && typeof window === 'undefined' ? null : h(coreDynamic, props),
|
|
31
|
+
)) as DynamicWithReference<Props>
|
|
41
32
|
|
|
42
33
|
DynamicComponent[dynamicReferenceSymbol] = coreDynamic[dynamicReferenceSymbol]
|
|
43
34
|
return DynamicComponent
|
|
@@ -48,7 +39,3 @@ export { dynamic }
|
|
|
48
39
|
type DynamicWithReference<Props extends object> = ComponentType<Props> & {
|
|
49
40
|
[dynamicReferenceSymbol]?: DynamicReference<Props>
|
|
50
41
|
}
|
|
51
|
-
|
|
52
|
-
function componentFromModule<Props>(module: DynamicModule<Props>) {
|
|
53
|
-
return typeof module === 'function' ? module : module.default
|
|
54
|
-
}
|
|
@@ -15,6 +15,7 @@ import { restartCacheEnabled } from '../../../dev/restart/enabled'
|
|
|
15
15
|
import { frameworkFingerprint } from '../../../runtime/fingerprint'
|
|
16
16
|
import { writeFileAtomic } from '../../../utils/fs'
|
|
17
17
|
import type { MetadataLink } from '../../../types'
|
|
18
|
+
import { outCachePath } from '../../../out-paths'
|
|
18
19
|
|
|
19
20
|
export interface PersistableFont {
|
|
20
21
|
css: string
|
|
@@ -54,7 +55,7 @@ interface FontIndex {
|
|
|
54
55
|
const indexes = new Map<string, FontIndex>()
|
|
55
56
|
|
|
56
57
|
function fontIndex(config: ResolvedConfig): FontIndex {
|
|
57
|
-
const file = path.join(config.outPath, '
|
|
58
|
+
const file = path.join(outCachePath(config.outPath), 'fonts', 'index.json')
|
|
58
59
|
const existing = indexes.get(file)
|
|
59
60
|
if (existing) return existing
|
|
60
61
|
const created: FontIndex = { file, fonts: readIndex(file), dirty: false }
|
|
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
8
8
|
import type { ResolvedConfig } from '../../../config'
|
|
9
9
|
import { onExtensionHostReset, registerResponseFinalizers } from '../../../extensions'
|
|
10
10
|
import { getWorkUnit } from '../../../request/context'
|
|
11
|
+
import { servedRelease } from '../../../runtime/production'
|
|
11
12
|
import type { MetadataLink } from '../../../types'
|
|
12
13
|
import { persistFont, persistedFont } from './cache'
|
|
13
14
|
import { escapeRegex } from '../../../utils/code'
|
|
@@ -383,7 +384,23 @@ function registerFont(definition: FontDefinition) {
|
|
|
383
384
|
fontStorage.getStore()?.fonts.set(definition.key, definition)
|
|
384
385
|
}
|
|
385
386
|
|
|
386
|
-
|
|
387
|
+
/** Every declared font, resolved for a release (its files emitted under the out dir). */
|
|
388
|
+
export async function releaseFonts(config: ResolvedConfig): Promise<Record<string, ResolvedFont>> {
|
|
389
|
+
const fonts: Record<string, ResolvedFont> = {}
|
|
390
|
+
for (const font of declaredFonts.values()) {
|
|
391
|
+
const { sources: _sources, ...resolved } = await resolveFont(font, { config })
|
|
392
|
+
fonts[font.key] = resolved
|
|
393
|
+
}
|
|
394
|
+
return fonts
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async function resolveFont(
|
|
398
|
+
definition: FontDefinition,
|
|
399
|
+
context: FontResolveContext,
|
|
400
|
+
): Promise<ResolvedFont> {
|
|
401
|
+
// A production release serves the build's resolution: font sources are not read at request time.
|
|
402
|
+
const released = servedRelease()?.fonts?.[definition.key]
|
|
403
|
+
if (released) return released
|
|
387
404
|
const key = `${context.config.outPath}:${context.dev ? 'dev' : 'build'}:${definition.key}`
|
|
388
405
|
let resolved = resolvedFontCache.get(key)
|
|
389
406
|
if (!resolved) {
|
|
@@ -506,7 +523,10 @@ async function resolveLocalFont(
|
|
|
506
523
|
? false
|
|
507
524
|
: true
|
|
508
525
|
const preload = request.options.preload !== false
|
|
509
|
-
const sources = normalizeLocalSources(
|
|
526
|
+
const sources = normalizeLocalSources(
|
|
527
|
+
request.options,
|
|
528
|
+
request.callerFile && path.resolve(context.config.root, request.callerFile),
|
|
529
|
+
)
|
|
510
530
|
const emitted = await Promise.all(
|
|
511
531
|
sources.map(async source => ({
|
|
512
532
|
...source,
|
|
@@ -785,7 +805,7 @@ async function emitFontBytes(
|
|
|
785
805
|
// Served from `/_next/static/media/` — files under the out dir's public/ map 1:1 to the URL path,
|
|
786
806
|
// which is the only place dev and build both look them up.
|
|
787
807
|
const mediaSegments = ['_next', 'static', 'media']
|
|
788
|
-
const outDir = path.join(context.config.outPath, '
|
|
808
|
+
const outDir = path.join(context.config.outPath, 'static', ...mediaSegments)
|
|
789
809
|
const file = path.join(outDir, filename)
|
|
790
810
|
const asset = {
|
|
791
811
|
ext,
|
package/src/compat/next/og.ts
CHANGED
|
@@ -134,13 +134,13 @@ async function renderWithSatori(
|
|
|
134
134
|
element: unknown,
|
|
135
135
|
options: ImageResponseOptions,
|
|
136
136
|
): Promise<Uint8Array | undefined> {
|
|
137
|
+
// Fonts first: without one satori cannot lay out text, so loading it would be wasted work.
|
|
138
|
+
const fonts = normalizeFonts(options.fonts)
|
|
139
|
+
if (fonts.length === 0) return undefined
|
|
137
140
|
const satori = await loadOptional<SatoriModule>('satori')
|
|
138
141
|
const resvg = await loadOptional<ResvgModule>('@resvg/resvg-js')
|
|
139
142
|
if (!satori || !resvg) return undefined
|
|
140
143
|
|
|
141
|
-
const fonts = normalizeFonts(options.fonts)
|
|
142
|
-
if (fonts.length === 0) return undefined
|
|
143
|
-
|
|
144
144
|
const width = dimension(options.width, DEFAULT_WIDTH, 'width')
|
|
145
145
|
const height = dimension(options.height, DEFAULT_HEIGHT, 'height')
|
|
146
146
|
|
package/src/compat/next/usage.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { existsSync, readdirSync,
|
|
1
|
+
import { existsSync, readdirSync, type Dirent } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { readSourceSync } from '../../resolve/source-text'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Build-time app facts that let compat drop code an app cannot reach. The fact here: whether any
|
|
@@ -95,7 +96,7 @@ function scan(dir: string, match: (source: string) => boolean): boolean {
|
|
|
95
96
|
if (!sourceFile.test(entry.name)) continue
|
|
96
97
|
let source: string
|
|
97
98
|
try {
|
|
98
|
-
source =
|
|
99
|
+
source = readSourceSync(file)
|
|
99
100
|
} catch {
|
|
100
101
|
continue
|
|
101
102
|
}
|
package/src/compat/pages/api.ts
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
// shims plus the API-route and data-fetch (`/_next/data`) dispatch. Registered by
|
|
3
3
|
// ../register/pages-api.ts, which wires the exports below into the extension registries.
|
|
4
4
|
|
|
5
|
-
import { existsSync, readFileSync } from 'node:fs'
|
|
5
|
+
import { type Dirent, existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
6
6
|
import { Writable } from 'node:stream'
|
|
7
7
|
import path from 'node:path'
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
devServerModuleHref,
|
|
10
|
+
pagesApiBundleTargetForRuntime,
|
|
11
|
+
serverBundleTargetForRuntime,
|
|
12
|
+
} from '../../runtime/load'
|
|
13
|
+
import { productionRelease } from '../../runtime/production'
|
|
14
|
+
import type { ResolvedConfig } from '../../config'
|
|
10
15
|
import { getRequestExtensions, type RequestInterceptor } from '../../extensions'
|
|
11
16
|
import { getRequestRuntime } from '../../routing/request-environment'
|
|
12
|
-
import { selectRouteForRequest } from '../../routing/
|
|
13
|
-
import { serverBundleTargetForRuntime } from '../../runtime/loader'
|
|
17
|
+
import { selectRouteForRequest } from '../../routing/match'
|
|
14
18
|
import { setWorkUnitRoute } from '../../request/context'
|
|
15
19
|
import { canonicalUrlHref } from '../next/canonical-url'
|
|
16
20
|
import { markPathRevalidated, normalizeRevalidatePath } from '../cache/revalidate'
|
|
@@ -65,7 +69,7 @@ export const pagesDataInterceptor: RequestInterceptor = async request => {
|
|
|
65
69
|
return dataResponse({ notFound: true }, 404, url)
|
|
66
70
|
}
|
|
67
71
|
const route = selection.route
|
|
68
|
-
if (!isMaterializedPagesRoute(route.file)) return undefined
|
|
72
|
+
if (!isMaterializedPagesRoute(runtime.config, route.file)) return undefined
|
|
69
73
|
|
|
70
74
|
const module = (await import(
|
|
71
75
|
await devServerModuleHref(
|
|
@@ -150,8 +154,19 @@ function dataResponse(body: Record<string, unknown>, status: number, url: URL):
|
|
|
150
154
|
|
|
151
155
|
// The materialized hybrid app hosts BOTH routers; only pages wrappers
|
|
152
156
|
// re-export from source-pages/, so sniff the (tiny, generated) wrapper body —
|
|
153
|
-
// app routes must never serve _next/data.
|
|
154
|
-
|
|
157
|
+
// app routes must never serve _next/data. A release carries the answer.
|
|
158
|
+
const releasedPagesRoutes = new WeakMap<object, Set<string>>()
|
|
159
|
+
|
|
160
|
+
export function isMaterializedPagesRoute(config: ResolvedConfig, file: string): boolean {
|
|
161
|
+
const released = productionRelease(config)?.compat?.pagesRoutes
|
|
162
|
+
if (released) {
|
|
163
|
+
let routes = releasedPagesRoutes.get(released)
|
|
164
|
+
if (!routes) {
|
|
165
|
+
routes = new Set(released.map(route => path.join(config.root, route)))
|
|
166
|
+
releasedPagesRoutes.set(released, routes)
|
|
167
|
+
}
|
|
168
|
+
return routes.has(file)
|
|
169
|
+
}
|
|
155
170
|
if (!file.split(path.sep).join('/').includes('pnext-pages-compat/')) return false
|
|
156
171
|
try {
|
|
157
172
|
return readFileSync(file, 'utf8').includes('source-pages/')
|
|
@@ -160,6 +175,29 @@ function isMaterializedPagesRoute(file: string): boolean {
|
|
|
160
175
|
}
|
|
161
176
|
}
|
|
162
177
|
|
|
178
|
+
/** The materialized pages-router wrappers of a pages-compat app, root-relative, for its release. */
|
|
179
|
+
export function pagesRouteFacts(config: ResolvedConfig): string[] {
|
|
180
|
+
if (!config.appPath.includes('pnext-pages-compat')) return []
|
|
181
|
+
const routes: string[] = []
|
|
182
|
+
const visit = (dir: string) => {
|
|
183
|
+
let entries: Dirent[]
|
|
184
|
+
try {
|
|
185
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
186
|
+
} catch {
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
for (const entry of entries) {
|
|
190
|
+
const file = path.join(dir, entry.name)
|
|
191
|
+
if (entry.isDirectory()) visit(file)
|
|
192
|
+
else if (isMaterializedPagesRoute(config, file)) {
|
|
193
|
+
routes.push(path.relative(config.root, file).split(path.sep).join('/'))
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
visit(config.appPath)
|
|
198
|
+
return routes
|
|
199
|
+
}
|
|
200
|
+
|
|
163
201
|
function pagesDataRequestShim(request: Request, url: URL) {
|
|
164
202
|
return {
|
|
165
203
|
method: request.method,
|
|
@@ -194,11 +232,16 @@ function pagesDataResponseShim() {
|
|
|
194
232
|
|
|
195
233
|
export const pagesApiInterceptor: RequestInterceptor = async (request, { config }) => {
|
|
196
234
|
const url = new URL(request.url)
|
|
197
|
-
const
|
|
235
|
+
const released = productionRelease(config)?.compat?.pagesApi
|
|
236
|
+
const exists = released
|
|
237
|
+
? (candidate: string) => path.relative(config.root, candidate) in released
|
|
238
|
+
: existsSync
|
|
239
|
+
const file = pagesApiFile(config.root, url.pathname, exists)
|
|
198
240
|
if (!file) return undefined
|
|
241
|
+
const runtime = released ? released[path.relative(config.root, file)] : apiRuntime(file)
|
|
199
242
|
const imported = (await import(
|
|
200
243
|
await devServerModuleHref(config, file, 'build', {
|
|
201
|
-
conditionTarget: pagesApiBundleTargetForRuntime(
|
|
244
|
+
conditionTarget: pagesApiBundleTargetForRuntime(runtime),
|
|
202
245
|
})
|
|
203
246
|
)) as PagesApiModule
|
|
204
247
|
if (typeof imported.default !== 'function') return undefined
|
|
@@ -208,7 +251,7 @@ export const pagesApiInterceptor: RequestInterceptor = async (request, { config
|
|
|
208
251
|
// nextUrl, text() — Request prototype getters a spread would lose); node
|
|
209
252
|
// handlers get the IncomingMessage-shaped shim.
|
|
210
253
|
const handlerRequest =
|
|
211
|
-
|
|
254
|
+
runtime === 'edge' ? toNextRequest(request) : createPagesApiRequest(request, url)
|
|
212
255
|
const finished = withPagesApiHandlerSpan(url.pathname, () =>
|
|
213
256
|
Promise.resolve(imported.default!(handlerRequest, responder.res)),
|
|
214
257
|
).catch(error => responder.fail(error))
|
|
@@ -226,7 +269,33 @@ export const pagesApiInterceptor: RequestInterceptor = async (request, { config
|
|
|
226
269
|
|
|
227
270
|
const STREAM_STARTED = Symbol('pnext.pagesApiStreamStarted')
|
|
228
271
|
|
|
229
|
-
|
|
272
|
+
/** Every pages API source with its runtime (`nodejs` unless declared), root-relative: what a release serves. */
|
|
273
|
+
export function pagesApiFacts(root: string): Record<string, string> {
|
|
274
|
+
const facts: Record<string, string> = {}
|
|
275
|
+
const visit = (dir: string) => {
|
|
276
|
+
let entries: Dirent[]
|
|
277
|
+
try {
|
|
278
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
279
|
+
} catch {
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
for (const entry of entries) {
|
|
283
|
+
const file = path.join(dir, entry.name)
|
|
284
|
+
if (entry.isDirectory()) visit(file)
|
|
285
|
+
else if (pageExtensions.some(ext => entry.name.endsWith(`.${ext}`))) {
|
|
286
|
+
facts[path.relative(root, file)] = apiRuntime(file) ?? 'nodejs'
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
visit(path.join(root, 'pages', 'api'))
|
|
291
|
+
return facts
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function pagesApiFile(
|
|
295
|
+
root: string,
|
|
296
|
+
pathname: string,
|
|
297
|
+
exists: (file: string) => boolean,
|
|
298
|
+
): string | undefined {
|
|
230
299
|
if (pathname !== '/api' && !pathname.startsWith('/api/')) return undefined
|
|
231
300
|
let relative: string
|
|
232
301
|
try {
|
|
@@ -239,9 +308,9 @@ function pagesApiFile(root: string, pathname: string): string | undefined {
|
|
|
239
308
|
if (base !== baseDir && !base.startsWith(`${baseDir}${path.sep}`)) return undefined
|
|
240
309
|
for (const ext of pageExtensions) {
|
|
241
310
|
const file = `${base}.${ext}`
|
|
242
|
-
if (
|
|
311
|
+
if (exists(file)) return file
|
|
243
312
|
const index = path.join(base, `index.${ext}`)
|
|
244
|
-
if (
|
|
313
|
+
if (exists(index)) return index
|
|
245
314
|
}
|
|
246
315
|
return undefined
|
|
247
316
|
}
|