@wular/pnext 0.1.5 → 0.1.7
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-j47a10ce.js +44 -0
- package/dist/server/_chunks/analyze-arswqe6s.js +445 -0
- package/dist/server/_chunks/boot-af0mv3dy.js +36 -0
- package/dist/server/_chunks/build-spy3dxp4.js +84 -0
- package/dist/server/_chunks/build-t9h0hec3.js +3550 -0
- package/dist/server/_chunks/build-tier-m7yvqz61.js +2472 -0
- package/dist/server/_chunks/compile-53j02j27.js +22 -0
- package/dist/server/_chunks/config-1yzwexq6.js +27 -0
- package/dist/server/_chunks/config-n2z7yxps.js +22 -0
- package/dist/server/_chunks/create-meec9hs6.js +134 -0
- package/dist/server/_chunks/dev-fjmqg6en.js +220 -0
- package/dist/server/_chunks/esbuild-yyktfrtt.js +15 -0
- package/dist/server/_chunks/generate-n9sh6hzt.js +21 -0
- package/dist/server/_chunks/index-0374j2b9.js +66 -0
- package/dist/server/_chunks/index-06nyqntx.js +213 -0
- package/dist/server/_chunks/index-1011cscr.js +5263 -0
- package/dist/server/_chunks/index-11sfk4hb.js +170 -0
- package/dist/server/_chunks/index-20ppawv7.js +297 -0
- package/dist/server/_chunks/index-2dv4y4wd.js +1065 -0
- package/dist/server/_chunks/index-2vz0wzdn.js +59 -0
- package/dist/server/_chunks/index-2wfv4kvx.js +182 -0
- package/dist/server/_chunks/index-357na4a8.js +109 -0
- package/dist/server/_chunks/index-3b3at80h.js +109 -0
- package/dist/server/_chunks/index-3tf1xjsp.js +6166 -0
- package/dist/server/_chunks/index-3xbr4eyv.js +105 -0
- package/dist/server/_chunks/index-4399bvd2.js +18 -0
- package/dist/server/_chunks/index-4hgjrqh7.js +851 -0
- package/dist/server/_chunks/index-4q2gbfwk.js +2530 -0
- package/dist/server/_chunks/index-4t92hdxd.js +172 -0
- package/dist/server/_chunks/index-4zzebszd.js +10 -0
- package/dist/server/_chunks/index-5gyr4emz.js +107 -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-6e4fqv30.js +588 -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-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-8k7pfejn.js +1599 -0
- package/dist/server/_chunks/index-8kcxdfya.js +206 -0
- package/dist/server/_chunks/index-91x12ykq.js +274 -0
- package/dist/server/_chunks/index-9ch50vtq.js +18 -0
- package/dist/server/_chunks/index-9hx2641q.js +28 -0
- package/dist/server/_chunks/index-9n2914ww.js +535 -0
- package/dist/server/_chunks/index-9ych9ma8.js +207 -0
- package/dist/server/_chunks/index-b6wtkdp4.js +24 -0
- package/dist/server/_chunks/index-bcws5eh2.js +35 -0
- package/dist/server/_chunks/index-c0g2wf3z.js +92 -0
- package/dist/server/_chunks/index-cf4rvxv6.js +95 -0
- package/dist/server/_chunks/index-cjgqs13g.js +65 -0
- package/dist/server/_chunks/index-ckkdpht5.js +41 -0
- package/dist/server/_chunks/index-cyfednwb.js +87 -0
- package/dist/server/_chunks/index-danncfhy.js +311 -0
- package/dist/server/_chunks/index-dg0f05zs.js +199 -0
- package/dist/server/_chunks/index-e3a6yx84.js +18 -0
- package/dist/server/_chunks/index-e88tyv35.js +45 -0
- package/dist/server/_chunks/index-eajaspjk.js +1253 -0
- package/dist/server/_chunks/index-eeaanp2e.js +483 -0
- package/dist/server/_chunks/index-egykcqg3.js +101 -0
- package/dist/server/_chunks/index-en7n9f7m.js +22 -0
- package/dist/server/_chunks/index-ezgj0tr1.js +88 -0
- package/dist/server/_chunks/index-fkp000p1.js +590 -0
- package/dist/server/_chunks/index-fn1chkkd.js +214 -0
- package/dist/server/_chunks/index-fp8r0sqs.js +64 -0
- package/dist/server/_chunks/index-ggk2j965.js +9432 -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-hkdfj58q.js +92 -0
- package/dist/server/_chunks/index-j2zrcp1k.js +66 -0
- package/dist/server/_chunks/index-jcsjq3d1.js +20 -0
- package/dist/server/_chunks/index-jepjvcrf.js +198 -0
- package/dist/server/_chunks/index-jks0x0a1.js +14 -0
- package/dist/server/_chunks/index-jx7bqvw1.js +57 -0
- package/dist/server/_chunks/index-k1g3epw0.js +1299 -0
- package/dist/server/_chunks/index-knp0s912.js +7 -0
- package/dist/server/_chunks/index-kq8kpzye.js +472 -0
- package/dist/server/_chunks/index-kqyy1d4f.js +50 -0
- package/dist/server/_chunks/index-kresp2n8.js +445 -0
- package/dist/server/_chunks/index-ms9v9tnx.js +31 -0
- package/dist/server/_chunks/index-n4hxpng2.js +11 -0
- package/dist/server/_chunks/index-ncnes8c6.js +17 -0
- package/dist/server/_chunks/index-nqh3xhdc.js +57 -0
- package/dist/server/_chunks/index-nyrba2kr.js +4130 -0
- package/dist/server/_chunks/index-p77b4kcx.js +296 -0
- package/dist/server/_chunks/index-pym1cezq.js +39 -0
- package/dist/server/_chunks/index-q738kkhj.js +100 -0
- package/dist/server/_chunks/index-qjj6gddn.js +54 -0
- package/dist/server/_chunks/index-qm6kmhqs.js +110 -0
- package/dist/server/_chunks/index-qn4z5s3c.js +819 -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-rn8dyr1f.js +126 -0
- package/dist/server/_chunks/index-rt9qq1va.js +4 -0
- package/dist/server/_chunks/index-rthrsed5.js +356 -0
- package/dist/server/_chunks/index-sctcgyvv.js +185 -0
- package/dist/server/_chunks/index-sjpckxqn.js +213 -0
- package/dist/server/_chunks/index-sq3kvz3g.js +200 -0
- package/dist/server/_chunks/index-stbk3jhn.js +31 -0
- package/dist/server/_chunks/index-sv8m6789.js +266 -0
- package/dist/server/_chunks/index-tgcakdxc.js +125 -0
- package/dist/server/_chunks/index-tgsfjmep.js +74 -0
- package/dist/server/_chunks/index-tq0pc7eg.js +154 -0
- package/dist/server/_chunks/index-tq1f96v7.js +51 -0
- package/dist/server/_chunks/index-tqn2qnnn.js +241 -0
- package/dist/server/_chunks/index-tvqkq6e6.js +128 -0
- package/dist/server/_chunks/index-v1ags1na.js +132 -0
- package/dist/server/_chunks/index-vvmmknm1.js +1431 -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-wpfhfbs4.js +194 -0
- package/dist/server/_chunks/index-x0y005nh.js +283 -0
- package/dist/server/_chunks/index-x3yn4ywm.js +22 -0
- package/dist/server/_chunks/index-x93hv0sc.js +271 -0
- package/dist/server/_chunks/index-xvj80c3a.js +30 -0
- package/dist/server/_chunks/index-xywjg2vc.js +100 -0
- package/dist/server/_chunks/index-y2jr2n72.js +152 -0
- package/dist/server/_chunks/index-y36a0ybw.js +57 -0
- package/dist/server/_chunks/index-ye9hmsvf.js +47 -0
- package/dist/server/_chunks/index-yhxkxghe.js +56 -0
- package/dist/server/_chunks/index-ym67zqxp.js +130 -0
- package/dist/server/_chunks/index-ytjvpbm2.js +736 -0
- package/dist/server/_chunks/index-yz54pxrh.js +960 -0
- package/dist/server/_chunks/index-z4z9zv3b.js +733 -0
- package/dist/server/_chunks/index-z84ab1w0.js +1270 -0
- package/dist/server/_chunks/index-z88qv16t.js +11 -0
- package/dist/server/_chunks/index-zqpqyg8p.js +666 -0
- package/dist/server/_chunks/loader-7yw0j98z.js +78 -0
- package/dist/server/_chunks/modules-jn8bmbn8.js +74 -0
- package/dist/server/_chunks/pipeline-yy9jhydf.js +832 -0
- package/dist/server/_chunks/production-jar9ztm3.js +44 -0
- package/dist/server/_chunks/proxy-config-j84dgksn.js +21 -0
- package/dist/server/_chunks/proxy-w1d0wmsn.js +33 -0
- package/dist/server/_chunks/router-k1reahfn.js +498 -0
- package/dist/server/_chunks/routes-2s277fc6.js +64 -0
- package/dist/server/_chunks/run-pvd8bs1t.js +696 -0
- package/dist/server/_chunks/server-mt4a994c.js +1835 -0
- package/dist/server/_chunks/tsconfig-defaults-1nb3308g.js +20 -0
- package/dist/server/_chunks/typegen-0qr0459b.js +35 -0
- package/dist/server/api/client-cache.js +14 -0
- package/dist/server/cli/index.js +378 -0
- package/dist/server/cli/start.js +137 -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 +32 -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 +32 -0
- package/dist/server/compat/next/error.js +112 -0
- package/dist/server/compat/next/font/cache.js +14 -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 +22 -0
- package/dist/server/compat/next/font/runtime-client.js +33 -0
- package/dist/server/compat/next/font/runtime.js +41 -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 +14 -0
- package/dist/server/compat/next/link.js +14 -0
- package/dist/server/compat/next/navigation.js +190 -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 +30 -0
- package/dist/server/compat/next/resource-hints.js +30 -0
- package/dist/server/compat/next/rewrites.js +41 -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/src/api/dynamic.tsx +2 -0
- package/src/api/server.ts +24 -6
- package/src/cli/adapters/vercel-warm.ts +315 -61
- package/src/cli/adapters/vercel.ts +348 -71
- package/src/cli/build.ts +58 -33
- package/src/cli/index.ts +23 -10
- package/src/cli/serve/entry.ts +21 -159
- package/src/cli/serve/immutable.ts +31 -0
- package/src/cli/serve/pipeline.ts +82 -84
- package/src/cli/start.ts +3 -1
- package/src/client/chunk-fold.ts +19 -6
- package/src/client/react-tier.ts +3 -2
- package/src/client/reference-stub.ts +21 -2
- package/src/compat/actions/client-plugin.ts +4 -2
- package/src/compat/actions/config.ts +6 -5
- package/src/compat/actions/extensions.ts +2 -3
- 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/cache-control.ts +16 -8
- package/src/compat/css/modules.ts +18 -5
- package/src/compat/lifecycle/error-funnel.ts +1 -1
- package/src/compat/lifecycle/instrumentation.ts +117 -24
- package/src/compat/lifecycle/testmode.ts +3 -2
- package/src/compat/next/config-loader.ts +137 -13
- package/src/compat/next/font/runtime.ts +22 -2
- 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/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/validation/validate.ts +10 -7
- package/src/config.ts +51 -7
- package/src/css/assets.ts +213 -0
- package/src/css/build.ts +174 -238
- package/src/dev/server.ts +27 -8
- package/src/extensions.ts +4 -0
- package/src/render/hooks.ts +13 -0
- package/src/render/renderer.ts +52 -32
- package/src/request/context.ts +9 -0
- package/src/resolve/dynamic.ts +3 -1
- package/src/resolve/imports.ts +12 -52
- package/src/resolve/package-json.ts +56 -0
- package/src/resolve/scan-facts.ts +65 -0
- package/src/routing/href.ts +10 -3
- package/src/routing/match.ts +287 -0
- package/src/routing/metadata-files.ts +19 -5
- 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 +215 -43
- package/src/runtime/module-cache.ts +13 -0
- package/src/runtime/modules.ts +370 -81
- package/src/runtime/prebundle.ts +81 -0
- package/src/runtime/production.ts +391 -0
- package/src/runtime/release-graph.ts +334 -0
- package/src/runtime/vendor-build.ts +724 -13
- package/src/runtime/vendor.ts +16 -3
- package/src/types.ts +2 -0
- package/src/utils/fs.ts +89 -3
package/src/render/renderer.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { stat, unlink, writeFile } from 'node:fs/promises'
|
|
|
3
3
|
import { basename, dirname, join, relative, sep } from 'node:path'
|
|
4
4
|
import { createHash } from 'node:crypto'
|
|
5
5
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
6
|
-
import { drainPreplanBuilds } from '../runtime/vendor'
|
|
7
6
|
import {
|
|
8
7
|
Component,
|
|
9
8
|
Fragment,
|
|
@@ -29,10 +28,13 @@ import { markErrorLogged } from '../utils/error-log'
|
|
|
29
28
|
import {
|
|
30
29
|
devClientModuleHref,
|
|
31
30
|
devServerModuleHref,
|
|
31
|
+
drainPreplanBuilds,
|
|
32
32
|
importDevModule,
|
|
33
33
|
importModuleOnce,
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
registerServerRuntime,
|
|
35
|
+
serverBundleTargetForRuntime,
|
|
36
|
+
} from '../runtime/load'
|
|
37
|
+
import { conventionFileExists, productionRelease, servedConventions } from '../runtime/production'
|
|
36
38
|
import {
|
|
37
39
|
getActionModuleExtensions,
|
|
38
40
|
getActiveMetadataExtensions,
|
|
@@ -63,7 +65,7 @@ import {
|
|
|
63
65
|
routeCssAssetNames,
|
|
64
66
|
routeCssHref,
|
|
65
67
|
withAssetPrefix,
|
|
66
|
-
} from '../css/
|
|
68
|
+
} from '../css/assets'
|
|
67
69
|
import { dynamicReferenceSymbol, type DynamicReference } from '../api/dynamic'
|
|
68
70
|
import {
|
|
69
71
|
isForbiddenError,
|
|
@@ -98,13 +100,11 @@ import {
|
|
|
98
100
|
trackPrerenderDynamic,
|
|
99
101
|
} from './ppr'
|
|
100
102
|
import {
|
|
101
|
-
collectFileCss,
|
|
102
|
-
collectNotFoundCss,
|
|
103
103
|
findConventionFiles,
|
|
104
104
|
findGlobalError,
|
|
105
105
|
findLayouts,
|
|
106
106
|
serverActionsUnsupportedMessage,
|
|
107
|
-
} from '../routing/
|
|
107
|
+
} from '../routing/match'
|
|
108
108
|
import { matchSegments, pathnameSegments, slotDirectoriesIn } from '../routing/slots'
|
|
109
109
|
import { getRequestRuntime } from '../routing/request-environment'
|
|
110
110
|
import { toNextRequest } from '../api/server'
|
|
@@ -121,7 +121,6 @@ import {
|
|
|
121
121
|
ISLAND_BOUNDARY_ERROR_MESSAGE_ATTRIBUTE,
|
|
122
122
|
} from './boundary-error'
|
|
123
123
|
import { captureCacheScope, runWithCacheScope } from '../request/cache'
|
|
124
|
-
import { registerServerRuntime } from '../runtime/loader'
|
|
125
124
|
import { readText } from '../utils/fs'
|
|
126
125
|
import { traceEnabled } from '../utils/trace-flags'
|
|
127
126
|
import {
|
|
@@ -804,7 +803,7 @@ function moduleHref(file: string, options: ModuleLoadOptions) {
|
|
|
804
803
|
? devServerModuleHref(options.config, file, options.devImportVersion ?? String(Date.now()), {
|
|
805
804
|
conditionTarget,
|
|
806
805
|
})
|
|
807
|
-
: reactCompatEnabled(options.config)
|
|
806
|
+
: reactCompatEnabled(options.config) || productionRelease(options.config)
|
|
808
807
|
? devServerModuleHref(options.config, file, 'build', { conditionTarget })
|
|
809
808
|
: pathToFileHref(file)
|
|
810
809
|
}
|
|
@@ -851,6 +850,17 @@ async function importClientModule(file: string, options: ModuleLoadOptions) {
|
|
|
851
850
|
return importModuleOnce<Record<string, unknown>>(href)
|
|
852
851
|
}
|
|
853
852
|
|
|
853
|
+
/** A synthetic route's CSS: in a release, the stylesheet its build emitted; else a source scan. */
|
|
854
|
+
async function syntheticRouteCss(
|
|
855
|
+
config: ResolvedConfig,
|
|
856
|
+
id: string,
|
|
857
|
+
scan: (routes: typeof import('../routing/routes')) => Promise<string[]>,
|
|
858
|
+
) {
|
|
859
|
+
if (!productionRelease(config)) return scan(await import('../routing/routes'))
|
|
860
|
+
const name = `${id}.css`
|
|
861
|
+
return emittedAssetName(config, name) === name ? [] : [name]
|
|
862
|
+
}
|
|
863
|
+
|
|
854
864
|
function clientScriptPath(route: RouteManifestEntry, dev?: boolean) {
|
|
855
865
|
return dev
|
|
856
866
|
? `/__pnext/client/${route.id}.js`
|
|
@@ -1530,7 +1540,7 @@ async function serializablePageProps(props: PageProps, omitSearchParams = false)
|
|
|
1530
1540
|
|
|
1531
1541
|
export async function staticParamsFor(config: ResolvedConfig, route: RouteManifestEntry) {
|
|
1532
1542
|
const moduleFiles = [
|
|
1533
|
-
...findLayouts(config.appPath, route.file).filter(
|
|
1543
|
+
...findLayouts(config.appPath, route.file).filter(conventionFileExists),
|
|
1534
1544
|
route.file,
|
|
1535
1545
|
]
|
|
1536
1546
|
let paramSets: Record<string, RouteParamValue>[] = [{}]
|
|
@@ -1615,7 +1625,7 @@ export async function renderPage(options: RenderOptions) {
|
|
|
1615
1625
|
export async function renderPageWithStatus(
|
|
1616
1626
|
options: RenderOptions,
|
|
1617
1627
|
): Promise<{ html: string; status: number; location?: string }> {
|
|
1618
|
-
registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1628
|
+
await registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1619
1629
|
await seedPrerenderSidecar(options)
|
|
1620
1630
|
const request = renderScopeRequest(options)
|
|
1621
1631
|
return runWithRequest(
|
|
@@ -1648,7 +1658,7 @@ export async function renderPageWithStatus(
|
|
|
1648
1658
|
}
|
|
1649
1659
|
|
|
1650
1660
|
export async function renderPageStream(options: RenderOptions) {
|
|
1651
|
-
registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1661
|
+
await registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1652
1662
|
await seedPrerenderSidecar(options)
|
|
1653
1663
|
|
|
1654
1664
|
const request = renderScopeRequest(options)
|
|
@@ -1666,7 +1676,7 @@ export async function renderPageStream(options: RenderOptions) {
|
|
|
1666
1676
|
}
|
|
1667
1677
|
|
|
1668
1678
|
export async function renderPageResponse(options: RenderOptions) {
|
|
1669
|
-
registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1679
|
+
await registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1670
1680
|
const method = options.request?.method.toUpperCase() ?? 'GET'
|
|
1671
1681
|
if (method !== 'GET' && method !== 'HEAD') {
|
|
1672
1682
|
return new Response('Method Not Allowed', {
|
|
@@ -1871,7 +1881,7 @@ const rejectedPprShellUpgrades = new Set<string>()
|
|
|
1871
1881
|
* when dynamic data escapes every boundary - the route must then be served fully dynamically.
|
|
1872
1882
|
*/
|
|
1873
1883
|
export async function renderPartialShell(options: RenderOptions): Promise<PrebuiltShell | null> {
|
|
1874
|
-
registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1884
|
+
await registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1875
1885
|
const sidecar = getRenderExtensions().prerenderSidecar
|
|
1876
1886
|
const sidecarContext = prerenderSidecarContext(options)
|
|
1877
1887
|
await sidecar.begin(sidecarContext)
|
|
@@ -1960,7 +1970,7 @@ export async function renderPartialShell(options: RenderOptions): Promise<Prebui
|
|
|
1960
1970
|
export async function renderRuntimePrefetchDocument(
|
|
1961
1971
|
options: RenderOptions,
|
|
1962
1972
|
): Promise<{ html: string; postponed: boolean } | null> {
|
|
1963
|
-
registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1973
|
+
await registerServerRuntime(options.config, options.route.sourceFiles)
|
|
1964
1974
|
// Seed (read-only) the resume-data sidecar so 'use cache' scopes resolve
|
|
1965
1975
|
// their build-time fills; unlike renderPartialShell nothing is collected or
|
|
1966
1976
|
// persisted back.
|
|
@@ -2512,7 +2522,7 @@ function hasParamFreeRootLayout(config: ResolvedConfig): boolean {
|
|
|
2512
2522
|
const cached = paramFreeRootLayoutCache.get(config.appPath)
|
|
2513
2523
|
if (cached !== undefined) return cached
|
|
2514
2524
|
const found = ['tsx', 'jsx', 'ts', 'js'].some(ext =>
|
|
2515
|
-
|
|
2525
|
+
conventionFileExists(join(config.appPath, `layout.${ext}`)),
|
|
2516
2526
|
)
|
|
2517
2527
|
paramFreeRootLayoutCache.set(config.appPath, found)
|
|
2518
2528
|
return found
|
|
@@ -2636,7 +2646,7 @@ export async function renderGlobalNotFoundResponse(
|
|
|
2636
2646
|
) {
|
|
2637
2647
|
const globalFile = ['tsx', 'ts', 'jsx', 'js']
|
|
2638
2648
|
.map(ext => `${options.config.appPath}/global-not-found.${ext}`)
|
|
2639
|
-
.find(
|
|
2649
|
+
.find(conventionFileExists)
|
|
2640
2650
|
// Render as GET regardless of the original method: the 404 page is what a
|
|
2641
2651
|
// browser should see for a stray POST too (Next's MPA fallback), not a 405.
|
|
2642
2652
|
const notFoundRequest = options.request
|
|
@@ -2664,9 +2674,9 @@ export async function renderGlobalNotFoundResponse(
|
|
|
2664
2674
|
// Include CSS shared with the root layout: this document replaces the
|
|
2665
2675
|
// whole page (no root layout render), so the global sheet isn't linked
|
|
2666
2676
|
// and anything it covered must ship in this route's own chunk.
|
|
2667
|
-
cssImports: await
|
|
2668
|
-
includeGlobalCss: true,
|
|
2669
|
-
|
|
2677
|
+
cssImports: await syntheticRouteCss(options.config, 'global-not-found', routes =>
|
|
2678
|
+
routes.collectFileCss(options.config.appPath, [globalFile], { includeGlobalCss: true }),
|
|
2679
|
+
),
|
|
2670
2680
|
sourceFiles: [globalFile],
|
|
2671
2681
|
synthetic: true,
|
|
2672
2682
|
}
|
|
@@ -2706,7 +2716,9 @@ export async function renderGlobalNotFoundResponse(
|
|
|
2706
2716
|
clientReferences: rootRoute?.clientReferences ?? [],
|
|
2707
2717
|
// Root not-found ships its own CSS (`/assets/not-found.css`) alongside the
|
|
2708
2718
|
// root-layout global sheet (`/assets/global.css`, emitted via globalCssHref).
|
|
2709
|
-
cssImports: await
|
|
2719
|
+
cssImports: await syntheticRouteCss(options.config, 'not-found', routes =>
|
|
2720
|
+
routes.collectNotFoundCss(options.config.appPath),
|
|
2721
|
+
),
|
|
2710
2722
|
sourceFiles: rootRoute?.sourceFiles ?? [anchor],
|
|
2711
2723
|
...(rootRoute?.needsRouterEntry ? { needsRouterEntry: true } : {}),
|
|
2712
2724
|
// Serve the ROOT route's built client entry: the synthetic id has no
|
|
@@ -2863,6 +2875,8 @@ const documentLayoutDefaults = new Map<string, { mtimeMs: number; hasDefault: bo
|
|
|
2863
2875
|
async function routeHasDocumentLayout(layoutFiles: string[]) {
|
|
2864
2876
|
const rootLayout = layoutFiles[0]
|
|
2865
2877
|
if (!rootLayout) return false
|
|
2878
|
+
const served = servedConventions()
|
|
2879
|
+
if (served) return served.documentLayouts.has(rootLayout)
|
|
2866
2880
|
let mtimeMs: number
|
|
2867
2881
|
try {
|
|
2868
2882
|
mtimeMs = statSync(rootLayout).mtimeMs
|
|
@@ -2923,7 +2937,7 @@ async function pageRender(options: RenderOptions, stream: boolean): Promise<Page
|
|
|
2923
2937
|
// Drop the non-existent anchor file so we don't try to import it; the
|
|
2924
2938
|
// layout's `children` is supplied by the `@children` slot instead (see
|
|
2925
2939
|
// childrenFromSlots).
|
|
2926
|
-
if (pageFile && !
|
|
2940
|
+
if (pageFile && !conventionFileExists(pageFile)) pageFile = undefined
|
|
2927
2941
|
}
|
|
2928
2942
|
const props = profileRenderSyncStep(profile, 'create page props', () =>
|
|
2929
2943
|
createPageProps(options),
|
|
@@ -3254,7 +3268,7 @@ async function renderAuthInterruptPage(
|
|
|
3254
3268
|
const fallbackTree = httpAccessFallbackTree(status, message)
|
|
3255
3269
|
const file = nearestConventionFile(options, `${kind}.tsx`)
|
|
3256
3270
|
const boundaryOptions = optionsForNotFoundBoundary(options, file)
|
|
3257
|
-
if (!file || !
|
|
3271
|
+
if (!file || !conventionFileExists(file)) {
|
|
3258
3272
|
return renderTreeOrFallback(
|
|
3259
3273
|
boundaryOptions,
|
|
3260
3274
|
fallbackTree,
|
|
@@ -3322,7 +3336,7 @@ async function renderGlobalErrorPage(
|
|
|
3322
3336
|
// global-error.js is a client component ('use client'): import it through
|
|
3323
3337
|
// the client module loader and SSR it to a full document. Server components
|
|
3324
3338
|
// (no directive) load through the server loader.
|
|
3325
|
-
const clientDirective =
|
|
3339
|
+
const clientDirective = await conventionUsesClient(file)
|
|
3326
3340
|
const module = (
|
|
3327
3341
|
clientDirective ? await importClientModule(file, options) : await importModule(file, options)
|
|
3328
3342
|
) as ErrorModule
|
|
@@ -3956,7 +3970,7 @@ async function renderTreeInFrame(
|
|
|
3956
3970
|
// global-not-found replaces the document without the root layout, so the
|
|
3957
3971
|
// root layout's global sheet must not load (its CSS ships in the route's
|
|
3958
3972
|
// own chunk, built with includeGlobalCss).
|
|
3959
|
-
options.route.id === 'global-not-found' ? undefined : globalCssHref(options.config)
|
|
3973
|
+
options.route.id === 'global-not-found' ? undefined : await globalCssHref(options.config)
|
|
3960
3974
|
let routeStylesheet = routeCssHref(options.route, options.config)
|
|
3961
3975
|
// File names, not logical ones: the inline path READS these off disk, so it has
|
|
3962
3976
|
// to spell them the way the build emitted them (content-hashed in production).
|
|
@@ -4378,7 +4392,7 @@ async function buildLoadingBoundaries(
|
|
|
4378
4392
|
options.route.file,
|
|
4379
4393
|
'loading.tsx',
|
|
4380
4394
|
)) {
|
|
4381
|
-
if (!
|
|
4395
|
+
if (!conventionFileExists(loadingFile)) continue
|
|
4382
4396
|
const fallback = await buildLoadingFallback(options, loadingFile)
|
|
4383
4397
|
if (fallback) fallbackByDir.set(dirname(loadingFile), fallback)
|
|
4384
4398
|
}
|
|
@@ -4485,7 +4499,7 @@ async function renderNotFoundPage(
|
|
|
4485
4499
|
// A `'use client'` not-found.js with a discovered client reference renders as an island (same as
|
|
4486
4500
|
// error.js) so it HYDRATES - its hooks must work on the 404 document. Server-rendering it would
|
|
4487
4501
|
// serialize child event-handler props as dead action stubs.
|
|
4488
|
-
const clientDirective =
|
|
4502
|
+
const clientDirective = await conventionUsesClient(file)
|
|
4489
4503
|
const clientReference = clientDirective
|
|
4490
4504
|
? conventionDefaultReference(notFoundOptions, file)
|
|
4491
4505
|
: undefined
|
|
@@ -4598,7 +4612,7 @@ async function renderErrorPage(options: RenderOptions, error: unknown, stream: b
|
|
|
4598
4612
|
if (!file) return renderGenericErrorPage(options, resolvedError, stream)
|
|
4599
4613
|
|
|
4600
4614
|
try {
|
|
4601
|
-
const clientDirective =
|
|
4615
|
+
const clientDirective = await conventionUsesClient(file)
|
|
4602
4616
|
const module = (
|
|
4603
4617
|
clientDirective ? await importClientModule(file, options) : await importModule(file, options)
|
|
4604
4618
|
) as ErrorModule
|
|
@@ -4867,10 +4881,16 @@ function generatedFallbackPage(
|
|
|
4867
4881
|
}
|
|
4868
4882
|
}
|
|
4869
4883
|
|
|
4884
|
+
/** Whether a convention file is `'use client'`: the frozen fact in production, its source otherwise. */
|
|
4885
|
+
async function conventionUsesClient(file: string) {
|
|
4886
|
+
const served = servedConventions()
|
|
4887
|
+
return served ? served.client.has(file) : hasUseClientDirective(await readText(file))
|
|
4888
|
+
}
|
|
4889
|
+
|
|
4870
4890
|
function nearestConventionFile(options: RenderOptions, name: string) {
|
|
4871
4891
|
return [...findConventionFiles(options.config.appPath, options.route.file, name)]
|
|
4872
4892
|
.reverse()
|
|
4873
|
-
.find(
|
|
4893
|
+
.find(conventionFileExists)
|
|
4874
4894
|
}
|
|
4875
4895
|
|
|
4876
4896
|
/**
|
|
@@ -6541,7 +6561,7 @@ function dynamicTargetReference(
|
|
|
6541
6561
|
const target = dynamicReference.target
|
|
6542
6562
|
if (!target) return undefined
|
|
6543
6563
|
const stored = state.clientReferences.get(
|
|
6544
|
-
`c-${clientReferenceId(target.file, target.exportName)}`,
|
|
6564
|
+
target.id ?? `c-${clientReferenceId(target.file, target.exportName)}`,
|
|
6545
6565
|
)
|
|
6546
6566
|
if (stored) return stored
|
|
6547
6567
|
for (const reference of state.clientReferences.values()) {
|
|
@@ -7616,7 +7636,7 @@ async function applyLayouts(
|
|
|
7616
7636
|
await profileRenderStep(profile, 'import layouts', async () => {
|
|
7617
7637
|
for (const layoutPath of options.layoutFiles ??
|
|
7618
7638
|
findLayouts(options.config.appPath, options.route.file)) {
|
|
7619
|
-
if (!options.moduleLoader && !
|
|
7639
|
+
if (!options.moduleLoader && !conventionFileExists(layoutPath)) continue
|
|
7620
7640
|
const layoutModule = (await importModule(layoutPath, options)) as LayoutModule
|
|
7621
7641
|
markServerReference(layoutModule.default)
|
|
7622
7642
|
// Cheap leaf span for the segment-module resolution (nested under the
|
|
@@ -8025,7 +8045,7 @@ function fullSegmentPrefetchSkipsSharedLayout(options: RenderOptions): boolean {
|
|
|
8025
8045
|
options.config.appPath,
|
|
8026
8046
|
options.route.file,
|
|
8027
8047
|
'layout.tsx',
|
|
8028
|
-
).filter(
|
|
8048
|
+
).filter(conventionFileExists)
|
|
8029
8049
|
const documentDir = layoutFiles[0] ? dirname(layoutFiles[0]) : undefined
|
|
8030
8050
|
return layoutFiles
|
|
8031
8051
|
.slice(1)
|
package/src/request/context.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
PostponeError,
|
|
9
9
|
} from '../render/ppr'
|
|
10
10
|
import type { NextRequest, RouteParamValue } from '../types'
|
|
11
|
+
import type { Release } from '../runtime/production'
|
|
11
12
|
|
|
12
13
|
// Request work-unit store (CORE seam for compat after()/onRequestError).
|
|
13
14
|
//
|
|
@@ -46,6 +47,8 @@ export interface WorkUnit {
|
|
|
46
47
|
* grows no dependency on compat.
|
|
47
48
|
*/
|
|
48
49
|
compat?: Record<symbol, unknown>
|
|
50
|
+
/** The production release this request serves from; dev and build leave it unset. */
|
|
51
|
+
release?: Release
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
// Anchored on globalThis (like requestStorage below) so compiled compat
|
|
@@ -67,6 +70,12 @@ export function getWorkUnit(): WorkUnit | undefined {
|
|
|
67
70
|
return workUnitStorage.getStore()
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
/** Mark the current work unit as serving `release` (production reads its app facts from it). */
|
|
74
|
+
export function setWorkUnitRelease(release: Release): void {
|
|
75
|
+
const unit = workUnitStorage.getStore()
|
|
76
|
+
if (unit) unit.release = release
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
/** Set the current work-unit phase (compat toggles render/action/handler/...). */
|
|
71
80
|
export function setPhase(phase: WorkUnitPhase): void {
|
|
72
81
|
const unit = workUnitStorage.getStore()
|
package/src/resolve/dynamic.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clientReferenceId } from '../client/reference'
|
|
1
2
|
import { dynamicCallFacts, rewriteFacts, type DynamicCallFact } from './scan-facts'
|
|
2
3
|
|
|
3
4
|
export interface DynamicCall {
|
|
@@ -132,7 +133,8 @@ export function rewriteDynamicCallTargets(
|
|
|
132
133
|
const args = source.slice(call.open + 1, call.close)
|
|
133
134
|
const argCount = topLevelArgCount(args)
|
|
134
135
|
if (argCount < 1 || argCount > 2) continue
|
|
135
|
-
const
|
|
136
|
+
const id = `c-${clientReferenceId(file, target.exportName)}`
|
|
137
|
+
const literal = JSON.stringify({ file, exportName: target.exportName, id })
|
|
136
138
|
const separator = /,\s*$/.test(args) ? '' : ', '
|
|
137
139
|
edits.push({
|
|
138
140
|
at: call.close,
|
package/src/resolve/imports.ts
CHANGED
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
tsConfigFileFor,
|
|
11
11
|
} from './engine'
|
|
12
12
|
import { onExtensionHostReset } from '../extensions'
|
|
13
|
+
import { findWorkspaceRoot, readPackageJson, type PackageJson } from './package-json'
|
|
14
|
+
|
|
15
|
+
export { findWorkspaceRoot }
|
|
13
16
|
|
|
14
17
|
// `Bun` through globalThis: pnext ships TypeScript source, so app compilers without
|
|
15
18
|
// bun-types typecheck this file and a bare `Bun` identifier would fail them.
|
|
@@ -45,6 +48,8 @@ export interface ExternalPackagePolicy {
|
|
|
45
48
|
* transpile.
|
|
46
49
|
*/
|
|
47
50
|
transpiled?: () => readonly string[]
|
|
51
|
+
/** Kept out of a release's server dependency graph beyond `external`: Next's built-in list. */
|
|
52
|
+
releaseExternal?: (packageName: string) => boolean
|
|
48
53
|
/** ESM external mode for package exports interop. */
|
|
49
54
|
esmExternals: () => boolean | 'loose'
|
|
50
55
|
}
|
|
@@ -94,9 +99,14 @@ export function resolveExternalLoadTarget(context: ExternalLoadContext): string
|
|
|
94
99
|
// `#imports` resolve from the importer's OWN package, so they are not
|
|
95
100
|
// shareable across a resolution root; they stay uncached.
|
|
96
101
|
if (context.specifier.startsWith('#')) return externalLoadResolver(context)
|
|
97
|
-
|
|
102
|
+
// A node_modules importer resolves from its own directory, as Node does: a version nested under
|
|
103
|
+
// its package wins over the hoisted one.
|
|
104
|
+
const resolveContext = context.fromFile.includes(`${path.sep}node_modules${path.sep}`)
|
|
105
|
+
? { ...context, root: path.dirname(context.fromFile) }
|
|
106
|
+
: context
|
|
107
|
+
const key = `${context.target}\0${resolutionRootForFile(resolveContext.root, context.fromFile)}\0${context.specifier}`
|
|
98
108
|
if (externalLoadTargets.has(key)) return externalLoadTargets.get(key)
|
|
99
|
-
const target = externalLoadResolver(
|
|
109
|
+
const target = externalLoadResolver(resolveContext)
|
|
100
110
|
externalLoadTargets.set(key, target)
|
|
101
111
|
return target
|
|
102
112
|
}
|
|
@@ -143,22 +153,6 @@ export function setTsConfigPath(file: string | undefined): void {
|
|
|
143
153
|
clearVendorPackageResolutions()
|
|
144
154
|
}
|
|
145
155
|
|
|
146
|
-
interface PackageJson {
|
|
147
|
-
name?: string
|
|
148
|
-
type?: string
|
|
149
|
-
browser?: string
|
|
150
|
-
main?: string
|
|
151
|
-
module?: string
|
|
152
|
-
source?: string
|
|
153
|
-
exports?: PackageExport
|
|
154
|
-
imports?: Record<string, PackageExport>
|
|
155
|
-
dependencies?: Record<string, string>
|
|
156
|
-
devDependencies?: Record<string, string>
|
|
157
|
-
optionalDependencies?: Record<string, string>
|
|
158
|
-
peerDependencies?: Record<string, string>
|
|
159
|
-
workspaces?: string[] | { packages?: string[] }
|
|
160
|
-
}
|
|
161
|
-
|
|
162
156
|
// Compat (or any bundler extension) registers its bare-specifier to file aliases here (e.g. `next/form` ->
|
|
163
157
|
// `src/compat/next/form.tsx`). Core's own route scanner has no static knowledge of those aliases otherwise,
|
|
164
158
|
// so a server component importing a 'use client' compat module would never be walked into and its client
|
|
@@ -886,25 +880,6 @@ export function commonJsModuleHasDefaultExport(source: string, file: string) {
|
|
|
886
880
|
)
|
|
887
881
|
}
|
|
888
882
|
|
|
889
|
-
export function findWorkspaceRoot(root: string) {
|
|
890
|
-
const key = path.resolve(root)
|
|
891
|
-
if (workspaceRootCache.has(key)) return workspaceRootCache.get(key)
|
|
892
|
-
|
|
893
|
-
let dir = key
|
|
894
|
-
while (true) {
|
|
895
|
-
if (readPackageJson(dir).workspaces || existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {
|
|
896
|
-
workspaceRootCache.set(key, dir)
|
|
897
|
-
return dir
|
|
898
|
-
}
|
|
899
|
-
const parent = path.dirname(dir)
|
|
900
|
-
if (parent === dir) {
|
|
901
|
-
workspaceRootCache.set(key, undefined)
|
|
902
|
-
return undefined
|
|
903
|
-
}
|
|
904
|
-
dir = parent
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
883
|
function isInside(root: string, file: string) {
|
|
909
884
|
const relative = path.relative(root, file)
|
|
910
885
|
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))
|
|
@@ -962,8 +937,6 @@ function readPnpmWorkspacePatterns(root: string) {
|
|
|
962
937
|
}
|
|
963
938
|
|
|
964
939
|
const tsConfigCache = new Map<string, TsConfig>()
|
|
965
|
-
const packageJsonCache = new Map<string, PackageJson>()
|
|
966
|
-
const workspaceRootCache = new Map<string, string | undefined>()
|
|
967
940
|
const workspacePackageCache = new Map<string, Map<string, string>>()
|
|
968
941
|
|
|
969
942
|
function readTsConfig(root: string) {
|
|
@@ -975,14 +948,6 @@ function readTsConfig(root: string) {
|
|
|
975
948
|
return config
|
|
976
949
|
}
|
|
977
950
|
|
|
978
|
-
function readPackageJson(root: string) {
|
|
979
|
-
const existing = packageJsonCache.get(root)
|
|
980
|
-
if (existing) return existing
|
|
981
|
-
const config = readJson<PackageJson>(path.join(root, 'package.json')) ?? {}
|
|
982
|
-
packageJsonCache.set(root, config)
|
|
983
|
-
return config
|
|
984
|
-
}
|
|
985
|
-
|
|
986
951
|
function workspacePackages(root: string) {
|
|
987
952
|
const existing = workspacePackageCache.get(root)
|
|
988
953
|
if (existing) return existing
|
|
@@ -1027,11 +992,6 @@ export function workspacePackageRoots(root: string) {
|
|
|
1027
992
|
return [...workspacePackages(path.resolve(root)).values()].sort()
|
|
1028
993
|
}
|
|
1029
994
|
|
|
1030
|
-
function readJson<T>(file: string) {
|
|
1031
|
-
if (!existsSync(file)) return undefined
|
|
1032
|
-
return JSON.parse(readFileSync(file, 'utf8')) as T
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
995
|
function readJsonc<T>(file: string) {
|
|
1036
996
|
if (!existsSync(file)) return undefined
|
|
1037
997
|
return JSON.parse(stripTrailingCommas(stripJsonComments(readFileSync(file, 'utf8')))) as T
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// package.json reads and workspace-root discovery, which config loading needs without the resolver.
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
type PackageExport = unknown
|
|
6
|
+
|
|
7
|
+
export interface PackageJson {
|
|
8
|
+
name?: string
|
|
9
|
+
type?: string
|
|
10
|
+
browser?: string
|
|
11
|
+
main?: string
|
|
12
|
+
module?: string
|
|
13
|
+
source?: string
|
|
14
|
+
exports?: PackageExport
|
|
15
|
+
imports?: Record<string, PackageExport>
|
|
16
|
+
dependencies?: Record<string, string>
|
|
17
|
+
devDependencies?: Record<string, string>
|
|
18
|
+
optionalDependencies?: Record<string, string>
|
|
19
|
+
peerDependencies?: Record<string, string>
|
|
20
|
+
workspaces?: string[] | { packages?: string[] }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const packageJsonCache = new Map<string, PackageJson>()
|
|
24
|
+
const workspaceRootCache = new Map<string, string | undefined>()
|
|
25
|
+
|
|
26
|
+
export function readPackageJson(root: string) {
|
|
27
|
+
const existing = packageJsonCache.get(root)
|
|
28
|
+
if (existing) return existing
|
|
29
|
+
const config = readJson<PackageJson>(path.join(root, 'package.json')) ?? {}
|
|
30
|
+
packageJsonCache.set(root, config)
|
|
31
|
+
return config
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function findWorkspaceRoot(root: string) {
|
|
35
|
+
const key = path.resolve(root)
|
|
36
|
+
if (workspaceRootCache.has(key)) return workspaceRootCache.get(key)
|
|
37
|
+
|
|
38
|
+
let dir = key
|
|
39
|
+
while (true) {
|
|
40
|
+
if (readPackageJson(dir).workspaces || existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {
|
|
41
|
+
workspaceRootCache.set(key, dir)
|
|
42
|
+
return dir
|
|
43
|
+
}
|
|
44
|
+
const parent = path.dirname(dir)
|
|
45
|
+
if (parent === dir) {
|
|
46
|
+
workspaceRootCache.set(key, undefined)
|
|
47
|
+
return undefined
|
|
48
|
+
}
|
|
49
|
+
dir = parent
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readJson<T>(file: string) {
|
|
54
|
+
if (!existsSync(file)) return undefined
|
|
55
|
+
return JSON.parse(readFileSync(file, 'utf8')) as T
|
|
56
|
+
}
|
|
@@ -581,6 +581,71 @@ function child(node: AstNode | undefined, key: string): AstNode | undefined {
|
|
|
581
581
|
return isNode(value) ? value : undefined
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
+
/**
|
|
585
|
+
* Drop `type: "json"` attributes from the import declarations and `import()` calls whose target
|
|
586
|
+
* `compiled` claims: the target is JS, which a native load would parse as JSON.
|
|
587
|
+
*/
|
|
588
|
+
export function stripJsonImportAttributes(
|
|
589
|
+
source: string,
|
|
590
|
+
file: string,
|
|
591
|
+
compiled: (specifier: string) => boolean,
|
|
592
|
+
) {
|
|
593
|
+
const result = parseSync(file, source, { lang: 'js', sourceType: 'module' })
|
|
594
|
+
if (result.errors.length > 0) return source
|
|
595
|
+
const edits: { start: number; end: number; value: string }[] = []
|
|
596
|
+
const visit = (node: AstNode) => {
|
|
597
|
+
const target = child(node, 'source')
|
|
598
|
+
const specifier = stringValue(target)
|
|
599
|
+
if (target && specifier !== undefined && compiled(specifier)) {
|
|
600
|
+
const attributes = node.attributes as AstNode[] | undefined
|
|
601
|
+
const options = child(node, 'options')
|
|
602
|
+
if (attributes?.length && attributes.every(jsonTypeAttribute)) {
|
|
603
|
+
const end = source.indexOf('}', attributes.at(-1)!.end) + 1
|
|
604
|
+
edits.push({ start: target.end, end, value: '' })
|
|
605
|
+
} else if (node.type === 'ImportExpression' && options && jsonImportOptions(options)) {
|
|
606
|
+
edits.push({ start: target.end, end: options.end, value: '' })
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
for (const value of Object.values(node)) {
|
|
610
|
+
if (isNode(value)) visit(value)
|
|
611
|
+
else if (Array.isArray(value)) for (const item of value) if (isNode(item)) visit(item)
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
visit(result.program as unknown as AstNode)
|
|
615
|
+
return edits.length > 0 ? spliceSource(source, edits) : source
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function propertyName(node: AstNode | undefined) {
|
|
619
|
+
if (!node) return undefined
|
|
620
|
+
return node.type === 'Identifier' ? (node.name as string) : stringValue(node)
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
function jsonTypeAttribute(node: AstNode) {
|
|
624
|
+
return (
|
|
625
|
+
!node.computed &&
|
|
626
|
+
propertyName(child(node, 'key')) === 'type' &&
|
|
627
|
+
stringValue(child(node, 'value')) === 'json'
|
|
628
|
+
)
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/** `{ with: { type: 'json' } }` (or `assert`) and nothing else. */
|
|
632
|
+
function jsonImportOptions(options: AstNode) {
|
|
633
|
+
const [property, ...rest] = (options.properties as AstNode[] | undefined) ?? []
|
|
634
|
+
const attributes = child(property, 'value')
|
|
635
|
+
const entries = attributes?.properties as AstNode[] | undefined
|
|
636
|
+
return (
|
|
637
|
+
options.type === 'ObjectExpression' &&
|
|
638
|
+
!!property &&
|
|
639
|
+
rest.length === 0 &&
|
|
640
|
+
property.type === 'Property' &&
|
|
641
|
+
!property.computed &&
|
|
642
|
+
['with', 'assert'].includes(propertyName(child(property, 'key')) ?? '') &&
|
|
643
|
+
attributes?.type === 'ObjectExpression' &&
|
|
644
|
+
!!entries?.length &&
|
|
645
|
+
entries.every(entry => entry.type === 'Property' && jsonTypeAttribute(entry))
|
|
646
|
+
)
|
|
647
|
+
}
|
|
648
|
+
|
|
584
649
|
function collectDynamicCalls(program: AstNode): DynamicCallFact[] {
|
|
585
650
|
const calls: DynamicCallFact[] = []
|
|
586
651
|
const visit = (value: unknown) => {
|
package/src/routing/href.ts
CHANGED
|
@@ -198,7 +198,16 @@ export function canonicalTrailingSlashPath(pathname: string, trailingSlash: bool
|
|
|
198
198
|
if (/\.[^/]+$/.test(pathname)) return pathname
|
|
199
199
|
const slashed = pathname.endsWith('/')
|
|
200
200
|
if (trailingSlash ? slashed : !slashed) return pathname
|
|
201
|
-
|
|
201
|
+
// Collapsed, so a rewritten path can never read as protocol-relative (`//host`).
|
|
202
|
+
const bare = pathname.replace(/\/{2,}/g, '/').replace(/\/+$/, '')
|
|
203
|
+
return trailingSlash ? `${bare}/` : bare || '/'
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Next 308s a path with repeated slashes to its collapsed form, for every method, before anything else. */
|
|
207
|
+
export function repeatedSlashRedirect(url: URL): Response | null {
|
|
208
|
+
if (!url.pathname.includes('//')) return null
|
|
209
|
+
const target = `${url.pathname.replace(/\/{2,}/g, '/')}${url.search}`
|
|
210
|
+
return new Response(target, { status: 308, headers: { location: target } })
|
|
202
211
|
}
|
|
203
212
|
|
|
204
213
|
/**
|
|
@@ -210,13 +219,11 @@ export function canonicalTrailingSlashPath(pathname: string, trailingSlash: bool
|
|
|
210
219
|
export function trailingSlashRedirect(
|
|
211
220
|
config: { trailingSlash?: boolean; skipTrailingSlashRedirect?: boolean },
|
|
212
221
|
url: URL,
|
|
213
|
-
method: string,
|
|
214
222
|
): Response | null {
|
|
215
223
|
// skipTrailingSlashRedirect: the app serves both slashed and unslashed URLs
|
|
216
224
|
// as-is, so no canonical redirect is ever emitted (route matching already
|
|
217
225
|
// tolerates a trailing slash via normalizePathname).
|
|
218
226
|
if (config.skipTrailingSlashRedirect) return null
|
|
219
|
-
if (method !== 'GET' && method !== 'HEAD') return null
|
|
220
227
|
const pathname = url.pathname
|
|
221
228
|
if (pathname === '/' || pathname === '') return null
|
|
222
229
|
if (pathname.startsWith('/__pnext') || isBuildAssetPathname(pathname)) return null
|