@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
|
@@ -0,0 +1,2530 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
coerceString,
|
|
4
|
+
settledPromise,
|
|
5
|
+
staticMetadataForPathFromFiles
|
|
6
|
+
} from "./index-3tf1xjsp.js";
|
|
7
|
+
import {
|
|
8
|
+
RSC_CONTENT_TYPE_HEADER
|
|
9
|
+
} from "./index-stbk3jhn.js";
|
|
10
|
+
import {
|
|
11
|
+
createVaryingParams,
|
|
12
|
+
createVaryingSearchParams,
|
|
13
|
+
getMetadataVaryParamsAccumulator,
|
|
14
|
+
varyNamesFor,
|
|
15
|
+
varyTrackingInfo
|
|
16
|
+
} from "./index-x0y005nh.js";
|
|
17
|
+
import {
|
|
18
|
+
readSourceSync,
|
|
19
|
+
readSourceText
|
|
20
|
+
} from "./index-fp8r0sqs.js";
|
|
21
|
+
import {
|
|
22
|
+
getNextConfig
|
|
23
|
+
} from "./index-6e4fqv30.js";
|
|
24
|
+
import {
|
|
25
|
+
getWorkUnit,
|
|
26
|
+
legacyRequestAPIs,
|
|
27
|
+
queueAfterTask
|
|
28
|
+
} from "./index-grta8ap3.js";
|
|
29
|
+
import {
|
|
30
|
+
extraPageExtensions
|
|
31
|
+
} from "./index-zqpqyg8p.js";
|
|
32
|
+
import {
|
|
33
|
+
stripComments
|
|
34
|
+
} from "./index-qjj6gddn.js";
|
|
35
|
+
|
|
36
|
+
// src/compat/otel/api.ts
|
|
37
|
+
import { createRequire } from "module";
|
|
38
|
+
import path from "path";
|
|
39
|
+
var resolved;
|
|
40
|
+
function getOtelApi(appRoot) {
|
|
41
|
+
if (resolved !== undefined)
|
|
42
|
+
return resolved;
|
|
43
|
+
resolved = null;
|
|
44
|
+
try {
|
|
45
|
+
const req = createRequire(path.join(appRoot, "package.json"));
|
|
46
|
+
const api = req("@opentelemetry/api");
|
|
47
|
+
if (api?.trace && api.context)
|
|
48
|
+
resolved = api;
|
|
49
|
+
} catch {
|
|
50
|
+
resolved = null;
|
|
51
|
+
}
|
|
52
|
+
return resolved;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/compat/otel/tracer.ts
|
|
56
|
+
var SPAN_TYPE = {
|
|
57
|
+
handleRequest: "BaseServer.handleRequest",
|
|
58
|
+
getBodyResult: "AppRender.getBodyResult",
|
|
59
|
+
fetch: "AppRender.fetch",
|
|
60
|
+
runHandler: "AppRouteRouteHandlers.runHandler",
|
|
61
|
+
generateMetadata: "ResolveMetadata.generateMetadata",
|
|
62
|
+
createComponentTree: "NextNodeServer.createComponentTree",
|
|
63
|
+
getLayoutOrPageModule: "NextNodeServer.getLayoutOrPageModule",
|
|
64
|
+
findPageComponents: "NextNodeServer.findPageComponents",
|
|
65
|
+
startResponse: "NextNodeServer.startResponse",
|
|
66
|
+
clientComponentLoading: "NextNodeServer.clientComponentLoading",
|
|
67
|
+
middleware: "Middleware.execute",
|
|
68
|
+
getRequestHandler: "NextServer.getRequestHandler",
|
|
69
|
+
nodeRunHandler: "Node.runHandler",
|
|
70
|
+
renderDocument: "Render.renderDocument",
|
|
71
|
+
getServerSideProps: "Render.getServerSideProps",
|
|
72
|
+
getStaticProps: "Render.getStaticProps"
|
|
73
|
+
};
|
|
74
|
+
var EDGE_SANDBOX_SPAN_TYPES = new Set([
|
|
75
|
+
SPAN_TYPE.getBodyResult,
|
|
76
|
+
SPAN_TYPE.createComponentTree,
|
|
77
|
+
SPAN_TYPE.getLayoutOrPageModule,
|
|
78
|
+
SPAN_TYPE.generateMetadata,
|
|
79
|
+
SPAN_TYPE.fetch,
|
|
80
|
+
SPAN_TYPE.renderDocument,
|
|
81
|
+
SPAN_TYPE.getServerSideProps,
|
|
82
|
+
SPAN_TYPE.getStaticProps
|
|
83
|
+
]);
|
|
84
|
+
var OTEL_STATE = Symbol.for("pnext.compat.otel.state");
|
|
85
|
+
function childRuntime(state, spanType) {
|
|
86
|
+
return state.edgeMode === "page" && EDGE_SANDBOX_SPAN_TYPES.has(spanType) ? "edge" : "nodejs";
|
|
87
|
+
}
|
|
88
|
+
var cachedAppRoot;
|
|
89
|
+
var spanEndDepth = 0;
|
|
90
|
+
function setOtelAppRoot(root) {
|
|
91
|
+
cachedAppRoot = root;
|
|
92
|
+
}
|
|
93
|
+
function api() {
|
|
94
|
+
return cachedAppRoot ? getOtelApi(cachedAppRoot) : null;
|
|
95
|
+
}
|
|
96
|
+
function stateOf(unit) {
|
|
97
|
+
return unit?.compat?.[OTEL_STATE];
|
|
98
|
+
}
|
|
99
|
+
function startRootSpan(input) {
|
|
100
|
+
const a = api();
|
|
101
|
+
if (!a)
|
|
102
|
+
return;
|
|
103
|
+
const unit = getWorkUnit();
|
|
104
|
+
if (!unit)
|
|
105
|
+
return;
|
|
106
|
+
unit.compat ??= {};
|
|
107
|
+
if (unit.compat[OTEL_STATE])
|
|
108
|
+
return;
|
|
109
|
+
const carrier = {};
|
|
110
|
+
input.headers.forEach((value, key) => {
|
|
111
|
+
carrier[key] = value;
|
|
112
|
+
});
|
|
113
|
+
const incomingContext = a.propagation.extract(a.context.active(), carrier, headerGetter);
|
|
114
|
+
const spanName = `${input.rsc ? "RSC " : ""}${input.method} ${input.target}`;
|
|
115
|
+
const tracer = a.trace.getTracer("next.js", "0.0.1");
|
|
116
|
+
let verboseSpan;
|
|
117
|
+
let rootParentCtx = incomingContext;
|
|
118
|
+
if (process.env.NEXT_OTEL_VERBOSE === "1") {
|
|
119
|
+
verboseSpan = tracer.startSpan(SPAN_TYPE.getRequestHandler, {
|
|
120
|
+
kind: a.SpanKind.INTERNAL,
|
|
121
|
+
attributes: {
|
|
122
|
+
"next.span_name": SPAN_TYPE.getRequestHandler,
|
|
123
|
+
"next.span_type": SPAN_TYPE.getRequestHandler
|
|
124
|
+
}
|
|
125
|
+
}, incomingContext);
|
|
126
|
+
rootParentCtx = a.trace.setSpan(incomingContext, verboseSpan);
|
|
127
|
+
}
|
|
128
|
+
const rootSpan = tracer.startSpan(spanName, {
|
|
129
|
+
kind: a.SpanKind.SERVER,
|
|
130
|
+
attributes: {
|
|
131
|
+
"http.method": input.method,
|
|
132
|
+
"http.target": input.target,
|
|
133
|
+
"next.rsc": input.rsc,
|
|
134
|
+
"next.span_name": spanName,
|
|
135
|
+
"next.span_type": SPAN_TYPE.handleRequest
|
|
136
|
+
}
|
|
137
|
+
}, rootParentCtx);
|
|
138
|
+
const rootContext = a.trace.setSpan(rootParentCtx, rootSpan);
|
|
139
|
+
const state = {
|
|
140
|
+
api: a,
|
|
141
|
+
rootContext,
|
|
142
|
+
rootSpan,
|
|
143
|
+
rootEnded: false,
|
|
144
|
+
method: input.method,
|
|
145
|
+
rsc: input.rsc,
|
|
146
|
+
target: input.target,
|
|
147
|
+
incomingContext,
|
|
148
|
+
...verboseSpan ? { verboseSpan } : {},
|
|
149
|
+
currentContext: rootContext
|
|
150
|
+
};
|
|
151
|
+
unit.compat[OTEL_STATE] = state;
|
|
152
|
+
}
|
|
153
|
+
function setRootSpanRoute(route, options = {}) {
|
|
154
|
+
const state = stateOf(getWorkUnit());
|
|
155
|
+
if (!state)
|
|
156
|
+
return;
|
|
157
|
+
state.route = route;
|
|
158
|
+
const { rootSpan } = state;
|
|
159
|
+
const name = `${state.rsc ? "RSC " : ""}${state.method} ${route}`;
|
|
160
|
+
rootSpan.setAttribute("next.route", route);
|
|
161
|
+
rootSpan.setAttribute("http.route", route);
|
|
162
|
+
rootSpan.setAttribute("next.span_name", name);
|
|
163
|
+
rootSpan.updateName(name);
|
|
164
|
+
if (!options.edge)
|
|
165
|
+
return;
|
|
166
|
+
state.edgeMode = options.kind === "handler" ? "handler" : "page";
|
|
167
|
+
if (state.edgeMode !== "page")
|
|
168
|
+
return;
|
|
169
|
+
const [pathname = "", search = ""] = splitTarget(state.target);
|
|
170
|
+
const query = new URLSearchParams(search);
|
|
171
|
+
for (const [key, value] of Object.entries(options.params ?? {})) {
|
|
172
|
+
if (Array.isArray(value))
|
|
173
|
+
query.set(key, value.join("/"));
|
|
174
|
+
else
|
|
175
|
+
query.set(key, value);
|
|
176
|
+
}
|
|
177
|
+
const queryText = query.toString();
|
|
178
|
+
if (queryText) {
|
|
179
|
+
rootSpan.setAttribute("http.target", `${pathname}?${queryText}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function splitTarget(target) {
|
|
183
|
+
const index = target.indexOf("?");
|
|
184
|
+
return index === -1 ? [target, ""] : [target.slice(0, index), target.slice(index + 1)];
|
|
185
|
+
}
|
|
186
|
+
function endRootSpan(status) {
|
|
187
|
+
const state = stateOf(getWorkUnit());
|
|
188
|
+
if (!state || state.rootEnded)
|
|
189
|
+
return;
|
|
190
|
+
state.rootEnded = true;
|
|
191
|
+
const { api: a, rootSpan } = state;
|
|
192
|
+
rootSpan.setAttribute("http.status_code", status);
|
|
193
|
+
if (status >= 500) {
|
|
194
|
+
rootSpan.setAttribute("error.type", String(status));
|
|
195
|
+
rootSpan.setStatus({ code: a.SpanStatusCode.ERROR });
|
|
196
|
+
} else {
|
|
197
|
+
rootSpan.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
198
|
+
}
|
|
199
|
+
endSpan(rootSpan, state.edgeMode === "page" ? "edge" : "nodejs");
|
|
200
|
+
if (state.verboseSpan) {
|
|
201
|
+
state.verboseSpan.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
202
|
+
endSpan(state.verboseSpan, "nodejs");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function endRootSpanIfUnclosed(fallbackStatus) {
|
|
206
|
+
const state = stateOf(getWorkUnit());
|
|
207
|
+
if (!state || state.rootEnded)
|
|
208
|
+
return;
|
|
209
|
+
endRootSpan(fallbackStatus);
|
|
210
|
+
}
|
|
211
|
+
function rootOtelContext() {
|
|
212
|
+
const state = stateOf(getWorkUnit());
|
|
213
|
+
if (!state)
|
|
214
|
+
return;
|
|
215
|
+
return { api: state.api, context: state.rootContext };
|
|
216
|
+
}
|
|
217
|
+
function activeOtelContext() {
|
|
218
|
+
const state = stateOf(getWorkUnit());
|
|
219
|
+
if (!state)
|
|
220
|
+
return;
|
|
221
|
+
return { api: state.api, context: state.api.context.active() };
|
|
222
|
+
}
|
|
223
|
+
function withChildSpan(name, spanType, attributes, fn, options = {}) {
|
|
224
|
+
const state = stateOf(getWorkUnit());
|
|
225
|
+
if (!state)
|
|
226
|
+
return fn();
|
|
227
|
+
const { api: a } = state;
|
|
228
|
+
const parentContext = state.currentContext;
|
|
229
|
+
const tracer = a.trace.getTracer("next.js", "0.0.1");
|
|
230
|
+
const span = tracer.startSpan(name, {
|
|
231
|
+
kind: options.kind ?? a.SpanKind.INTERNAL,
|
|
232
|
+
attributes: {
|
|
233
|
+
...attributes,
|
|
234
|
+
"next.span_name": name,
|
|
235
|
+
"next.span_type": spanType
|
|
236
|
+
}
|
|
237
|
+
}, parentContext);
|
|
238
|
+
const childContext = a.trace.setSpan(parentContext, span);
|
|
239
|
+
state.currentContext = childContext;
|
|
240
|
+
const settle = (error) => {
|
|
241
|
+
state.currentContext = parentContext;
|
|
242
|
+
if (error !== undefined) {
|
|
243
|
+
if (options.onError)
|
|
244
|
+
options.onError(span, error);
|
|
245
|
+
else {
|
|
246
|
+
span.recordException(error);
|
|
247
|
+
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) });
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
251
|
+
}
|
|
252
|
+
endSpan(span, childRuntime(state, spanType));
|
|
253
|
+
};
|
|
254
|
+
try {
|
|
255
|
+
const result = a.context.with(childContext, fn);
|
|
256
|
+
if (isThenable(result)) {
|
|
257
|
+
return result.then((value) => {
|
|
258
|
+
settle();
|
|
259
|
+
return value;
|
|
260
|
+
}, (error) => {
|
|
261
|
+
settle(error);
|
|
262
|
+
throw error;
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
settle();
|
|
266
|
+
return result;
|
|
267
|
+
} catch (error) {
|
|
268
|
+
settle(error);
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function withRenderBodySpan(name, route, fn, spanType = SPAN_TYPE.getBodyResult) {
|
|
273
|
+
const state = stateOf(getWorkUnit());
|
|
274
|
+
if (!state)
|
|
275
|
+
return fn();
|
|
276
|
+
const { api: a } = state;
|
|
277
|
+
const parentContext = state.currentContext;
|
|
278
|
+
const tracer = a.trace.getTracer("next.js", "0.0.1");
|
|
279
|
+
const span = tracer.startSpan(name, {
|
|
280
|
+
kind: a.SpanKind.INTERNAL,
|
|
281
|
+
attributes: {
|
|
282
|
+
"next.route": route,
|
|
283
|
+
"next.span_name": name,
|
|
284
|
+
"next.span_type": spanType
|
|
285
|
+
}
|
|
286
|
+
}, parentContext);
|
|
287
|
+
const spanContext = a.trace.setSpan(parentContext, span);
|
|
288
|
+
const previousRenderSpan = state.renderSpan;
|
|
289
|
+
state.renderSpan = { span, parentContext, spanContext, ended: false, spanType };
|
|
290
|
+
state.currentContext = spanContext;
|
|
291
|
+
const finish = (error) => {
|
|
292
|
+
const current = state.renderSpan;
|
|
293
|
+
if (current?.span !== span || current.ended)
|
|
294
|
+
return;
|
|
295
|
+
current.ended = true;
|
|
296
|
+
endComponentTreeSpan(state);
|
|
297
|
+
if (current.discarded) {
|
|
298
|
+
state.renderSpan = previousRenderSpan;
|
|
299
|
+
if (state.currentContext === spanContext)
|
|
300
|
+
state.currentContext = parentContext;
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (error !== undefined)
|
|
304
|
+
markSpanError(a, span, error);
|
|
305
|
+
else if (!current.errored && span.isRecording()) {
|
|
306
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
307
|
+
}
|
|
308
|
+
endSpan(span, childRuntime(state, spanType));
|
|
309
|
+
state.renderSpan = previousRenderSpan;
|
|
310
|
+
if (state.currentContext === spanContext)
|
|
311
|
+
state.currentContext = parentContext;
|
|
312
|
+
};
|
|
313
|
+
const queued = queueAfterTask(() => finish());
|
|
314
|
+
try {
|
|
315
|
+
const result = a.context.with(spanContext, fn);
|
|
316
|
+
if (isThenable(result)) {
|
|
317
|
+
return result.then((value) => {
|
|
318
|
+
if (!queued)
|
|
319
|
+
finish();
|
|
320
|
+
return value;
|
|
321
|
+
}, (error) => {
|
|
322
|
+
finish(error);
|
|
323
|
+
throw error;
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
if (!queued)
|
|
327
|
+
finish();
|
|
328
|
+
return result;
|
|
329
|
+
} catch (error) {
|
|
330
|
+
finish(error);
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function markRenderSpanError(error) {
|
|
335
|
+
const state = stateOf(getWorkUnit());
|
|
336
|
+
const render = state?.renderSpan;
|
|
337
|
+
if (!state || !render || render.ended)
|
|
338
|
+
return;
|
|
339
|
+
render.errored = true;
|
|
340
|
+
markSpanError(state.api, render.span, error);
|
|
341
|
+
}
|
|
342
|
+
function withRouteHandlerSpan(route, fn) {
|
|
343
|
+
return runHandlerSpan(`executing api route (app) ${route}`, SPAN_TYPE.runHandler, { "next.route": route }, fn);
|
|
344
|
+
}
|
|
345
|
+
function runHandlerSpan(name, spanType, attributes, fn) {
|
|
346
|
+
const state = stateOf(getWorkUnit());
|
|
347
|
+
if (!state)
|
|
348
|
+
return fn();
|
|
349
|
+
const { api: a } = state;
|
|
350
|
+
const edge = state.edgeMode === "handler";
|
|
351
|
+
const parentContext = edge ? state.incomingContext : state.currentContext;
|
|
352
|
+
const tracer = a.trace.getTracer("next.js", "0.0.1");
|
|
353
|
+
const span = tracer.startSpan(name, {
|
|
354
|
+
kind: a.SpanKind.INTERNAL,
|
|
355
|
+
attributes: {
|
|
356
|
+
...attributes,
|
|
357
|
+
"next.span_name": name,
|
|
358
|
+
"next.span_type": spanType
|
|
359
|
+
}
|
|
360
|
+
}, parentContext);
|
|
361
|
+
const spanContext = a.trace.setSpan(parentContext, span);
|
|
362
|
+
const previousContext = state.currentContext;
|
|
363
|
+
state.currentContext = spanContext;
|
|
364
|
+
const settle = (error) => {
|
|
365
|
+
state.currentContext = previousContext;
|
|
366
|
+
if (error !== undefined) {
|
|
367
|
+
span.recordException(error);
|
|
368
|
+
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) });
|
|
369
|
+
} else {
|
|
370
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
371
|
+
}
|
|
372
|
+
endSpan(span, edge ? "edge" : "nodejs");
|
|
373
|
+
};
|
|
374
|
+
try {
|
|
375
|
+
const result = a.context.with(spanContext, fn);
|
|
376
|
+
if (isThenable(result)) {
|
|
377
|
+
return result.then((value) => {
|
|
378
|
+
settle();
|
|
379
|
+
return value;
|
|
380
|
+
}, (error) => {
|
|
381
|
+
settle(error);
|
|
382
|
+
throw error;
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
settle();
|
|
386
|
+
return result;
|
|
387
|
+
} catch (error) {
|
|
388
|
+
settle(error);
|
|
389
|
+
throw error;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function withPagesApiHandlerSpan(route, fn) {
|
|
393
|
+
const state = stateOf(getWorkUnit());
|
|
394
|
+
if (state)
|
|
395
|
+
state.pagesApi = true;
|
|
396
|
+
const name = `executing api route (pages) ${route}`;
|
|
397
|
+
return runHandlerSpan(name, SPAN_TYPE.nodeRunHandler, {}, fn);
|
|
398
|
+
}
|
|
399
|
+
function withPagesDataSpan(kind, fn) {
|
|
400
|
+
const state = stateOf(getWorkUnit());
|
|
401
|
+
const route = state?.route;
|
|
402
|
+
if (!state || !route)
|
|
403
|
+
return fn();
|
|
404
|
+
const { api: a } = state;
|
|
405
|
+
const spanType = kind === "getServerSideProps" ? SPAN_TYPE.getServerSideProps : SPAN_TYPE.getStaticProps;
|
|
406
|
+
const name = `${kind} ${route}`;
|
|
407
|
+
const span = a.trace.getTracer("next.js", "0.0.1").startSpan(name, {
|
|
408
|
+
kind: a.SpanKind.INTERNAL,
|
|
409
|
+
attributes: {
|
|
410
|
+
"next.route": route,
|
|
411
|
+
"next.span_name": name,
|
|
412
|
+
"next.span_type": spanType
|
|
413
|
+
}
|
|
414
|
+
}, state.rootContext);
|
|
415
|
+
const settle = (error, result) => {
|
|
416
|
+
if (error !== undefined) {
|
|
417
|
+
markSpanError(a, span, error);
|
|
418
|
+
emitPagesErrorFallbackSpans(state, route);
|
|
419
|
+
} else {
|
|
420
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
421
|
+
if (result?.notFound) {
|
|
422
|
+
emitPagesNotFoundFallbackSpans(state, route);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
endSpan(span, childRuntime(state, spanType));
|
|
426
|
+
};
|
|
427
|
+
try {
|
|
428
|
+
const result = fn();
|
|
429
|
+
if (isThenable(result)) {
|
|
430
|
+
return result.then((value) => {
|
|
431
|
+
settle(undefined, value);
|
|
432
|
+
return value;
|
|
433
|
+
}, (error) => {
|
|
434
|
+
settle(error ?? new Error("getServerSideProps error"), undefined);
|
|
435
|
+
throw error;
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
settle(undefined, result);
|
|
439
|
+
return result;
|
|
440
|
+
} catch (error) {
|
|
441
|
+
settle(error ?? new Error("getServerSideProps error"), undefined);
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function emitRootLeafSpan(state, name, spanType, attributes) {
|
|
446
|
+
const { api: a } = state;
|
|
447
|
+
const span = a.trace.getTracer("next.js", "0.0.1").startSpan(name, {
|
|
448
|
+
kind: a.SpanKind.INTERNAL,
|
|
449
|
+
attributes: {
|
|
450
|
+
...attributes,
|
|
451
|
+
"next.span_name": name,
|
|
452
|
+
"next.span_type": spanType
|
|
453
|
+
}
|
|
454
|
+
}, state.rootContext);
|
|
455
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
456
|
+
endSpan(span, "nodejs");
|
|
457
|
+
}
|
|
458
|
+
function discardRenderSpan(state) {
|
|
459
|
+
state.pagesFallback = true;
|
|
460
|
+
if (state.renderSpan && !state.renderSpan.ended)
|
|
461
|
+
state.renderSpan.discarded = true;
|
|
462
|
+
}
|
|
463
|
+
function emitPagesErrorFallbackSpans(state, _route) {
|
|
464
|
+
discardRenderSpan(state);
|
|
465
|
+
emitRootLeafSpan(state, "render route (pages) /_error", SPAN_TYPE.renderDocument, {
|
|
466
|
+
"next.route": "/_error"
|
|
467
|
+
});
|
|
468
|
+
emitRootLeafSpan(state, "resolve page components", SPAN_TYPE.findPageComponents, {
|
|
469
|
+
"next.route": "/_error"
|
|
470
|
+
});
|
|
471
|
+
for (let i = 0;i < 2; i += 1) {
|
|
472
|
+
emitRootLeafSpan(state, "resolve page components", SPAN_TYPE.findPageComponents, {
|
|
473
|
+
"next.route": "/500"
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function emitPagesNotFoundFallbackSpans(state, _route) {
|
|
478
|
+
discardRenderSpan(state);
|
|
479
|
+
emitRootLeafSpan(state, "resolve page components", SPAN_TYPE.findPageComponents, {
|
|
480
|
+
"next.route": "/_not-found"
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
function emitStartResponseSpan() {
|
|
484
|
+
const state = stateOf(getWorkUnit());
|
|
485
|
+
if (state?.pagesFallback || state?.pagesApi)
|
|
486
|
+
return;
|
|
487
|
+
emitNodeLeafSpan("start response", SPAN_TYPE.startResponse, {});
|
|
488
|
+
}
|
|
489
|
+
function emitClientComponentLoadingSpan(count) {
|
|
490
|
+
const state = stateOf(getWorkUnit());
|
|
491
|
+
if (!state?.renderSpan || state.renderSpan.ended)
|
|
492
|
+
return;
|
|
493
|
+
emitNodeLeafSpan(SPAN_TYPE.clientComponentLoading, SPAN_TYPE.clientComponentLoading, {
|
|
494
|
+
"next.clientComponentLoadCount": count
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
function emitNodeLeafSpan(name, spanType, attributes) {
|
|
498
|
+
const state = stateOf(getWorkUnit());
|
|
499
|
+
if (!state)
|
|
500
|
+
return;
|
|
501
|
+
const { api: a } = state;
|
|
502
|
+
const render = state.renderSpan;
|
|
503
|
+
const parentContext = render && !render.ended ? render.spanContext : state.rootContext;
|
|
504
|
+
const span = a.trace.getTracer("next.js", "0.0.1").startSpan(name, {
|
|
505
|
+
kind: a.SpanKind.INTERNAL,
|
|
506
|
+
attributes: {
|
|
507
|
+
...attributes,
|
|
508
|
+
"next.span_name": name,
|
|
509
|
+
"next.span_type": spanType
|
|
510
|
+
}
|
|
511
|
+
}, parentContext);
|
|
512
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
513
|
+
endSpan(span, "nodejs");
|
|
514
|
+
}
|
|
515
|
+
function withMiddlewareSpan(request, fn) {
|
|
516
|
+
const a = api();
|
|
517
|
+
if (!a)
|
|
518
|
+
return fn();
|
|
519
|
+
const method = request.method.toUpperCase();
|
|
520
|
+
let target = "";
|
|
521
|
+
try {
|
|
522
|
+
const url = new URL(request.url);
|
|
523
|
+
target = url.pathname + url.search;
|
|
524
|
+
} catch {
|
|
525
|
+
target = request.url;
|
|
526
|
+
}
|
|
527
|
+
const carrier = {};
|
|
528
|
+
request.headers.forEach((value, key) => {
|
|
529
|
+
carrier[key] = value;
|
|
530
|
+
});
|
|
531
|
+
const parentCtx = a.propagation.extract(a.context.active(), carrier, headerGetter);
|
|
532
|
+
const name = `middleware ${method}`;
|
|
533
|
+
const tracer = a.trace.getTracer("next.js", "0.0.1");
|
|
534
|
+
const span = tracer.startSpan(name, {
|
|
535
|
+
attributes: {
|
|
536
|
+
"http.method": method,
|
|
537
|
+
"http.target": target,
|
|
538
|
+
"next.span_name": name,
|
|
539
|
+
"next.span_type": SPAN_TYPE.middleware
|
|
540
|
+
}
|
|
541
|
+
}, parentCtx);
|
|
542
|
+
const spanCtx = a.trace.setSpan(parentCtx, span);
|
|
543
|
+
const settle = (error) => {
|
|
544
|
+
if (error !== undefined) {
|
|
545
|
+
span.recordException(error);
|
|
546
|
+
span.setStatus({ code: a.SpanStatusCode.ERROR, message: errorMessage(error) });
|
|
547
|
+
} else {
|
|
548
|
+
span.setStatus({ code: a.SpanStatusCode.UNSET });
|
|
549
|
+
}
|
|
550
|
+
endSpan(span, "edge");
|
|
551
|
+
};
|
|
552
|
+
try {
|
|
553
|
+
const result = a.context.with(spanCtx, fn);
|
|
554
|
+
if (isThenable(result)) {
|
|
555
|
+
return result.then((value) => {
|
|
556
|
+
settle();
|
|
557
|
+
return value;
|
|
558
|
+
}, (error) => {
|
|
559
|
+
settle(error);
|
|
560
|
+
throw error;
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
settle();
|
|
564
|
+
return result;
|
|
565
|
+
} catch (error) {
|
|
566
|
+
settle(error);
|
|
567
|
+
throw error;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
function emitLeafSpan(name, spanType, attributes, kind) {
|
|
571
|
+
if (spanType === SPAN_TYPE.getLayoutOrPageModule) {
|
|
572
|
+
emitSegmentSpan(name, spanType, attributes, kind);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
withChildSpan(name, spanType, attributes, () => {
|
|
576
|
+
return;
|
|
577
|
+
}, kind !== undefined ? { kind } : {});
|
|
578
|
+
}
|
|
579
|
+
function emitSegmentSpan(name, spanType, attributes, kind) {
|
|
580
|
+
const state = stateOf(getWorkUnit());
|
|
581
|
+
if (state?.pagesFallback)
|
|
582
|
+
return;
|
|
583
|
+
if (!state?.renderSpan || state.renderSpan.ended) {
|
|
584
|
+
withChildSpan(name, spanType, attributes, () => {
|
|
585
|
+
return;
|
|
586
|
+
}, kind !== undefined ? { kind } : {});
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
const tree = ensureComponentTreeSpan(state);
|
|
590
|
+
const previous = state.currentContext;
|
|
591
|
+
state.currentContext = tree.spanContext;
|
|
592
|
+
try {
|
|
593
|
+
withChildSpan(name, spanType, attributes, () => {
|
|
594
|
+
return;
|
|
595
|
+
}, kind !== undefined ? { kind } : {});
|
|
596
|
+
} finally {
|
|
597
|
+
state.currentContext = previous;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
function ensureComponentTreeSpan(state) {
|
|
601
|
+
const current = state.componentTreeSpan;
|
|
602
|
+
if (current && !current.ended)
|
|
603
|
+
return current;
|
|
604
|
+
const { api: a } = state;
|
|
605
|
+
const parentContext = state.renderSpan?.spanContext ?? state.currentContext;
|
|
606
|
+
const name = "build component tree";
|
|
607
|
+
const span = a.trace.getTracer("next.js", "0.0.1").startSpan(name, {
|
|
608
|
+
kind: a.SpanKind.INTERNAL,
|
|
609
|
+
attributes: {
|
|
610
|
+
"next.span_name": name,
|
|
611
|
+
"next.span_type": SPAN_TYPE.createComponentTree
|
|
612
|
+
}
|
|
613
|
+
}, parentContext);
|
|
614
|
+
const spanContext = a.trace.setSpan(parentContext, span);
|
|
615
|
+
const next = { span, parentContext, spanContext, ended: false };
|
|
616
|
+
state.componentTreeSpan = next;
|
|
617
|
+
return next;
|
|
618
|
+
}
|
|
619
|
+
function endComponentTreeSpan(state) {
|
|
620
|
+
const tree = state.componentTreeSpan;
|
|
621
|
+
if (!tree || tree.ended)
|
|
622
|
+
return;
|
|
623
|
+
tree.ended = true;
|
|
624
|
+
tree.span.setStatus({ code: state.api.SpanStatusCode.UNSET });
|
|
625
|
+
endSpan(tree.span, childRuntime(state, SPAN_TYPE.createComponentTree));
|
|
626
|
+
if (state.currentContext === tree.spanContext)
|
|
627
|
+
state.currentContext = tree.parentContext;
|
|
628
|
+
}
|
|
629
|
+
var headerGetter = {
|
|
630
|
+
keys(carrier) {
|
|
631
|
+
return Object.keys(carrier);
|
|
632
|
+
},
|
|
633
|
+
get(carrier, key) {
|
|
634
|
+
return carrier[key.toLowerCase()] ?? carrier[key];
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
var carrierSetter = {
|
|
638
|
+
set(carrier, key, value) {
|
|
639
|
+
carrier[key] = value;
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
function errorMessage(error) {
|
|
643
|
+
if (error instanceof Error)
|
|
644
|
+
return error.message;
|
|
645
|
+
return String(error);
|
|
646
|
+
}
|
|
647
|
+
function markSpanError(api2, span, error) {
|
|
648
|
+
span.setAttribute("error.type", error instanceof Error ? error.name : typeof error);
|
|
649
|
+
span.recordException(error);
|
|
650
|
+
span.setStatus({ code: api2.SpanStatusCode.ERROR, message: errorMessage(error) });
|
|
651
|
+
}
|
|
652
|
+
function otelExportInProgress() {
|
|
653
|
+
return spanEndDepth > 0;
|
|
654
|
+
}
|
|
655
|
+
function endSpan(span, runtime) {
|
|
656
|
+
spanEndDepth++;
|
|
657
|
+
const previousRuntime = process.env.NEXT_RUNTIME;
|
|
658
|
+
if (runtime)
|
|
659
|
+
process.env.NEXT_RUNTIME = runtime;
|
|
660
|
+
try {
|
|
661
|
+
span.end();
|
|
662
|
+
} finally {
|
|
663
|
+
if (runtime) {
|
|
664
|
+
if (previousRuntime === undefined)
|
|
665
|
+
delete process.env.NEXT_RUNTIME;
|
|
666
|
+
else
|
|
667
|
+
process.env.NEXT_RUNTIME = previousRuntime;
|
|
668
|
+
}
|
|
669
|
+
spanEndDepth--;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
function isThenable(value) {
|
|
673
|
+
return typeof value?.then === "function";
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/compat/metadata.ts
|
|
677
|
+
async function readNextModuleMetadata(module, props, parent, modulePath) {
|
|
678
|
+
if (typeof module.generateMetadata === "function") {
|
|
679
|
+
const generate = module.generateMetadata;
|
|
680
|
+
const headProps = headVaryTrackedProps(props);
|
|
681
|
+
const run = () => generate({ params: headProps.params, searchParams: headProps.searchParams }, Promise.resolve(resolvedParentMetadata(parent)));
|
|
682
|
+
const name = metadataSpanName(modulePath);
|
|
683
|
+
return await (name ? withChildSpan(name, SPAN_TYPE.generateMetadata, { "next.page": name.slice("generateMetadata ".length) }, run) : run());
|
|
684
|
+
}
|
|
685
|
+
return module.metadata;
|
|
686
|
+
}
|
|
687
|
+
function metadataSpanName(modulePath) {
|
|
688
|
+
if (!modulePath)
|
|
689
|
+
return;
|
|
690
|
+
const normalized = modulePath.replace(/\\/g, "/").replace(/\.[cm]?[jt]sx?$/, "");
|
|
691
|
+
const idx = normalized.lastIndexOf("/app/");
|
|
692
|
+
const rel = idx >= 0 ? normalized.slice(idx) : `/${normalized.replace(/^\/+/, "")}`;
|
|
693
|
+
return `generateMetadata ${rel}`;
|
|
694
|
+
}
|
|
695
|
+
async function readNextModuleViewport(module, props) {
|
|
696
|
+
if (typeof module.generateViewport === "function") {
|
|
697
|
+
const headProps = headVaryTrackedProps(props);
|
|
698
|
+
return module.generateViewport({
|
|
699
|
+
params: headProps.params,
|
|
700
|
+
searchParams: headProps.searchParams
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
return module.viewport;
|
|
704
|
+
}
|
|
705
|
+
function headVaryTrackedProps(props) {
|
|
706
|
+
const head = getMetadataVaryParamsAccumulator();
|
|
707
|
+
if (!head)
|
|
708
|
+
return { params: props.params, searchParams: props.searchParams };
|
|
709
|
+
return {
|
|
710
|
+
params: retrackSettled(props.params, (raw, info) => createVaryingParams(head, raw, info.optionalCatchAllParam)),
|
|
711
|
+
searchParams: retrackSettled(props.searchParams, (raw) => createVaryingSearchParams(head, raw))
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function retrackSettled(promise, wrap) {
|
|
715
|
+
const settled = promise;
|
|
716
|
+
if (settled.status !== "fulfilled" || settled.value === undefined)
|
|
717
|
+
return promise;
|
|
718
|
+
const info = varyTrackingInfo(settled.value);
|
|
719
|
+
if (!info)
|
|
720
|
+
return promise;
|
|
721
|
+
return settledPromise(wrap(info.raw, info));
|
|
722
|
+
}
|
|
723
|
+
function hasRuntimeMetadata(module) {
|
|
724
|
+
return typeof module.generateMetadata === "function";
|
|
725
|
+
}
|
|
726
|
+
function shouldRenderMetadataInBody({
|
|
727
|
+
config,
|
|
728
|
+
request
|
|
729
|
+
}) {
|
|
730
|
+
const userAgent = request?.headers.get("user-agent") ?? "";
|
|
731
|
+
const limitedBot = config.htmlLimitedBots ?? /Twitterbot|Slackbot|Bingbot|Discordbot|LinkedInBot|Google-PageRenderer|Chrome-Lighthouse|Lighthouse/i;
|
|
732
|
+
return !limitedBot.test(userAgent);
|
|
733
|
+
}
|
|
734
|
+
function resolvedParentMetadata(parent) {
|
|
735
|
+
return {
|
|
736
|
+
...parent,
|
|
737
|
+
metadataBase: parent.metadataBase === undefined ? undefined : coerceString(parent.metadataBase),
|
|
738
|
+
keywords: normalizeKeywordList(parent.keywords),
|
|
739
|
+
openGraph: resolvedParentOpenGraph(parent.openGraph),
|
|
740
|
+
twitter: parent.twitter ?? {},
|
|
741
|
+
robots: parent.robots ?? {},
|
|
742
|
+
alternates: parent.alternates ?? {},
|
|
743
|
+
icons: parent.icons ?? {}
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function resolvedParentOpenGraph(openGraph) {
|
|
747
|
+
if (!openGraph)
|
|
748
|
+
return {};
|
|
749
|
+
return {
|
|
750
|
+
...openGraph,
|
|
751
|
+
title: openGraph.title === undefined || typeof openGraph.title === "object" && openGraph.title !== null ? openGraph.title : { absolute: coerceString(openGraph.title) },
|
|
752
|
+
images: openGraph.images === undefined ? [] : Array.isArray(openGraph.images) ? openGraph.images : [openGraph.images]
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
function normalizeKeywordList(value) {
|
|
756
|
+
if (value === undefined || value === null)
|
|
757
|
+
return;
|
|
758
|
+
return Array.isArray(value) ? value : [value];
|
|
759
|
+
}
|
|
760
|
+
async function warnNextMetadataBuildIssues(appPath, routes, staticMetadataFiles) {
|
|
761
|
+
const warned = new Set;
|
|
762
|
+
const facts = new Map;
|
|
763
|
+
const factsFor = async (file) => {
|
|
764
|
+
let cached = facts.get(file);
|
|
765
|
+
if (!cached) {
|
|
766
|
+
cached = metadataSourceFacts(await readSourceTextOrEmpty(file));
|
|
767
|
+
facts.set(file, cached);
|
|
768
|
+
}
|
|
769
|
+
return cached;
|
|
770
|
+
};
|
|
771
|
+
for (const route of routes) {
|
|
772
|
+
if (route.kind !== "page")
|
|
773
|
+
continue;
|
|
774
|
+
const routeFacts = await Promise.all(routeSourceFiles(appPath, route).map(factsFor));
|
|
775
|
+
const some = (pick) => routeFacts.some(pick);
|
|
776
|
+
if (!legacyRequestAPIs() && some((fact) => fact.themeColor)) {
|
|
777
|
+
warnOnce(warned, `themeColor:${route.route}`, `Unsupported metadata themeColor is configured in metadata export in ${route.route || "/"}. Please move it to viewport
|
|
778
|
+
Read more: https://nextjs.org/docs/app/api-reference/functions/generate-viewport`);
|
|
779
|
+
}
|
|
780
|
+
if (some((fact) => fact.appleTouchFullscreen)) {
|
|
781
|
+
warnOnce(warned, "apple-touch-fullscreen", "Unsupported metadata other.apple-touch-fullscreen is configured in metadata export. Use appleWebApp instead.");
|
|
782
|
+
}
|
|
783
|
+
if (some((fact) => fact.appleTouchIconPrecomposed)) {
|
|
784
|
+
warnOnce(warned, "apple-touch-icon-precomposed", "Unsupported metadata other.apple-touch-icon-precomposed is configured in metadata export. Use icons.apple instead.");
|
|
785
|
+
}
|
|
786
|
+
if (!some((fact) => fact.metadataBase) && routeUsesRelativeSocialImage(route, routeFacts, staticMetadataFiles)) {
|
|
787
|
+
warnOnce(warned, "metadataBase", 'metadataBase property in metadata export is not set for resolving social open graph or twitter images, using "http://localhost:3000". See https://nextjs.org/docs/app/api-reference/functions/generate-metadata#metadatabase');
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
function routeSourceFiles(appPath, route) {
|
|
792
|
+
const root = `${appPath}/`;
|
|
793
|
+
return route.sourceFiles.filter((file) => file === appPath || file.startsWith(root));
|
|
794
|
+
}
|
|
795
|
+
async function readSourceTextOrEmpty(file) {
|
|
796
|
+
try {
|
|
797
|
+
return await readSourceText(file);
|
|
798
|
+
} catch {
|
|
799
|
+
return "";
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
function metadataSourceFacts(source) {
|
|
803
|
+
return {
|
|
804
|
+
themeColor: themeColorInMetadataExport(source),
|
|
805
|
+
appleTouchFullscreen: source.includes("apple-touch-fullscreen") && /['"]apple-touch-fullscreen['"]/.test(source),
|
|
806
|
+
appleTouchIconPrecomposed: source.includes("apple-touch-icon-precomposed") && /['"]apple-touch-icon-precomposed['"]/.test(source),
|
|
807
|
+
metadataBase: source.includes("metadataBase") && /\bmetadataBase\s*:/.test(source),
|
|
808
|
+
relativeSocialImage: hasRelativeSocialImage(source)
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
function themeColorInMetadataExport(source) {
|
|
812
|
+
if (!source.includes("themeColor") || !/\bthemeColor\s*:/.test(source))
|
|
813
|
+
return false;
|
|
814
|
+
return /\bthemeColor\s*:/.test(stripViewportExports(source));
|
|
815
|
+
}
|
|
816
|
+
function stripViewportExports(source) {
|
|
817
|
+
const starts = /export\s+(?:const|let|var)\s+viewport\b|export\s+(?:async\s+)?function\s+generateViewport\b/g;
|
|
818
|
+
let out = "";
|
|
819
|
+
let last = 0;
|
|
820
|
+
for (let match = starts.exec(source);match; match = starts.exec(source)) {
|
|
821
|
+
const open = source.indexOf("{", match.index);
|
|
822
|
+
if (open === -1)
|
|
823
|
+
break;
|
|
824
|
+
let depth = 0;
|
|
825
|
+
let end = open;
|
|
826
|
+
for (;end < source.length; end++) {
|
|
827
|
+
const char = source[end];
|
|
828
|
+
if (char === "{")
|
|
829
|
+
depth++;
|
|
830
|
+
else if (char === "}" && --depth === 0)
|
|
831
|
+
break;
|
|
832
|
+
}
|
|
833
|
+
out += source.slice(last, match.index);
|
|
834
|
+
last = end + 1;
|
|
835
|
+
starts.lastIndex = last;
|
|
836
|
+
}
|
|
837
|
+
return out + source.slice(last);
|
|
838
|
+
}
|
|
839
|
+
function routeUsesRelativeSocialImage(route, facts, staticMetadataFiles) {
|
|
840
|
+
if (facts.some((fact) => fact.relativeSocialImage))
|
|
841
|
+
return true;
|
|
842
|
+
if (route.params.length > 0)
|
|
843
|
+
return false;
|
|
844
|
+
const staticMetadata = staticMetadataForPathFromFiles(staticMetadataFiles, route.route);
|
|
845
|
+
return Boolean(staticMetadata.openGraphImage || staticMetadata.twitterImage);
|
|
846
|
+
}
|
|
847
|
+
function hasRelativeSocialImage(source) {
|
|
848
|
+
if (!source.includes("images"))
|
|
849
|
+
return false;
|
|
850
|
+
return /(?:openGraph|twitter)\s*:\s*\{[\s\S]*?\bimages\s*:\s*['"`](?:\/|\.\.?\/)/m.test(source);
|
|
851
|
+
}
|
|
852
|
+
function warnOnce(warned, key, message) {
|
|
853
|
+
if (warned.has(key))
|
|
854
|
+
return;
|
|
855
|
+
warned.add(key);
|
|
856
|
+
console.warn(message);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// src/compat/validation/validate.ts
|
|
860
|
+
import { existsSync, readdirSync } from "fs";
|
|
861
|
+
import path2 from "path";
|
|
862
|
+
|
|
863
|
+
// src/compat/validation/errors.ts
|
|
864
|
+
function missingRootLayoutMessage(pageFile) {
|
|
865
|
+
return `${pageFile} doesn't have a root layout. To fix this error, make sure every page has a root layout.`;
|
|
866
|
+
}
|
|
867
|
+
function conflictingAppAndPageMessage(conflicts) {
|
|
868
|
+
const numConflicting = conflicts.length;
|
|
869
|
+
const list = conflicts.map((item) => ` "${item.page}" - "${item.app}"`).join(`
|
|
870
|
+
`);
|
|
871
|
+
return `Conflicting app and page file${numConflicting === 1 ? " was" : "s were"} found, ` + `please remove the conflicting files to continue:
|
|
872
|
+
${list}
|
|
873
|
+
`;
|
|
874
|
+
}
|
|
875
|
+
function conflictingParallelPagesMessage(existingPath, appPath) {
|
|
876
|
+
return `You cannot have two parallel pages that resolve to the same path. ` + `Please check ${existingPath} and ${appPath}. ` + `Refer to the route group docs for more information: ` + `https://nextjs.org/docs/app/building-your-application/routing/route-groups`;
|
|
877
|
+
}
|
|
878
|
+
function missingDefaultParallelRouteMessage(segmentPath, slotName) {
|
|
879
|
+
return `Missing required default.js file for parallel route at ${segmentPath}
|
|
880
|
+
` + `The parallel route slot "${slotName}" is missing a default.js file. ` + `When using parallel routes, each slot must have a default.js file to serve as a fallback.
|
|
881
|
+
|
|
882
|
+
` + `Create a default.js file at: ${segmentPath}/default.js`;
|
|
883
|
+
}
|
|
884
|
+
function missingSuspenseWithCsrBailoutMessage(page) {
|
|
885
|
+
return `useSearchParams() should be wrapped in a suspense boundary at page "${page}". ` + `Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
|
|
886
|
+
` + ` at Page (.next/server/app${page === "/" ? "" : page}/page.js)`;
|
|
887
|
+
}
|
|
888
|
+
function incompatibleCacheComponentsSegmentConfigMessage(key) {
|
|
889
|
+
return `Route segment config "${key}" is not compatible with \`nextConfig.cacheComponents\`. Please remove it.`;
|
|
890
|
+
}
|
|
891
|
+
function undefinedDefaultExportMessage(componentPath) {
|
|
892
|
+
return `Error occurred prerendering page "${componentPath.replace(/\/(?:page|layout|not-found)$/, "") || "/"}". Read more: https://nextjs.org/docs/messages/prerender-error
|
|
893
|
+
Error: The default export is not a React Component in "${componentPath}"`;
|
|
894
|
+
}
|
|
895
|
+
function missingGenerateStaticParamsForExportMessage(page) {
|
|
896
|
+
return `Page "${page}" is missing "generateStaticParams()" so it cannot be used with "output: export" config.`;
|
|
897
|
+
}
|
|
898
|
+
function dynamicForceDynamicWithExportMessage(page) {
|
|
899
|
+
return `export const dynamic = "force-dynamic" on page "${page}" cannot be used with "output: export". ` + `See more info here: https://nextjs.org/docs/advanced-features/static-html-export`;
|
|
900
|
+
}
|
|
901
|
+
function forceDynamicPageWithExportMessage() {
|
|
902
|
+
return `Page with \`dynamic = "force-dynamic"\` couldn't be exported. ` + `\`output: "export"\` requires all pages be renderable statically ` + `because there is no runtime server to dynamically render routes in this output format. ` + `Learn more: https://nextjs.org/docs/app/building-your-application/deploying/static-exports`;
|
|
903
|
+
}
|
|
904
|
+
function routeHandlerNotStaticWithExportMessage(route) {
|
|
905
|
+
return `export const dynamic = "force-static"/export const revalidate not configured on route "${route}" ` + `with "output: export".`;
|
|
906
|
+
}
|
|
907
|
+
function exportPathMapWithAppDirMessage() {
|
|
908
|
+
return `The "exportPathMap" configuration cannot be used with the "app" directory. ` + `Please use generateStaticParams() instead. ` + `See more info here: https://nextjs.org/docs/app/building-your-application/deploying/static-exports`;
|
|
909
|
+
}
|
|
910
|
+
function unresolvedCodemodCommentMessage(note) {
|
|
911
|
+
return `You have an unresolved @next/codemod comment "${note}" that needs review.
|
|
912
|
+
` + `After review, either remove the comment if you made the necessary changes or replace ` + `"@next-codemod-error" with "@next-codemod-ignore" to bypass the build error if no action at this line can be taken.`;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/compat/validation/validate.ts
|
|
916
|
+
var BASE_PAGE_EXTENSIONS = ["tsx", "ts", "jsx", "js", "mjs"];
|
|
917
|
+
|
|
918
|
+
class PnextBuildValidationError extends Error {
|
|
919
|
+
constructor(message) {
|
|
920
|
+
super(message);
|
|
921
|
+
this.name = "PnextBuildValidationError";
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
function validateBuild(config, routes) {
|
|
925
|
+
sourceCache.clear();
|
|
926
|
+
const pageRoutes = routes.filter((route) => route.kind === "page" && !route.interception);
|
|
927
|
+
warnBuildDiagnostics(config, routes);
|
|
928
|
+
validateRootLayout(config, pageRoutes);
|
|
929
|
+
validateAppPagesConflict(config);
|
|
930
|
+
validateParallelPageConflicts(config, pageRoutes);
|
|
931
|
+
validateMissingSlotDefaults(config, routes);
|
|
932
|
+
validateCodemodComments(routes);
|
|
933
|
+
validateDefaultExports(config, routes);
|
|
934
|
+
validateSearchParamsSuspense(config, pageRoutes);
|
|
935
|
+
validateUseCacheDirectives(config, routes);
|
|
936
|
+
validateUseCacheSearchParams(routes);
|
|
937
|
+
validateUseCacheHangingInputs(routes);
|
|
938
|
+
validateCacheComponentsSegmentConfigs(config, routes);
|
|
939
|
+
validateInstantStaticShells(config, routes);
|
|
940
|
+
validateClientSegmentConfigs(config, routes);
|
|
941
|
+
validateImageLoaderFile(config);
|
|
942
|
+
validateStaticImageImports(config, routes);
|
|
943
|
+
validateExportMode(config, routes);
|
|
944
|
+
}
|
|
945
|
+
function validateInstantStaticShells(config, routes) {
|
|
946
|
+
if (!cacheComponentsIsEnabled())
|
|
947
|
+
return;
|
|
948
|
+
for (const route of routes) {
|
|
949
|
+
if (route.kind !== "page")
|
|
950
|
+
continue;
|
|
951
|
+
const pageSource = readSource(route.file);
|
|
952
|
+
if (!pageSource || !/\bexport\s+const\s+unstable_instant\s*=\s*false\b/.test(pageSource))
|
|
953
|
+
continue;
|
|
954
|
+
if (!/\bconnection\s*\(/.test(pageSource))
|
|
955
|
+
continue;
|
|
956
|
+
const staticParent = layoutChain(config.appPath, route.file).some((file) => {
|
|
957
|
+
const source = readSource(file);
|
|
958
|
+
return Boolean(source && /\bexport\s+const\s+unstable_instant\s*=\s*true\b/.test(source));
|
|
959
|
+
});
|
|
960
|
+
if (!staticParent)
|
|
961
|
+
continue;
|
|
962
|
+
throw new PnextBuildValidationError(`Error occurred during prerendering page "${route.route || "/"}": Next.js encountered uncached data during prerendering.`);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
function validateUseCacheHangingInputs(routes) {
|
|
966
|
+
if (!cacheComponentsIsEnabled())
|
|
967
|
+
return;
|
|
968
|
+
const failures = [];
|
|
969
|
+
const timeout = 'Filling a cache during prerender timed out, likely because request-specific arguments such as params, searchParams, cookies() or dynamic data were used inside "use cache".';
|
|
970
|
+
for (const route of routes) {
|
|
971
|
+
if (route.kind !== "page")
|
|
972
|
+
continue;
|
|
973
|
+
const source = readSource(route.file);
|
|
974
|
+
if (!source || useCacheDirectives(source).length === 0)
|
|
975
|
+
continue;
|
|
976
|
+
const routePath = nextPagePath(route);
|
|
977
|
+
const thrown = /\bthrow\s+new\s+Error\(\s*['"]([^'"]+)['"]\s*\)/.exec(source);
|
|
978
|
+
if (thrown?.[1] && !readsRequestDataOutsideCache(source)) {
|
|
979
|
+
failures.push(`Error occurred prerendering page "${routePath}". Read more: https://nextjs.org/docs/messages/prerender-error
|
|
980
|
+
Error: ${thrown[1]}`);
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
const scoped = useCacheScopedSource(source).filter((scope) => scope.kind !== "private");
|
|
984
|
+
const isHangingInput = (ident) => ident === "promise" || /^[A-Za-z_$][\w$]*Promise$/.test(ident) || !route.hasStaticParams && ident === "params";
|
|
985
|
+
const hangs = scoped.some((scope) => {
|
|
986
|
+
const params = new Set(scope.params);
|
|
987
|
+
return awaitedIdentifiers(scope.body).some((ident) => isHangingInput(ident) && !params.has(ident));
|
|
988
|
+
});
|
|
989
|
+
const cachedNames = new Set(scoped.map((scope) => scope.name).filter((name) => name !== ""));
|
|
990
|
+
const exemptNames = new Set([...cachedNames, ...requestApiNames(source)]);
|
|
991
|
+
const receivesUncachedPromise = scoped.some((scope) => scope.name !== "" && scope.params.length > 0 && passesUncachedPromiseInto(source, scope.name, exemptNames));
|
|
992
|
+
if (!hangs && !receivesUncachedPromise)
|
|
993
|
+
continue;
|
|
994
|
+
failures.push(`${timeout}
|
|
995
|
+
Error occurred prerendering page "${routePath}". Read more: https://nextjs.org/docs/messages/prerender-error`);
|
|
996
|
+
}
|
|
997
|
+
if (failures.length > 0)
|
|
998
|
+
throw new PnextBuildValidationError(failures.join(`
|
|
999
|
+
|
|
1000
|
+
`));
|
|
1001
|
+
}
|
|
1002
|
+
function validateUseCacheSearchParams(routes) {
|
|
1003
|
+
if (!cacheComponentsIsEnabled())
|
|
1004
|
+
return;
|
|
1005
|
+
const failures = [];
|
|
1006
|
+
for (const route of routes) {
|
|
1007
|
+
if (route.kind !== "page")
|
|
1008
|
+
continue;
|
|
1009
|
+
const source = readSource(route.file);
|
|
1010
|
+
if (!source || useCacheDirectives(source).length === 0)
|
|
1011
|
+
continue;
|
|
1012
|
+
const scoped = useCacheScopedSource(source).filter((scope) => scope.kind !== "private");
|
|
1013
|
+
const violates = scoped.some((scope) => {
|
|
1014
|
+
const params = new Set(scope.params);
|
|
1015
|
+
return awaitedIdentifiers(scope.body).some((ident) => ident === "searchParams" && !params.has(ident));
|
|
1016
|
+
});
|
|
1017
|
+
if (!violates)
|
|
1018
|
+
continue;
|
|
1019
|
+
const routePath = route.route || "/";
|
|
1020
|
+
failures.push(`Route ${routePath} used \`searchParams\` inside "use cache". Accessing dynamic request data inside a cache scope is not supported. ` + "If you need some search params inside a cached function await `searchParams` outside of the cached function and pass only the required search params as arguments to the cached function. " + `See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache
|
|
1021
|
+
` + `Error occurred prerendering page "${routePath}"`);
|
|
1022
|
+
}
|
|
1023
|
+
if (failures.length > 0)
|
|
1024
|
+
throw new PnextBuildValidationError(failures.join(`
|
|
1025
|
+
|
|
1026
|
+
`));
|
|
1027
|
+
}
|
|
1028
|
+
function validateClientSegmentConfigs(config, routes) {
|
|
1029
|
+
for (const route of routes) {
|
|
1030
|
+
if (route.kind !== "page")
|
|
1031
|
+
continue;
|
|
1032
|
+
const source = readSource(route.file);
|
|
1033
|
+
if (!source || !hasDirective(source, "use client"))
|
|
1034
|
+
continue;
|
|
1035
|
+
if (/\bexport\s+const\s+unstable_instant\b/.test(source)) {
|
|
1036
|
+
throw new PnextBuildValidationError(`"unstable_instant" is a route segment config and can only be used when the segment is a Server Component module. Remove the "use client" directive`);
|
|
1037
|
+
}
|
|
1038
|
+
if (getNextConfig().output === "export" && /\bexport\s+(?:async\s+)?function\s+generateStaticParams\b/.test(source)) {
|
|
1039
|
+
throw new PnextBuildValidationError(`Page "/${appDirRelativeFile(config, route.file).replace(/\.[^.]+$/, "")}" cannot use both "use client" and export function "generateStaticParams()".`);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
function validateImageLoaderFile(config) {
|
|
1044
|
+
const images = getNextConfig().images;
|
|
1045
|
+
if (!images || typeof images !== "object" || Array.isArray(images))
|
|
1046
|
+
return;
|
|
1047
|
+
const loaderFile = images.loaderFile;
|
|
1048
|
+
if (typeof loaderFile !== "string" || loaderFile.length === 0)
|
|
1049
|
+
return;
|
|
1050
|
+
const file = path2.resolve(config.root, loaderFile);
|
|
1051
|
+
const source = readSource(file);
|
|
1052
|
+
if (source && /\bexport\s+default\b|\bmodule\.exports\s*=/.test(source))
|
|
1053
|
+
return;
|
|
1054
|
+
throw new PnextBuildValidationError(`images.loaderFile detected but the file is missing default export.
|
|
1055
|
+
` + "Read more: https://nextjs.org/docs/messages/invalid-images-config");
|
|
1056
|
+
}
|
|
1057
|
+
function validateStaticImageImports(config, routes) {
|
|
1058
|
+
const seen = new Set;
|
|
1059
|
+
for (const route of routes) {
|
|
1060
|
+
for (const file of routeFiles(route)) {
|
|
1061
|
+
if (seen.has(file))
|
|
1062
|
+
continue;
|
|
1063
|
+
seen.add(file);
|
|
1064
|
+
if (!isAppSourceFile(config, file))
|
|
1065
|
+
continue;
|
|
1066
|
+
const source = readSource(file);
|
|
1067
|
+
if (!source)
|
|
1068
|
+
continue;
|
|
1069
|
+
const imports = stripComments(source).matchAll(/\bimport\s+(?:[^'";]+?\s+from\s+)?['"]([^'"]+\.(?:png|jpe?g|gif|webp|avif|ico|bmp|svg))['"]/gi);
|
|
1070
|
+
for (const match of imports) {
|
|
1071
|
+
const specifier = match[1];
|
|
1072
|
+
if (!specifier.startsWith("."))
|
|
1073
|
+
continue;
|
|
1074
|
+
if (existsSync(path2.resolve(path2.dirname(file), specifier)))
|
|
1075
|
+
continue;
|
|
1076
|
+
throw new PnextBuildValidationError(`Module not found: Can't resolve '${specifier}'
|
|
1077
|
+
./app/${appDirRelativeFile(config, file)}`);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
function warnBuildDiagnostics(config, routes) {
|
|
1083
|
+
const nextConfig = getNextConfig();
|
|
1084
|
+
const experimental = nextConfig.experimental;
|
|
1085
|
+
if (hasBabelConfig(config.root) && experimental?.forceSwcTransforms !== true) {
|
|
1086
|
+
console.warn("Disabled SWC as replacement for Babel because of custom Babel configuration");
|
|
1087
|
+
}
|
|
1088
|
+
if (!legacyRequestAPIs() && typeof nextConfig.outputFileTracingRoot !== "string" && !(nextConfig.turbopack && typeof nextConfig.turbopack === "object" && typeof nextConfig.turbopack.root === "string")) {
|
|
1089
|
+
warnMultipleLockfiles(config.root);
|
|
1090
|
+
}
|
|
1091
|
+
let warnedEdgeRuntime = false;
|
|
1092
|
+
for (const file of new Set(routes.flatMap((route) => routeFiles(route)))) {
|
|
1093
|
+
if (!isAppSourceFile(config, file))
|
|
1094
|
+
continue;
|
|
1095
|
+
const source = readSource(file);
|
|
1096
|
+
if (!source)
|
|
1097
|
+
continue;
|
|
1098
|
+
if (!warnedEdgeRuntime && /\bruntime\s*=\s*['"](?:edge|experimental-edge)['"]/.test(source)) {
|
|
1099
|
+
console.warn('The Edge Runtime is deprecated. You can use the "nodejs" runtime instead.');
|
|
1100
|
+
warnedEdgeRuntime = true;
|
|
1101
|
+
}
|
|
1102
|
+
for (const key of ["runtime", "preferredRegion"]) {
|
|
1103
|
+
if (new RegExp(`\\bexport\\s*\\{[^}]*\\b${key}\\b[^}]*\\}\\s*from\\s*['"]`).test(source)) {
|
|
1104
|
+
console.warn(`Next.js can't recognize the exported \`${key}\` field in ${toPosix(path2.relative(config.root, file))}`);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
function hasBabelConfig(root) {
|
|
1110
|
+
return [
|
|
1111
|
+
".babelrc",
|
|
1112
|
+
".babelrc.json",
|
|
1113
|
+
".babelrc.js",
|
|
1114
|
+
".babelrc.cjs",
|
|
1115
|
+
"babel.config.js",
|
|
1116
|
+
"babel.config.cjs"
|
|
1117
|
+
].some((name) => existsSync(path2.join(root, name)));
|
|
1118
|
+
}
|
|
1119
|
+
function warnMultipleLockfiles(root) {
|
|
1120
|
+
if (typeof getNextConfig().outputFileTracingRoot === "string")
|
|
1121
|
+
return;
|
|
1122
|
+
const lockfiles = [];
|
|
1123
|
+
let current = root;
|
|
1124
|
+
while (true) {
|
|
1125
|
+
for (const name of [
|
|
1126
|
+
"package-lock.json",
|
|
1127
|
+
"yarn.lock",
|
|
1128
|
+
"pnpm-lock.yaml",
|
|
1129
|
+
"bun.lock",
|
|
1130
|
+
"bun.lockb"
|
|
1131
|
+
]) {
|
|
1132
|
+
const file = path2.join(current, name);
|
|
1133
|
+
if (existsSync(file))
|
|
1134
|
+
lockfiles.push(file);
|
|
1135
|
+
}
|
|
1136
|
+
if (existsSync(path2.join(current, "pnpm-workspace.yaml")))
|
|
1137
|
+
break;
|
|
1138
|
+
const parent = path2.dirname(current);
|
|
1139
|
+
if (parent === current)
|
|
1140
|
+
break;
|
|
1141
|
+
current = parent;
|
|
1142
|
+
}
|
|
1143
|
+
const dirs = [...new Set(lockfiles.map((file) => path2.dirname(file)))];
|
|
1144
|
+
if (dirs.length < 2)
|
|
1145
|
+
return;
|
|
1146
|
+
const selected = dirs[0];
|
|
1147
|
+
const additional = lockfiles.filter((file) => path2.dirname(file) !== selected);
|
|
1148
|
+
console.warn(`\u26A0 Warning: Next.js inferred your workspace root, but it may not be correct.
|
|
1149
|
+
` + ` We detected multiple lockfiles and selected the directory of ${selected} as the root directory.
|
|
1150
|
+
` + " To silence this warning, set `outputFileTracingRoot` in your Next.js config, or consider removing one of the lockfiles if it's not needed.\n" + ` See https://nextjs.org/docs/app/api-reference/config/next-config-js/output#caveats for more information.
|
|
1151
|
+
` + ` Detected additional lockfiles:
|
|
1152
|
+
` + additional.map((file) => ` * ${file}`).join(`
|
|
1153
|
+
`));
|
|
1154
|
+
}
|
|
1155
|
+
var sourceCache = new Map;
|
|
1156
|
+
function readSource(file) {
|
|
1157
|
+
if (sourceCache.has(file))
|
|
1158
|
+
return sourceCache.get(file);
|
|
1159
|
+
let source;
|
|
1160
|
+
try {
|
|
1161
|
+
source = readSourceSync(file);
|
|
1162
|
+
} catch {
|
|
1163
|
+
source = undefined;
|
|
1164
|
+
}
|
|
1165
|
+
sourceCache.set(file, source);
|
|
1166
|
+
return source;
|
|
1167
|
+
}
|
|
1168
|
+
function routeFiles(route) {
|
|
1169
|
+
return [...new Set([route.file, ...route.sourceFiles])];
|
|
1170
|
+
}
|
|
1171
|
+
function isAppSourceFile(config, file) {
|
|
1172
|
+
const materialized = file.includes(`${path2.sep}source-app${path2.sep}`) || file.includes(`${path2.sep}source-pages${path2.sep}`);
|
|
1173
|
+
if (isInside(config.outPath, file))
|
|
1174
|
+
return materialized && file.includes(`${path2.sep}pnext-pages-compat${path2.sep}`);
|
|
1175
|
+
const relative = path2.relative(config.root, file);
|
|
1176
|
+
if (relative !== "" && !relative.startsWith("..") && !path2.isAbsolute(relative)) {
|
|
1177
|
+
return !relative.split(path2.sep).includes("node_modules");
|
|
1178
|
+
}
|
|
1179
|
+
return materialized;
|
|
1180
|
+
}
|
|
1181
|
+
function isInside(parent, file) {
|
|
1182
|
+
const relative = path2.relative(parent, file);
|
|
1183
|
+
return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
|
|
1184
|
+
}
|
|
1185
|
+
function hasDirective(source, directive) {
|
|
1186
|
+
return directivePrologue(source, 0).includes(directive);
|
|
1187
|
+
}
|
|
1188
|
+
function cacheComponentsIsEnabled() {
|
|
1189
|
+
const nextConfig = getNextConfig();
|
|
1190
|
+
const experimental = nextConfig.experimental;
|
|
1191
|
+
return nextConfig.cacheComponents === true || experimental?.cacheComponents === true || experimental?.useCache === true || experimental?.dynamicIO === true || process.env.__NEXT_CACHE_COMPONENTS === "true";
|
|
1192
|
+
}
|
|
1193
|
+
var CACHE_COMPONENTS_FORBIDDEN_SEGMENT_CONFIGS = [
|
|
1194
|
+
"dynamic",
|
|
1195
|
+
"dynamicParams",
|
|
1196
|
+
"revalidate",
|
|
1197
|
+
"fetchCache"
|
|
1198
|
+
];
|
|
1199
|
+
var SEGMENT_CONFIG_FILE = /(?:^|\/)(?:page|layout|route|default)\.(?:tsx|ts|jsx|js|mjs)$/;
|
|
1200
|
+
function validateCacheComponentsSegmentConfigs(config, routes) {
|
|
1201
|
+
if (!cacheComponentsIsEnabled())
|
|
1202
|
+
return;
|
|
1203
|
+
const projectRoot = path2.resolve(config.appPath, "..");
|
|
1204
|
+
const seen = new Set;
|
|
1205
|
+
const failures = [];
|
|
1206
|
+
for (const route of routes) {
|
|
1207
|
+
for (const file of route.sourceFiles) {
|
|
1208
|
+
if (seen.has(file))
|
|
1209
|
+
continue;
|
|
1210
|
+
if (!SEGMENT_CONFIG_FILE.test(toPosix(file)))
|
|
1211
|
+
continue;
|
|
1212
|
+
seen.add(file);
|
|
1213
|
+
if (!isProjectSourceFile(projectRoot, file))
|
|
1214
|
+
continue;
|
|
1215
|
+
const source = readSource(file);
|
|
1216
|
+
if (source === undefined)
|
|
1217
|
+
continue;
|
|
1218
|
+
if (isMaterializedPagesWrapper(source))
|
|
1219
|
+
continue;
|
|
1220
|
+
let earliest;
|
|
1221
|
+
for (const key of CACHE_COMPONENTS_FORBIDDEN_SEGMENT_CONFIGS) {
|
|
1222
|
+
const match = new RegExp(`(?:^|[;\\n])\\s*export\\s+const\\s+${key}\\b`).exec(source);
|
|
1223
|
+
if (match && (earliest === undefined || match.index < earliest.index)) {
|
|
1224
|
+
earliest = { key, index: match.index };
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
const runtimeMatch = /(?:^|[;\n])\s*export\s+const\s+runtime\s*=\s*['"]([^'"]+)['"]/.exec(source);
|
|
1228
|
+
if (runtimeMatch && (runtimeMatch[1] !== "edge" || useCacheOnlyIsEnabled()) && (earliest === undefined || runtimeMatch.index < earliest.index)) {
|
|
1229
|
+
earliest = { key: "runtime", index: runtimeMatch.index };
|
|
1230
|
+
}
|
|
1231
|
+
if (!earliest)
|
|
1232
|
+
continue;
|
|
1233
|
+
if (useCacheOnlyIsEnabled()) {
|
|
1234
|
+
throw new PnextBuildValidationError(useCacheSegmentConfigBuildError(source, earliest.key));
|
|
1235
|
+
}
|
|
1236
|
+
let trace = "";
|
|
1237
|
+
if (/(?:^|\/)layout\.(?:tsx|ts|jsx|js|mjs)$/.test(toPosix(file))) {
|
|
1238
|
+
const importers = new Set;
|
|
1239
|
+
for (const other of routes) {
|
|
1240
|
+
if (other.kind !== "page")
|
|
1241
|
+
continue;
|
|
1242
|
+
if (!other.sourceFiles.includes(file))
|
|
1243
|
+
continue;
|
|
1244
|
+
importers.add(`./app/${appDirRelativeFile(config, other.file)}`);
|
|
1245
|
+
}
|
|
1246
|
+
const layoutRel = `./app/${appDirRelativeFile(config, file)}`;
|
|
1247
|
+
for (const importer of [...importers].sort()) {
|
|
1248
|
+
trace += `
|
|
1249
|
+
|
|
1250
|
+
Import trace for requested module:
|
|
1251
|
+
${importer}
|
|
1252
|
+
${layoutRel}`;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
failures.push(`./app/${appDirRelativeFile(config, file)}
|
|
1256
|
+
` + incompatibleCacheComponentsSegmentConfigMessage(earliest.key) + trace);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
if (failures.length > 0)
|
|
1260
|
+
throw new PnextBuildValidationError(failures.join(`
|
|
1261
|
+
|
|
1262
|
+
`));
|
|
1263
|
+
}
|
|
1264
|
+
function useCacheOnlyIsEnabled() {
|
|
1265
|
+
const nextConfig = getNextConfig();
|
|
1266
|
+
const experimental = nextConfig.experimental;
|
|
1267
|
+
return experimental?.useCache === true && nextConfig.cacheComponents !== true && experimental?.cacheComponents !== true && experimental?.dynamicIO !== true && process.env.__NEXT_CACHE_COMPONENTS !== "true";
|
|
1268
|
+
}
|
|
1269
|
+
function useCacheSegmentConfigBuildError(source, key) {
|
|
1270
|
+
const lines = source.split(`
|
|
1271
|
+
`);
|
|
1272
|
+
const exportRe = new RegExp(`\\bexport\\s+const\\s+${key}\\b`);
|
|
1273
|
+
let line = 1;
|
|
1274
|
+
let column = 1;
|
|
1275
|
+
for (let i = 0;i < lines.length; i += 1) {
|
|
1276
|
+
const match = new RegExp(`\\b${key}\\b`).exec(lines[i] ?? "");
|
|
1277
|
+
if (exportRe.test(lines[i] ?? "") && match) {
|
|
1278
|
+
line = i + 1;
|
|
1279
|
+
column = match.index + 1;
|
|
1280
|
+
break;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
const last = Math.min(lines.length, line + 3);
|
|
1284
|
+
const width = String(last).length;
|
|
1285
|
+
const gutter = " ".repeat(width + 2);
|
|
1286
|
+
const frame = [`${gutter},-[${line}:1]`];
|
|
1287
|
+
for (let n = line;n <= last; n += 1) {
|
|
1288
|
+
frame.push(` ${String(n).padStart(width)} | ${lines[n - 1] ?? ""}`);
|
|
1289
|
+
if (n === line) {
|
|
1290
|
+
frame.push(`${gutter}: ${" ".repeat(column - 1)}${"^".repeat(key.length)}`);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
frame.push(`${gutter}\`----`);
|
|
1294
|
+
return `Failed to compile.
|
|
1295
|
+
` + `
|
|
1296
|
+
` + `__next_edge_ssr_entry__
|
|
1297
|
+
` + `Error: x Route segment config "${key}" is not compatible with \`nextConfig.experimental.useCache\`. Please remove it.
|
|
1298
|
+
` + `${frame.join(`
|
|
1299
|
+
`)}
|
|
1300
|
+
` + `
|
|
1301
|
+
` + `Import trace for requested module:
|
|
1302
|
+
` + `__next_edge_ssr_entry__
|
|
1303
|
+
` + `
|
|
1304
|
+
` + `
|
|
1305
|
+
` + "> Build failed because of webpack errors";
|
|
1306
|
+
}
|
|
1307
|
+
function isMaterializedPagesWrapper(source) {
|
|
1308
|
+
return /\bfrom\s+['"][^'"]*source-pages[/\\]/.test(source);
|
|
1309
|
+
}
|
|
1310
|
+
function validateUseCacheDirectives(config, routes) {
|
|
1311
|
+
const nextConfig = getNextConfig();
|
|
1312
|
+
const experimental = nextConfig.experimental;
|
|
1313
|
+
const enabled = nextConfig.cacheComponents === true || experimental?.cacheComponents === true || experimental?.useCache === true || experimental?.dynamicIO === true || process.env.__NEXT_CACHE_COMPONENTS === "true";
|
|
1314
|
+
const kinds = new Set(["default", "private", "remote"]);
|
|
1315
|
+
const configured = nextConfig.cacheHandlers;
|
|
1316
|
+
if (configured && typeof configured === "object" && !Array.isArray(configured)) {
|
|
1317
|
+
for (const kind of Object.keys(configured))
|
|
1318
|
+
kinds.add(kind);
|
|
1319
|
+
}
|
|
1320
|
+
const projectRoot = path2.resolve(config.appPath, "..");
|
|
1321
|
+
const seen = new Set;
|
|
1322
|
+
for (const route of routes) {
|
|
1323
|
+
for (const file of route.sourceFiles) {
|
|
1324
|
+
if (seen.has(file))
|
|
1325
|
+
continue;
|
|
1326
|
+
seen.add(file);
|
|
1327
|
+
if (!isProjectSourceFile(projectRoot, file))
|
|
1328
|
+
continue;
|
|
1329
|
+
const source = readSource(file);
|
|
1330
|
+
if (source === undefined)
|
|
1331
|
+
continue;
|
|
1332
|
+
for (const directive of useCacheDirectives(source)) {
|
|
1333
|
+
if (!enabled) {
|
|
1334
|
+
throw new PnextBuildValidationError(useCacheNotEnabledBuildError(`./app/${appDirRelativeFile(config, file)}`, source));
|
|
1335
|
+
}
|
|
1336
|
+
const kind = directive.kind;
|
|
1337
|
+
if (!kinds.has(kind)) {
|
|
1338
|
+
throw new PnextBuildValidationError(unknownCacheKindBuildError(`./app/${appDirRelativeFile(config, file)}`, source, kind));
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function isProjectSourceFile(projectRoot, file) {
|
|
1345
|
+
const relative = path2.relative(projectRoot, file);
|
|
1346
|
+
return relative !== "" && !relative.startsWith("..") && !path2.isAbsolute(relative) && !relative.split(path2.sep).includes("node_modules");
|
|
1347
|
+
}
|
|
1348
|
+
function useCacheDirectives(source) {
|
|
1349
|
+
const directives = [
|
|
1350
|
+
...directivePrologue(source, 0),
|
|
1351
|
+
...functionBodies(source).flatMap((offset) => directivePrologue(source, offset))
|
|
1352
|
+
];
|
|
1353
|
+
return directives.flatMap((value) => {
|
|
1354
|
+
const match = /^use cache(?:\s*:\s*([\w-]+))?$/.exec(value);
|
|
1355
|
+
return match ? [{ kind: match[1] ?? "default" }] : [];
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
function useCacheScopedSource(source) {
|
|
1359
|
+
const kindOf = (value) => /^use cache(?:\s*:\s*([\w-]+))?$/.exec(value);
|
|
1360
|
+
for (const directive of directivePrologue(source, 0)) {
|
|
1361
|
+
const match = kindOf(directive);
|
|
1362
|
+
if (match)
|
|
1363
|
+
return [{ kind: match[1] ?? "default", body: source, params: [], name: "" }];
|
|
1364
|
+
}
|
|
1365
|
+
const scopes = [];
|
|
1366
|
+
for (const scope of functionScopes(source)) {
|
|
1367
|
+
for (const directive of directivePrologue(source, scope.offset)) {
|
|
1368
|
+
const match = kindOf(directive);
|
|
1369
|
+
if (!match)
|
|
1370
|
+
continue;
|
|
1371
|
+
scopes.push({
|
|
1372
|
+
kind: match[1] ?? "default",
|
|
1373
|
+
body: source.slice(scope.offset, functionBodyEnd(source, scope.offset)),
|
|
1374
|
+
params: scope.params,
|
|
1375
|
+
name: scope.name
|
|
1376
|
+
});
|
|
1377
|
+
break;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
return scopes;
|
|
1381
|
+
}
|
|
1382
|
+
function passesUncachedPromiseInto(source, name, resolvableNames) {
|
|
1383
|
+
const isUncached = (expression) => isUncachedPromiseExpression(expression, resolvableNames);
|
|
1384
|
+
const pattern = new RegExp(`(<)?\\b${escapeRegExp(name)}\\b`, "g");
|
|
1385
|
+
for (const match of source.matchAll(pattern)) {
|
|
1386
|
+
const index = match.index;
|
|
1387
|
+
if (index === undefined || !isCodeOffset(source, index))
|
|
1388
|
+
continue;
|
|
1389
|
+
const after = index + match[0].length;
|
|
1390
|
+
if (match[1] === "<") {
|
|
1391
|
+
if (jsxPropsPassUncachedPromise(source, after, isUncached))
|
|
1392
|
+
return true;
|
|
1393
|
+
continue;
|
|
1394
|
+
}
|
|
1395
|
+
const open = source.slice(after).search(/\S/);
|
|
1396
|
+
if (open === -1 || source[after + open] !== "(")
|
|
1397
|
+
continue;
|
|
1398
|
+
const args = balancedFrom(source, after + open, "(", ")");
|
|
1399
|
+
if (args !== undefined && splitTopLevelCommas(args).some(isUncached))
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
function jsxPropsPassUncachedPromise(source, offset, isUncached) {
|
|
1405
|
+
for (let cursor = offset;cursor < source.length; cursor++) {
|
|
1406
|
+
const current = source[cursor];
|
|
1407
|
+
if (current === ">")
|
|
1408
|
+
return false;
|
|
1409
|
+
if (current !== "{")
|
|
1410
|
+
continue;
|
|
1411
|
+
const expression = balancedFrom(source, cursor, "{", "}");
|
|
1412
|
+
if (expression === undefined)
|
|
1413
|
+
return false;
|
|
1414
|
+
if (isUncached(expression))
|
|
1415
|
+
return true;
|
|
1416
|
+
cursor += expression.length + 1;
|
|
1417
|
+
}
|
|
1418
|
+
return false;
|
|
1419
|
+
}
|
|
1420
|
+
function balancedFrom(source, index, open, close) {
|
|
1421
|
+
let depth = 0;
|
|
1422
|
+
let quote;
|
|
1423
|
+
for (let cursor = index;cursor < source.length; cursor++) {
|
|
1424
|
+
const current = source[cursor];
|
|
1425
|
+
if (quote) {
|
|
1426
|
+
if (current === "\\")
|
|
1427
|
+
cursor++;
|
|
1428
|
+
else if (current === quote)
|
|
1429
|
+
quote = undefined;
|
|
1430
|
+
continue;
|
|
1431
|
+
}
|
|
1432
|
+
if (current === '"' || current === "'" || current === "`") {
|
|
1433
|
+
quote = current;
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
if (current === open)
|
|
1437
|
+
depth++;
|
|
1438
|
+
else if (current === close && --depth === 0)
|
|
1439
|
+
return source.slice(index + 1, cursor);
|
|
1440
|
+
}
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
function isUncachedPromiseExpression(expression, resolvableNames) {
|
|
1444
|
+
const trimmed = expression.trim();
|
|
1445
|
+
if (trimmed === "" || /^await\b/.test(trimmed))
|
|
1446
|
+
return false;
|
|
1447
|
+
const call = /^([A-Za-z_$][\w$.]*)\s*\(/.exec(trimmed);
|
|
1448
|
+
return call !== null && !resolvableNames.has(call[1]);
|
|
1449
|
+
}
|
|
1450
|
+
function requestApiNames(source) {
|
|
1451
|
+
const names = new Set;
|
|
1452
|
+
const imports = source.matchAll(/\bimport\s*\{([^}]*)\}\s*from\s*['"]next\/(?:headers|root-params)['"]/g);
|
|
1453
|
+
for (const match of imports) {
|
|
1454
|
+
for (const clause of match[1].split(",")) {
|
|
1455
|
+
const local = /([A-Za-z_$][\w$]*)\s*$/.exec(clause.trim());
|
|
1456
|
+
if (local)
|
|
1457
|
+
names.add(local[1]);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
return names;
|
|
1461
|
+
}
|
|
1462
|
+
function escapeRegExp(value) {
|
|
1463
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1464
|
+
}
|
|
1465
|
+
function readsRequestDataOutsideCache(source) {
|
|
1466
|
+
const outside = useCacheScopedSource(source).reduce((rest, scope) => rest.replace(scope.body, ""), source);
|
|
1467
|
+
return /\b(?:connection|cookies|headers|draftMode)\s*\(\s*\)/.test(outside);
|
|
1468
|
+
}
|
|
1469
|
+
function functionBodyEnd(source, offset) {
|
|
1470
|
+
let depth = 1;
|
|
1471
|
+
let quote;
|
|
1472
|
+
for (let cursor = offset;cursor < source.length; cursor++) {
|
|
1473
|
+
const current = source[cursor];
|
|
1474
|
+
if (quote) {
|
|
1475
|
+
if (current === "\\")
|
|
1476
|
+
cursor++;
|
|
1477
|
+
else if (current === quote)
|
|
1478
|
+
quote = undefined;
|
|
1479
|
+
continue;
|
|
1480
|
+
}
|
|
1481
|
+
if (current === "/" && source[cursor + 1] === "/") {
|
|
1482
|
+
const newline = source.indexOf(`
|
|
1483
|
+
`, cursor + 2);
|
|
1484
|
+
if (newline === -1)
|
|
1485
|
+
return source.length;
|
|
1486
|
+
cursor = newline;
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
if (current === "/" && source[cursor + 1] === "*") {
|
|
1490
|
+
const end = source.indexOf("*/", cursor + 2);
|
|
1491
|
+
if (end === -1)
|
|
1492
|
+
return source.length;
|
|
1493
|
+
cursor = end + 1;
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
if (current === '"' || current === "'" || current === "`") {
|
|
1497
|
+
quote = current;
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
if (current === "{")
|
|
1501
|
+
depth++;
|
|
1502
|
+
else if (current === "}" && --depth === 0)
|
|
1503
|
+
return cursor;
|
|
1504
|
+
}
|
|
1505
|
+
return source.length;
|
|
1506
|
+
}
|
|
1507
|
+
function useCacheNotEnabledBuildError(displayPath, source) {
|
|
1508
|
+
return useCacheDirectiveBuildError(displayPath, source, 'To use "use cache", please enable the feature flag `cacheComponents` in your Next.js config.\n' + ` |
|
|
1509
|
+
` + " | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage");
|
|
1510
|
+
}
|
|
1511
|
+
function unknownCacheKindBuildError(displayPath, source, kind) {
|
|
1512
|
+
return useCacheDirectiveBuildError(displayPath, source, `Unknown cache kind "${kind}". Please configure a cache handler for this kind in the \`cacheHandlers\` object in your Next.js config.`);
|
|
1513
|
+
}
|
|
1514
|
+
function useCacheDirectiveBuildError(displayPath, source, message) {
|
|
1515
|
+
const match = /(['"])use cache(?:\s*:\s*[\w-]+)?\1/.exec(source);
|
|
1516
|
+
const index = match?.index ?? 0;
|
|
1517
|
+
const span = match?.[0].length ?? 11;
|
|
1518
|
+
const before = source.slice(0, index);
|
|
1519
|
+
const line = before.split(`
|
|
1520
|
+
`).length;
|
|
1521
|
+
const column = index - before.lastIndexOf(`
|
|
1522
|
+
`);
|
|
1523
|
+
const frame = swcCodeFrame(source, line, column, span);
|
|
1524
|
+
return `Failed to compile.
|
|
1525
|
+
` + `
|
|
1526
|
+
` + `${displayPath}
|
|
1527
|
+
` + `Error: x ${message}
|
|
1528
|
+
` + `
|
|
1529
|
+
` + `${frame}
|
|
1530
|
+
` + `
|
|
1531
|
+
` + `Import trace for requested module:
|
|
1532
|
+
` + `${displayPath}
|
|
1533
|
+
` + `
|
|
1534
|
+
` + `
|
|
1535
|
+
` + "> Build failed because of webpack errors";
|
|
1536
|
+
}
|
|
1537
|
+
function swcCodeFrame(source, line, column, span) {
|
|
1538
|
+
const lines = source.split(`
|
|
1539
|
+
`);
|
|
1540
|
+
const last = Math.min(lines.length, line + 3);
|
|
1541
|
+
const width = String(last).length;
|
|
1542
|
+
const gutter = " ".repeat(width + 2);
|
|
1543
|
+
const out = [`${gutter},-[${line}:${column}]`];
|
|
1544
|
+
for (let n = line;n <= last; n += 1) {
|
|
1545
|
+
out.push(` ${String(n).padStart(width)} | ${lines[n - 1] ?? ""}`);
|
|
1546
|
+
if (n === line) {
|
|
1547
|
+
out.push(`${gutter}: ${" ".repeat(column - 1)}${"^".repeat(span)}`);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
out.push(`${gutter}\`----`);
|
|
1551
|
+
return out.join(`
|
|
1552
|
+
`);
|
|
1553
|
+
}
|
|
1554
|
+
function directivePrologue(source, offset) {
|
|
1555
|
+
const directives = [];
|
|
1556
|
+
let cursor = offset;
|
|
1557
|
+
while (true) {
|
|
1558
|
+
cursor = skipTrivia(source, cursor);
|
|
1559
|
+
const quote = source[cursor];
|
|
1560
|
+
if (quote !== '"' && quote !== "'")
|
|
1561
|
+
return directives;
|
|
1562
|
+
const end = stringEnd(source, cursor, quote);
|
|
1563
|
+
if (end === -1)
|
|
1564
|
+
return directives;
|
|
1565
|
+
const value = source.slice(cursor + 1, end);
|
|
1566
|
+
const afterString = end + 1;
|
|
1567
|
+
cursor = skipTrivia(source, afterString);
|
|
1568
|
+
if (source[cursor] === ";")
|
|
1569
|
+
cursor++;
|
|
1570
|
+
else if (cursor < source.length && source[cursor] !== "}" && !/[\r\n]/.test(source.slice(afterString, cursor))) {
|
|
1571
|
+
return directives;
|
|
1572
|
+
}
|
|
1573
|
+
directives.push(value);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
function functionBodies(source) {
|
|
1577
|
+
return functionScopes(source).map((scope) => scope.offset);
|
|
1578
|
+
}
|
|
1579
|
+
function functionScopes(source) {
|
|
1580
|
+
const scopes = [];
|
|
1581
|
+
const pattern = /\b(?:async\s+)?function(?:\s*\*)?(?:\s+[A-Za-z_$][\w$]*)?\s*(?:<[^>{}]*>)?\s*\([^)]*\)\s*(?::\s*[^={]+)?\{|\b(?:async\s+)?(?:[A-Za-z_$][\w$]*|\([^)]*\))\s*=>\s*\{/g;
|
|
1582
|
+
for (const match of source.matchAll(pattern)) {
|
|
1583
|
+
if (match.index !== undefined && isCodeOffset(source, match.index)) {
|
|
1584
|
+
scopes.push({
|
|
1585
|
+
offset: match.index + match[0].length,
|
|
1586
|
+
params: signatureParams(match[0]),
|
|
1587
|
+
name: signatureName(source, match.index, match[0])
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
return scopes;
|
|
1592
|
+
}
|
|
1593
|
+
function signatureName(source, index, signature) {
|
|
1594
|
+
const declared = /\bfunction(?:\s*\*)?\s+([A-Za-z_$][\w$]*)/.exec(signature);
|
|
1595
|
+
if (declared)
|
|
1596
|
+
return declared[1];
|
|
1597
|
+
const before = source.slice(Math.max(0, index - 200), index);
|
|
1598
|
+
const assigned = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=;]*)?=\s*$/.exec(before);
|
|
1599
|
+
return assigned?.[1] ?? "";
|
|
1600
|
+
}
|
|
1601
|
+
function signatureParams(signature) {
|
|
1602
|
+
const bareArrow = /(?:^|[^\w$.])([A-Za-z_$][\w$]*)\s*=>\s*\{\s*$/.exec(signature);
|
|
1603
|
+
if (bareArrow && !signature.includes("("))
|
|
1604
|
+
return [bareArrow[1]];
|
|
1605
|
+
const open = signature.indexOf("(");
|
|
1606
|
+
if (open === -1)
|
|
1607
|
+
return [];
|
|
1608
|
+
const close = signature.indexOf(")", open);
|
|
1609
|
+
if (close === -1)
|
|
1610
|
+
return [];
|
|
1611
|
+
return paramBindingNames(signature.slice(open + 1, close));
|
|
1612
|
+
}
|
|
1613
|
+
function paramBindingNames(paramList) {
|
|
1614
|
+
const names = [];
|
|
1615
|
+
for (const raw of splitTopLevelCommas(paramList)) {
|
|
1616
|
+
const part = stripDefaultValue(raw).trim().replace(/^\.\.\.\s*/, "");
|
|
1617
|
+
if (!part)
|
|
1618
|
+
continue;
|
|
1619
|
+
if (part.startsWith("{") || part.startsWith("[")) {
|
|
1620
|
+
destructureBindings(firstBalancedGroup(part), names);
|
|
1621
|
+
} else {
|
|
1622
|
+
const ident = /^([A-Za-z_$][\w$]*)/.exec(part);
|
|
1623
|
+
if (ident)
|
|
1624
|
+
names.push(ident[1]);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
return names;
|
|
1628
|
+
}
|
|
1629
|
+
function destructureBindings(pattern, names) {
|
|
1630
|
+
const inner = pattern.slice(1, -1);
|
|
1631
|
+
for (const raw of splitTopLevelCommas(inner)) {
|
|
1632
|
+
const entry = stripDefaultValue(raw).trim().replace(/^\.\.\.\s*/, "");
|
|
1633
|
+
if (!entry)
|
|
1634
|
+
continue;
|
|
1635
|
+
const colon = topLevelColonIndex(entry);
|
|
1636
|
+
const binding = (colon === -1 ? entry : entry.slice(colon + 1)).trim();
|
|
1637
|
+
if (binding.startsWith("{") || binding.startsWith("[")) {
|
|
1638
|
+
destructureBindings(firstBalancedGroup(binding), names);
|
|
1639
|
+
} else {
|
|
1640
|
+
const ident = /^([A-Za-z_$][\w$]*)/.exec(binding);
|
|
1641
|
+
if (ident)
|
|
1642
|
+
names.push(ident[1]);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
function splitTopLevelCommas(text) {
|
|
1647
|
+
const parts = [];
|
|
1648
|
+
let depth = 0;
|
|
1649
|
+
let start = 0;
|
|
1650
|
+
let quote;
|
|
1651
|
+
for (let i = 0;i < text.length; i++) {
|
|
1652
|
+
const current = text[i];
|
|
1653
|
+
if (quote) {
|
|
1654
|
+
if (current === "\\")
|
|
1655
|
+
i++;
|
|
1656
|
+
else if (current === quote)
|
|
1657
|
+
quote = undefined;
|
|
1658
|
+
continue;
|
|
1659
|
+
}
|
|
1660
|
+
if (current === '"' || current === "'" || current === "`")
|
|
1661
|
+
quote = current;
|
|
1662
|
+
else if (current === "{" || current === "[" || current === "(" || current === "<")
|
|
1663
|
+
depth++;
|
|
1664
|
+
else if (current === "}" || current === "]" || current === ")" || current === ">")
|
|
1665
|
+
depth--;
|
|
1666
|
+
else if (current === "," && depth === 0) {
|
|
1667
|
+
parts.push(text.slice(start, i));
|
|
1668
|
+
start = i + 1;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
parts.push(text.slice(start));
|
|
1672
|
+
return parts;
|
|
1673
|
+
}
|
|
1674
|
+
function firstBalancedGroup(text) {
|
|
1675
|
+
const open = text[0];
|
|
1676
|
+
const close = open === "{" ? "}" : "]";
|
|
1677
|
+
let depth = 0;
|
|
1678
|
+
let quote;
|
|
1679
|
+
for (let i = 0;i < text.length; i++) {
|
|
1680
|
+
const current = text[i];
|
|
1681
|
+
if (quote) {
|
|
1682
|
+
if (current === "\\")
|
|
1683
|
+
i++;
|
|
1684
|
+
else if (current === quote)
|
|
1685
|
+
quote = undefined;
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
if (current === '"' || current === "'" || current === "`")
|
|
1689
|
+
quote = current;
|
|
1690
|
+
else if (current === open)
|
|
1691
|
+
depth++;
|
|
1692
|
+
else if (current === close && --depth === 0)
|
|
1693
|
+
return text.slice(0, i + 1);
|
|
1694
|
+
}
|
|
1695
|
+
return text;
|
|
1696
|
+
}
|
|
1697
|
+
function topLevelColonIndex(text) {
|
|
1698
|
+
let depth = 0;
|
|
1699
|
+
let quote;
|
|
1700
|
+
for (let i = 0;i < text.length; i++) {
|
|
1701
|
+
const current = text[i];
|
|
1702
|
+
if (quote) {
|
|
1703
|
+
if (current === "\\")
|
|
1704
|
+
i++;
|
|
1705
|
+
else if (current === quote)
|
|
1706
|
+
quote = undefined;
|
|
1707
|
+
continue;
|
|
1708
|
+
}
|
|
1709
|
+
if (current === '"' || current === "'" || current === "`")
|
|
1710
|
+
quote = current;
|
|
1711
|
+
else if (current === "{" || current === "[" || current === "(" || current === "<")
|
|
1712
|
+
depth++;
|
|
1713
|
+
else if (current === "}" || current === "]" || current === ")" || current === ">")
|
|
1714
|
+
depth--;
|
|
1715
|
+
else if (current === ":" && depth === 0)
|
|
1716
|
+
return i;
|
|
1717
|
+
}
|
|
1718
|
+
return -1;
|
|
1719
|
+
}
|
|
1720
|
+
function stripDefaultValue(entry) {
|
|
1721
|
+
let depth = 0;
|
|
1722
|
+
let quote;
|
|
1723
|
+
for (let i = 0;i < entry.length; i++) {
|
|
1724
|
+
const current = entry[i];
|
|
1725
|
+
if (quote) {
|
|
1726
|
+
if (current === "\\")
|
|
1727
|
+
i++;
|
|
1728
|
+
else if (current === quote)
|
|
1729
|
+
quote = undefined;
|
|
1730
|
+
continue;
|
|
1731
|
+
}
|
|
1732
|
+
if (current === '"' || current === "'" || current === "`")
|
|
1733
|
+
quote = current;
|
|
1734
|
+
else if (current === "{" || current === "[" || current === "(" || current === "<")
|
|
1735
|
+
depth++;
|
|
1736
|
+
else if (current === "}" || current === "]" || current === ")" || current === ">")
|
|
1737
|
+
depth--;
|
|
1738
|
+
else if (current === "=" && depth === 0 && entry[i + 1] !== "=" && entry[i + 1] !== ">" && entry[i - 1] !== "=" && entry[i - 1] !== "!" && entry[i - 1] !== "<" && entry[i - 1] !== ">") {
|
|
1739
|
+
return entry.slice(0, i);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
return entry;
|
|
1743
|
+
}
|
|
1744
|
+
function awaitedIdentifiers(body) {
|
|
1745
|
+
return [...body.matchAll(/\bawait\s+([A-Za-z_$][\w$]*)\b/g)].map((match) => match[1]);
|
|
1746
|
+
}
|
|
1747
|
+
function isCodeOffset(source, target) {
|
|
1748
|
+
let quote;
|
|
1749
|
+
for (let cursor = 0;cursor < target; cursor++) {
|
|
1750
|
+
const current = source[cursor];
|
|
1751
|
+
if (quote) {
|
|
1752
|
+
if (current === "\\")
|
|
1753
|
+
cursor++;
|
|
1754
|
+
else if (current === quote)
|
|
1755
|
+
quote = undefined;
|
|
1756
|
+
continue;
|
|
1757
|
+
}
|
|
1758
|
+
if (current === "/" && source[cursor + 1] === "/") {
|
|
1759
|
+
const newline = source.indexOf(`
|
|
1760
|
+
`, cursor + 2);
|
|
1761
|
+
if (newline === -1 || newline >= target)
|
|
1762
|
+
return false;
|
|
1763
|
+
cursor = newline;
|
|
1764
|
+
continue;
|
|
1765
|
+
}
|
|
1766
|
+
if (current === "/" && source[cursor + 1] === "*") {
|
|
1767
|
+
const end = source.indexOf("*/", cursor + 2);
|
|
1768
|
+
if (end === -1 || end >= target)
|
|
1769
|
+
return false;
|
|
1770
|
+
cursor = end + 1;
|
|
1771
|
+
continue;
|
|
1772
|
+
}
|
|
1773
|
+
if (current === '"' || current === "'" || current === "`")
|
|
1774
|
+
quote = current;
|
|
1775
|
+
}
|
|
1776
|
+
return quote === undefined;
|
|
1777
|
+
}
|
|
1778
|
+
function skipTrivia(source, start) {
|
|
1779
|
+
let cursor = start;
|
|
1780
|
+
while (cursor < source.length) {
|
|
1781
|
+
if (/\s/.test(source[cursor])) {
|
|
1782
|
+
cursor++;
|
|
1783
|
+
continue;
|
|
1784
|
+
}
|
|
1785
|
+
if (source[cursor] === "/" && source[cursor + 1] === "/") {
|
|
1786
|
+
const newline = source.indexOf(`
|
|
1787
|
+
`, cursor + 2);
|
|
1788
|
+
cursor = newline === -1 ? source.length : newline + 1;
|
|
1789
|
+
continue;
|
|
1790
|
+
}
|
|
1791
|
+
if (source[cursor] === "/" && source[cursor + 1] === "*") {
|
|
1792
|
+
const end = source.indexOf("*/", cursor + 2);
|
|
1793
|
+
if (end === -1)
|
|
1794
|
+
return source.length;
|
|
1795
|
+
cursor = end + 2;
|
|
1796
|
+
continue;
|
|
1797
|
+
}
|
|
1798
|
+
return cursor;
|
|
1799
|
+
}
|
|
1800
|
+
return cursor;
|
|
1801
|
+
}
|
|
1802
|
+
function stringEnd(source, start, quote) {
|
|
1803
|
+
for (let cursor = start + 1;cursor < source.length; cursor++) {
|
|
1804
|
+
if (source[cursor] === "\\") {
|
|
1805
|
+
cursor++;
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1808
|
+
if (source[cursor] === quote)
|
|
1809
|
+
return cursor;
|
|
1810
|
+
}
|
|
1811
|
+
return -1;
|
|
1812
|
+
}
|
|
1813
|
+
function validateCodemodComments(routes) {
|
|
1814
|
+
for (const file of new Set(routes.map((route) => route.file))) {
|
|
1815
|
+
const source = readSource(file);
|
|
1816
|
+
if (source === undefined)
|
|
1817
|
+
continue;
|
|
1818
|
+
const match = /@next-codemod-error\s+([^\n*]+)/.exec(source);
|
|
1819
|
+
if (match?.[1]) {
|
|
1820
|
+
throw new PnextBuildValidationError(unresolvedCodemodCommentMessage(match[1].trim()));
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
function validateRootLayout(config, pageRoutes) {
|
|
1825
|
+
if (pageRoutes.length === 0)
|
|
1826
|
+
return;
|
|
1827
|
+
const hasRootLayout = pageExtensions().some((ext) => existsSync(path2.join(config.appPath, `layout.${ext}`)));
|
|
1828
|
+
if (hasRootLayout)
|
|
1829
|
+
return;
|
|
1830
|
+
const orphan = pageRoutes.find((route) => !hasAncestorLayout(config.appPath, route.file));
|
|
1831
|
+
if (!orphan)
|
|
1832
|
+
return;
|
|
1833
|
+
throw new PnextBuildValidationError(missingRootLayoutMessage(appDirRelativeFile(config, orphan.file)));
|
|
1834
|
+
}
|
|
1835
|
+
function hasAncestorLayout(appPath, routeFile) {
|
|
1836
|
+
let dir = path2.dirname(routeFile);
|
|
1837
|
+
while (dir.startsWith(appPath)) {
|
|
1838
|
+
if (pageExtensions().some((ext) => existsSync(path2.join(dir, `layout.${ext}`))))
|
|
1839
|
+
return true;
|
|
1840
|
+
if (dir === appPath)
|
|
1841
|
+
break;
|
|
1842
|
+
dir = path2.dirname(dir);
|
|
1843
|
+
}
|
|
1844
|
+
return false;
|
|
1845
|
+
}
|
|
1846
|
+
function pageExtensions() {
|
|
1847
|
+
return [...new Set([...BASE_PAGE_EXTENSIONS, ...extraPageExtensions()])];
|
|
1848
|
+
}
|
|
1849
|
+
function validateAppPagesConflict(config) {
|
|
1850
|
+
const pagesDir = pagesDirFor(config);
|
|
1851
|
+
if (!pagesDir || !existsSync(pagesDir))
|
|
1852
|
+
return;
|
|
1853
|
+
const pagePaths = collectPagesRouterPaths(pagesDir);
|
|
1854
|
+
if (pagePaths.size === 0)
|
|
1855
|
+
return;
|
|
1856
|
+
const appPaths = collectAppRouterPaths(path2.join(config.root, "app"));
|
|
1857
|
+
const conflicts = [];
|
|
1858
|
+
for (const [route, app] of appPaths) {
|
|
1859
|
+
const page = pagePaths.get(route);
|
|
1860
|
+
if (page)
|
|
1861
|
+
conflicts.push({ page, app });
|
|
1862
|
+
}
|
|
1863
|
+
if (conflicts.length === 0)
|
|
1864
|
+
return;
|
|
1865
|
+
throw new PnextBuildValidationError(conflictingAppAndPageMessage(dedupeConflicts(conflicts).sort(conflictSort)));
|
|
1866
|
+
}
|
|
1867
|
+
function pagesDirFor(config) {
|
|
1868
|
+
return path2.join(config.root, "pages");
|
|
1869
|
+
}
|
|
1870
|
+
function collectAppRouterPaths(appDir) {
|
|
1871
|
+
const paths = new Map;
|
|
1872
|
+
if (!existsSync(appDir))
|
|
1873
|
+
return paths;
|
|
1874
|
+
const walk = (dir, segments) => {
|
|
1875
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1876
|
+
const full = path2.join(dir, entry.name);
|
|
1877
|
+
if (entry.isDirectory()) {
|
|
1878
|
+
if (entry.name.startsWith("@") || entry.name.startsWith("(") && entry.name.includes("."))
|
|
1879
|
+
continue;
|
|
1880
|
+
walk(full, entry.name.startsWith("(") && entry.name.endsWith(")") ? segments : [...segments, entry.name]);
|
|
1881
|
+
continue;
|
|
1882
|
+
}
|
|
1883
|
+
if (!/^page\.(?:tsx|ts|jsx|js|mjs)$/.test(entry.name))
|
|
1884
|
+
continue;
|
|
1885
|
+
const route = segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
1886
|
+
paths.set(route, toPosix(path2.relative(path2.dirname(appDir), full)));
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
walk(appDir, []);
|
|
1890
|
+
return paths;
|
|
1891
|
+
}
|
|
1892
|
+
function collectPagesRouterPaths(pagesDir) {
|
|
1893
|
+
const paths = new Map;
|
|
1894
|
+
const walk = (dir, prefix) => {
|
|
1895
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1896
|
+
if (entry.name.startsWith("_"))
|
|
1897
|
+
continue;
|
|
1898
|
+
const full = path2.join(dir, entry.name);
|
|
1899
|
+
if (entry.isDirectory()) {
|
|
1900
|
+
if (entry.name === "api")
|
|
1901
|
+
continue;
|
|
1902
|
+
walk(full, `${prefix}/${entry.name}`);
|
|
1903
|
+
continue;
|
|
1904
|
+
}
|
|
1905
|
+
const match = /^(.*)\.(tsx|ts|jsx|js|mjs)$/.exec(entry.name);
|
|
1906
|
+
if (!match)
|
|
1907
|
+
continue;
|
|
1908
|
+
const base = match[1];
|
|
1909
|
+
const rel = toPosix(path2.relative(path2.dirname(pagesDir), full));
|
|
1910
|
+
if (base === "index") {
|
|
1911
|
+
paths.set(prefix || "/", rel);
|
|
1912
|
+
} else {
|
|
1913
|
+
paths.set(`${prefix}/${base}`, rel);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1917
|
+
walk(pagesDir, "");
|
|
1918
|
+
return paths;
|
|
1919
|
+
}
|
|
1920
|
+
function dedupeConflicts(conflicts) {
|
|
1921
|
+
const seen = new Set;
|
|
1922
|
+
return conflicts.filter((conflict) => {
|
|
1923
|
+
const key = `${conflict.page}\x00${conflict.app}`;
|
|
1924
|
+
if (seen.has(key))
|
|
1925
|
+
return false;
|
|
1926
|
+
seen.add(key);
|
|
1927
|
+
return true;
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1930
|
+
function conflictSort(a, b) {
|
|
1931
|
+
return a.page.localeCompare(b.page) || a.app.localeCompare(b.app);
|
|
1932
|
+
}
|
|
1933
|
+
function validateParallelPageConflicts(config, pageRoutes) {
|
|
1934
|
+
const byPattern = new Map;
|
|
1935
|
+
for (const route of pageRoutes) {
|
|
1936
|
+
if (route.synthetic)
|
|
1937
|
+
continue;
|
|
1938
|
+
const existing = byPattern.get(route.pattern);
|
|
1939
|
+
if (existing) {
|
|
1940
|
+
const labels = [routeGroupLabel(config, existing), routeGroupLabel(config, route)].sort();
|
|
1941
|
+
throw new PnextBuildValidationError(conflictingParallelPagesMessage(labels[0], labels[1]));
|
|
1942
|
+
}
|
|
1943
|
+
byPattern.set(route.pattern, route);
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
function routeGroupLabel(config, route) {
|
|
1947
|
+
const dir = path2.dirname(appDirRelativeFile(config, route.file));
|
|
1948
|
+
return dir === "." ? "/" : `/${dir}`;
|
|
1949
|
+
}
|
|
1950
|
+
function validateMissingSlotDefaults(config, routes) {
|
|
1951
|
+
const failures = [];
|
|
1952
|
+
const interceptedTargets = interceptedTargetDirs(routes);
|
|
1953
|
+
const visit = (dir) => {
|
|
1954
|
+
for (const entry of readDirEntries(dir)) {
|
|
1955
|
+
if (!entry.isDirectory())
|
|
1956
|
+
continue;
|
|
1957
|
+
const child = path2.join(dir, entry.name);
|
|
1958
|
+
if (isSlotDir(entry.name))
|
|
1959
|
+
continue;
|
|
1960
|
+
visit(child);
|
|
1961
|
+
}
|
|
1962
|
+
if (!hasNormalChildRoute(dir))
|
|
1963
|
+
return;
|
|
1964
|
+
if (interceptedTargets.has(dir))
|
|
1965
|
+
return;
|
|
1966
|
+
for (const slot of readDirEntries(dir)) {
|
|
1967
|
+
if (!slot.isDirectory() || !isNamedSlotDir(slot.name))
|
|
1968
|
+
continue;
|
|
1969
|
+
const slotDir = path2.join(dir, slot.name);
|
|
1970
|
+
if (hasConventionFile(slotDir, "default"))
|
|
1971
|
+
continue;
|
|
1972
|
+
if (slotHasCatchAllPage(slotDir))
|
|
1973
|
+
continue;
|
|
1974
|
+
failures.push(missingDefaultParallelRouteMessage(appPath(config, slotDir), slot.name));
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
visit(config.appPath);
|
|
1978
|
+
if (failures.length > 0)
|
|
1979
|
+
throw new PnextBuildValidationError(failures.join(`
|
|
1980
|
+
|
|
1981
|
+
`));
|
|
1982
|
+
}
|
|
1983
|
+
function interceptedTargetDirs(routes) {
|
|
1984
|
+
const patterns = new Set(routes.filter((route) => route.kind === "page" && route.interception).map((route) => route.pattern));
|
|
1985
|
+
return new Set(routes.filter((route) => route.kind === "page" && !route.interception && patterns.has(route.pattern)).map((route) => path2.dirname(route.file)));
|
|
1986
|
+
}
|
|
1987
|
+
function hasNormalChildRoute(dir, depth = 0) {
|
|
1988
|
+
for (const entry of readDirEntries(dir)) {
|
|
1989
|
+
if (!entry.isDirectory() || isSlotDir(entry.name))
|
|
1990
|
+
continue;
|
|
1991
|
+
const child = path2.join(dir, entry.name);
|
|
1992
|
+
const nextDepth = isGroupDir(entry.name) ? depth : depth + 1;
|
|
1993
|
+
if (nextDepth > 0 && (hasConventionFile(child, "page") || hasConventionFile(child, "default"))) {
|
|
1994
|
+
return true;
|
|
1995
|
+
}
|
|
1996
|
+
if (hasNormalChildRoute(child, nextDepth))
|
|
1997
|
+
return true;
|
|
1998
|
+
}
|
|
1999
|
+
return false;
|
|
2000
|
+
}
|
|
2001
|
+
function slotHasCatchAllPage(dir) {
|
|
2002
|
+
for (const entry of readDirEntries(dir)) {
|
|
2003
|
+
if (!entry.isDirectory())
|
|
2004
|
+
continue;
|
|
2005
|
+
const child = path2.join(dir, entry.name);
|
|
2006
|
+
if (/^\[\[?\.\.\..+\]\]?$/.test(entry.name) && hasConventionFile(child, "page"))
|
|
2007
|
+
return true;
|
|
2008
|
+
if (slotHasCatchAllPage(child))
|
|
2009
|
+
return true;
|
|
2010
|
+
}
|
|
2011
|
+
return false;
|
|
2012
|
+
}
|
|
2013
|
+
function hasConventionFile(dir, name) {
|
|
2014
|
+
return pageExtensions().some((ext) => existsSync(path2.join(dir, `${name}.${ext}`)));
|
|
2015
|
+
}
|
|
2016
|
+
function readDirEntries(dir) {
|
|
2017
|
+
try {
|
|
2018
|
+
return readdirSync(dir, { withFileTypes: true });
|
|
2019
|
+
} catch {
|
|
2020
|
+
return [];
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
function isSlotDir(name) {
|
|
2024
|
+
return name.startsWith("@");
|
|
2025
|
+
}
|
|
2026
|
+
function isNamedSlotDir(name) {
|
|
2027
|
+
return isSlotDir(name) && name !== "@children";
|
|
2028
|
+
}
|
|
2029
|
+
function isGroupDir(name) {
|
|
2030
|
+
return name.startsWith("(") && name.endsWith(")");
|
|
2031
|
+
}
|
|
2032
|
+
function appPath(config, file) {
|
|
2033
|
+
return `app/${appDirRelativeFile(config, file)}`;
|
|
2034
|
+
}
|
|
2035
|
+
function validateDefaultExports(config, routes) {
|
|
2036
|
+
const failures = [];
|
|
2037
|
+
const appPath2 = path2.resolve(config.appPath);
|
|
2038
|
+
for (const route of routes) {
|
|
2039
|
+
if (route.kind !== "page" || route.interception || route.synthetic)
|
|
2040
|
+
continue;
|
|
2041
|
+
for (const file of defaultExportFiles(route)) {
|
|
2042
|
+
if (/\.mdx?$/.test(file))
|
|
2043
|
+
continue;
|
|
2044
|
+
if (isRootLayoutFile(appPath2, file))
|
|
2045
|
+
continue;
|
|
2046
|
+
const source = readSource(file);
|
|
2047
|
+
if (source === undefined)
|
|
2048
|
+
continue;
|
|
2049
|
+
if (!hasDefaultExport(stripCommentsAndStrings(source))) {
|
|
2050
|
+
failures.push(undefinedDefaultExportMessage(componentRoutePath(route, file)));
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
if (failures.length > 0)
|
|
2055
|
+
throw new PnextBuildValidationError([...new Set(failures)].join(`
|
|
2056
|
+
`));
|
|
2057
|
+
}
|
|
2058
|
+
function defaultExportFiles(route) {
|
|
2059
|
+
const files = new Set([route.file]);
|
|
2060
|
+
const dir = path2.dirname(route.file);
|
|
2061
|
+
for (const ext of pageExtensions()) {
|
|
2062
|
+
files.add(path2.join(dir, `layout.${ext}`));
|
|
2063
|
+
files.add(path2.join(dir, `not-found.${ext}`));
|
|
2064
|
+
}
|
|
2065
|
+
return [...files].filter((file) => existsSync(file));
|
|
2066
|
+
}
|
|
2067
|
+
function isRootLayoutFile(appPath2, file) {
|
|
2068
|
+
return path2.basename(file).replace(/\.[^.]+$/, "") === "layout" && path2.resolve(path2.dirname(file)) === appPath2;
|
|
2069
|
+
}
|
|
2070
|
+
function componentRoutePath(route, file) {
|
|
2071
|
+
const convention = path2.basename(file).replace(/\.(tsx|ts|jsx|js|mjs)$/, "");
|
|
2072
|
+
const routePath = route.route || "/";
|
|
2073
|
+
if (convention === "page")
|
|
2074
|
+
return routePath === "/" ? "/page" : `${routePath}/page`;
|
|
2075
|
+
return `${routePath === "/" ? "" : routePath}/${convention}`;
|
|
2076
|
+
}
|
|
2077
|
+
function hasDefaultExport(searchable) {
|
|
2078
|
+
return /\bexport\s+default\b/.test(searchable) || hasDefaultNamedExport(searchable);
|
|
2079
|
+
}
|
|
2080
|
+
function hasDefaultNamedExport(searchable) {
|
|
2081
|
+
for (const match of searchable.matchAll(/\bexport\s*\{([^}]*)\}/g)) {
|
|
2082
|
+
const specifiers = match[1]?.split(",") ?? [];
|
|
2083
|
+
if (specifiers.some(exportsDefaultSpecifier))
|
|
2084
|
+
return true;
|
|
2085
|
+
}
|
|
2086
|
+
return false;
|
|
2087
|
+
}
|
|
2088
|
+
function exportsDefaultSpecifier(specifier) {
|
|
2089
|
+
const parts = specifier.trim().split(/\s+as\s+/);
|
|
2090
|
+
return parts.length === 1 ? parts[0] === "default" : parts.at(-1) === "default";
|
|
2091
|
+
}
|
|
2092
|
+
function validateSearchParamsSuspense(config, pageRoutes) {
|
|
2093
|
+
for (const route of pageRoutes) {
|
|
2094
|
+
if (!route.client)
|
|
2095
|
+
continue;
|
|
2096
|
+
if (!isStaticallyPrerendered(route))
|
|
2097
|
+
continue;
|
|
2098
|
+
const source = readSource(route.file);
|
|
2099
|
+
if (source === undefined)
|
|
2100
|
+
continue;
|
|
2101
|
+
const stripped = stripCommentsAndStrings(source);
|
|
2102
|
+
if (/\buseSyncExternalStore\s*\(/.test(stripped))
|
|
2103
|
+
continue;
|
|
2104
|
+
if (!usesSearchParamsHook(stripped))
|
|
2105
|
+
continue;
|
|
2106
|
+
if (fileTreeHasSuspense(config, route))
|
|
2107
|
+
continue;
|
|
2108
|
+
throw new PnextBuildValidationError(missingSuspenseWithCsrBailoutMessage(route.route || "/"));
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
function usesSearchParamsHook(searchable) {
|
|
2112
|
+
return /\buseSearchParams\s*\(/.test(searchable);
|
|
2113
|
+
}
|
|
2114
|
+
function isStaticallyPrerendered(route) {
|
|
2115
|
+
const config = route.segmentConfig;
|
|
2116
|
+
const configForcesDynamic = config?.dynamic === "force-dynamic" || config?.revalidate === 0 || config?.fetchCache === "force-no-store";
|
|
2117
|
+
if (configForcesDynamic)
|
|
2118
|
+
return false;
|
|
2119
|
+
const isDynamicRoute = route.params.length > 0 || Boolean(route.catchAll);
|
|
2120
|
+
if (isDynamicRoute && !route.hasStaticParams)
|
|
2121
|
+
return false;
|
|
2122
|
+
return true;
|
|
2123
|
+
}
|
|
2124
|
+
function fileTreeHasSuspense(config, route) {
|
|
2125
|
+
const files = [route.file, ...layoutChain(config.appPath, route.file)];
|
|
2126
|
+
for (const file of files) {
|
|
2127
|
+
const source = readSource(file);
|
|
2128
|
+
if (source === undefined)
|
|
2129
|
+
continue;
|
|
2130
|
+
if (/<Suspense[\s/>]/.test(source) || /\bReact\.Suspense\b/.test(source))
|
|
2131
|
+
return true;
|
|
2132
|
+
}
|
|
2133
|
+
return false;
|
|
2134
|
+
}
|
|
2135
|
+
function layoutChain(appPath2, routeFile) {
|
|
2136
|
+
const files = [];
|
|
2137
|
+
let dir = path2.dirname(routeFile);
|
|
2138
|
+
while (dir.startsWith(appPath2)) {
|
|
2139
|
+
for (const ext of pageExtensions()) {
|
|
2140
|
+
const candidate = path2.join(dir, `layout.${ext}`);
|
|
2141
|
+
if (existsSync(candidate))
|
|
2142
|
+
files.push(candidate);
|
|
2143
|
+
}
|
|
2144
|
+
if (dir === appPath2)
|
|
2145
|
+
break;
|
|
2146
|
+
dir = path2.dirname(dir);
|
|
2147
|
+
}
|
|
2148
|
+
return files;
|
|
2149
|
+
}
|
|
2150
|
+
function validateExportMode(config, routes) {
|
|
2151
|
+
const nextConfig = getNextConfig();
|
|
2152
|
+
if (nextConfig.output !== "export")
|
|
2153
|
+
return;
|
|
2154
|
+
const hasAppPages = routes.some((route) => route.kind === "page" && !route.interception);
|
|
2155
|
+
if (hasAppPages && typeof nextConfig.exportPathMap === "function") {
|
|
2156
|
+
throw new PnextBuildValidationError(exportPathMapWithAppDirMessage());
|
|
2157
|
+
}
|
|
2158
|
+
if (routesUseServerActions(routes)) {
|
|
2159
|
+
throw new PnextBuildValidationError("Server Actions are not supported with static export.");
|
|
2160
|
+
}
|
|
2161
|
+
if (routes.some((route) => route.interception)) {
|
|
2162
|
+
throw new PnextBuildValidationError("Intercepting routes are not supported with static export.");
|
|
2163
|
+
}
|
|
2164
|
+
for (const route of routes) {
|
|
2165
|
+
if (route.interception || route.synthetic)
|
|
2166
|
+
continue;
|
|
2167
|
+
if (route.segmentConfig?.dynamic === "force-dynamic") {
|
|
2168
|
+
throw new PnextBuildValidationError(route.kind === "page" ? forceDynamicPageWithExportMessage() : dynamicForceDynamicWithExportMessage(nextPagePath(route)));
|
|
2169
|
+
}
|
|
2170
|
+
if (route.kind === "handler" && !routeHandlerStaticExportable(route)) {
|
|
2171
|
+
throw new PnextBuildValidationError(routeHandlerNotStaticWithExportMessage(nextPagePath(route)));
|
|
2172
|
+
}
|
|
2173
|
+
const isDynamicRoute = route.params.length > 0 || Boolean(route.catchAll);
|
|
2174
|
+
if (route.kind === "page" && isDynamicRoute && !route.hasStaticParams) {
|
|
2175
|
+
throw new PnextBuildValidationError(missingGenerateStaticParamsForExportMessage(nextPagePath(route)));
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
function routesUseServerActions(routes) {
|
|
2180
|
+
const seen = new Set;
|
|
2181
|
+
for (const route of routes) {
|
|
2182
|
+
for (const file of route.sourceFiles ?? []) {
|
|
2183
|
+
if (seen.has(file))
|
|
2184
|
+
continue;
|
|
2185
|
+
seen.add(file);
|
|
2186
|
+
const source = readSource(file);
|
|
2187
|
+
if (source === undefined)
|
|
2188
|
+
continue;
|
|
2189
|
+
if (/(["'])use server\1\s*;?/.test(source))
|
|
2190
|
+
return true;
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
return false;
|
|
2194
|
+
}
|
|
2195
|
+
function routeHandlerStaticExportable(route) {
|
|
2196
|
+
const config = route.segmentConfig;
|
|
2197
|
+
return config?.dynamic === "force-static" || config?.dynamic === "error" || config?.revalidate === false || typeof config?.revalidate === "number" && config.revalidate > 0 || route.hasStaticParams;
|
|
2198
|
+
}
|
|
2199
|
+
function nextPagePath(route) {
|
|
2200
|
+
let value = route.route || "/";
|
|
2201
|
+
if (route.catchAll) {
|
|
2202
|
+
const token = route.catchAllOptional ? `[[...${route.catchAll}]]` : `[...${route.catchAll}]`;
|
|
2203
|
+
value = value.replace(`:${route.catchAll}*`, token);
|
|
2204
|
+
}
|
|
2205
|
+
for (const param of route.params)
|
|
2206
|
+
value = value.replace(`:${param}`, `[${param}]`);
|
|
2207
|
+
return value;
|
|
2208
|
+
}
|
|
2209
|
+
function appDirRelativeFile(config, file) {
|
|
2210
|
+
return toPosix(path2.relative(config.appPath, file));
|
|
2211
|
+
}
|
|
2212
|
+
function toPosix(file) {
|
|
2213
|
+
return file.split(path2.sep).join("/");
|
|
2214
|
+
}
|
|
2215
|
+
function stripCommentsAndStrings(source) {
|
|
2216
|
+
let out = "";
|
|
2217
|
+
let i = 0;
|
|
2218
|
+
const n = source.length;
|
|
2219
|
+
while (i < n) {
|
|
2220
|
+
const ch = source[i];
|
|
2221
|
+
const next = source[i + 1];
|
|
2222
|
+
if (ch === "/" && next === "*") {
|
|
2223
|
+
const end = source.indexOf("*/", i + 2);
|
|
2224
|
+
out += " ";
|
|
2225
|
+
i = end === -1 ? n : end + 2;
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
if (ch === "/" && next === "/") {
|
|
2229
|
+
const end = source.indexOf(`
|
|
2230
|
+
`, i + 2);
|
|
2231
|
+
out += " ";
|
|
2232
|
+
i = end === -1 ? n : end;
|
|
2233
|
+
continue;
|
|
2234
|
+
}
|
|
2235
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
2236
|
+
const quote = ch;
|
|
2237
|
+
out += quote;
|
|
2238
|
+
i += 1;
|
|
2239
|
+
while (i < n) {
|
|
2240
|
+
const c = source[i];
|
|
2241
|
+
if (c === "\\") {
|
|
2242
|
+
i += 2;
|
|
2243
|
+
continue;
|
|
2244
|
+
}
|
|
2245
|
+
if (c === quote) {
|
|
2246
|
+
i += 1;
|
|
2247
|
+
break;
|
|
2248
|
+
}
|
|
2249
|
+
i += 1;
|
|
2250
|
+
}
|
|
2251
|
+
out += quote;
|
|
2252
|
+
continue;
|
|
2253
|
+
}
|
|
2254
|
+
out += ch;
|
|
2255
|
+
i += 1;
|
|
2256
|
+
}
|
|
2257
|
+
return out;
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
// src/compat/segment/tree.ts
|
|
2261
|
+
var TREE_SEGMENT_PATH = "/_tree";
|
|
2262
|
+
var DEFAULT_DYNAMIC_STALE_TIME_SECONDS = 0;
|
|
2263
|
+
var DEFAULT_STATIC_STALE_TIME_SECONDS = 300;
|
|
2264
|
+
function buildRootTreePrefetch(options) {
|
|
2265
|
+
const staleTime = options.staleTimeSeconds ?? (options.isStatic ? DEFAULT_STATIC_STALE_TIME_SECONDS : DEFAULT_DYNAMIC_STALE_TIME_SECONDS);
|
|
2266
|
+
return {
|
|
2267
|
+
...options.buildId ? { buildId: options.buildId } : {},
|
|
2268
|
+
tree: buildTree(options),
|
|
2269
|
+
staleTime,
|
|
2270
|
+
isStatic: options.isStatic,
|
|
2271
|
+
...options.vary ? { vary: options.vary } : {},
|
|
2272
|
+
...options.routePattern ? { route: options.routePattern } : {},
|
|
2273
|
+
...options.params ? { params: options.params } : {},
|
|
2274
|
+
...options.headOutlined ? { headOutlined: true } : {},
|
|
2275
|
+
...options.headFirst ? { headFirst: true } : {}
|
|
2276
|
+
};
|
|
2277
|
+
}
|
|
2278
|
+
function buildTree(options) {
|
|
2279
|
+
const parts = routeParts(options);
|
|
2280
|
+
const bodySize = options.bodySizeBytes ?? 0;
|
|
2281
|
+
const budget = options.inlineBudgetBytes ?? 32 * 1024;
|
|
2282
|
+
const canInlineBody = options.isStatic && !options.postponed && bodySize <= budget;
|
|
2283
|
+
let child = pageNode(parts.length === 0, {
|
|
2284
|
+
isStatic: options.isStatic,
|
|
2285
|
+
canInlineBody,
|
|
2286
|
+
bodySizeBytes: options.bodySizeBytes,
|
|
2287
|
+
...options.vary ? { varyParams: options.vary.params } : {}
|
|
2288
|
+
});
|
|
2289
|
+
for (let index = parts.length - 1;index >= 0; index--) {
|
|
2290
|
+
child = routeNode(parts[index], child, index === 0, {
|
|
2291
|
+
isStatic: options.isStatic,
|
|
2292
|
+
canInlineBody,
|
|
2293
|
+
runtimePrefetch: options.runtimePrefetch
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
return {
|
|
2297
|
+
name: "",
|
|
2298
|
+
param: null,
|
|
2299
|
+
slots: { children: child },
|
|
2300
|
+
prefetchHints: 16 /* IsRootLayout */ | (canInlineBody ? 64 /* InlinedIntoChild */ : 0)
|
|
2301
|
+
};
|
|
2302
|
+
}
|
|
2303
|
+
function routeParts(options) {
|
|
2304
|
+
const source = options.routeId ?? options.pathname;
|
|
2305
|
+
if (source === "index" || source === "/")
|
|
2306
|
+
return [];
|
|
2307
|
+
return source.split("/").map((part) => part.trim()).filter(Boolean).filter((part) => !part.startsWith("(") && !part.startsWith("@")).map((part) => part === "index" ? "__PAGE__" : part);
|
|
2308
|
+
}
|
|
2309
|
+
function routeNode(name, child, parentInlined, options) {
|
|
2310
|
+
const dynamic = !options.isStatic || name.includes("instant-false");
|
|
2311
|
+
const runtime = Boolean(options.runtimePrefetch) || name.includes("runtime");
|
|
2312
|
+
const inlinesIntoChild = options.canInlineBody && !dynamic && !runtime;
|
|
2313
|
+
return {
|
|
2314
|
+
name,
|
|
2315
|
+
param: name.startsWith("[") ? { type: "d", key: null, siblings: null } : null,
|
|
2316
|
+
slots: {
|
|
2317
|
+
children: { ...child, prefetchHints: child.prefetchHints | parentHint(inlinesIntoChild) }
|
|
2318
|
+
},
|
|
2319
|
+
prefetchHints: (parentInlined ? 32 /* ParentInlinedIntoSelf */ : 0) | (runtime ? 1 /* HasRuntimePrefetch */ : 0) | (dynamic ? 1024 /* PrefetchDisabled */ : 0) | (inlinesIntoChild ? 64 /* InlinedIntoChild */ : 0)
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
function pageNode(parentInlined, options) {
|
|
2323
|
+
return {
|
|
2324
|
+
name: "__PAGE__",
|
|
2325
|
+
param: null,
|
|
2326
|
+
slots: null,
|
|
2327
|
+
prefetchHints: (parentInlined ? 32 /* ParentInlinedIntoSelf */ : 0) | (options.canInlineBody ? 128 /* HeadInlinedIntoSelf */ : 256 /* HeadOutlined */),
|
|
2328
|
+
...options.bodySizeBytes !== undefined ? { sizeBytes: options.bodySizeBytes } : {},
|
|
2329
|
+
...options.canInlineBody ? {} : { segmentPath: ROUTE_SEGMENT_PATH },
|
|
2330
|
+
...options.varyParams ? { varyParams: options.varyParams } : {}
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
function parentHint(enabled) {
|
|
2334
|
+
return enabled ? 32 /* ParentInlinedIntoSelf */ : 0;
|
|
2335
|
+
}
|
|
2336
|
+
function rootTreePrefetchText(payload, format = "json") {
|
|
2337
|
+
const json = JSON.stringify(payload);
|
|
2338
|
+
return format === "flight" ? `0:${json}` : json;
|
|
2339
|
+
}
|
|
2340
|
+
function treePrefetchResponse(payload, options = {}) {
|
|
2341
|
+
return new Response(rootTreePrefetchText(payload, options.format), {
|
|
2342
|
+
status: 200,
|
|
2343
|
+
headers: {
|
|
2344
|
+
"content-type": RSC_CONTENT_TYPE_HEADER,
|
|
2345
|
+
"x-nextjs-postponed": "2",
|
|
2346
|
+
"x-nextjs-stale-time": String(payload.staleTime),
|
|
2347
|
+
...payload.isStatic ? { "x-nextjs-prerender": "1" } : {},
|
|
2348
|
+
"cache-control": payload.isStatic ? "s-maxage=31536000, stale-while-revalidate" : "private, no-store"
|
|
2349
|
+
}
|
|
2350
|
+
});
|
|
2351
|
+
}
|
|
2352
|
+
var ROUTE_SEGMENT_PATH = "/";
|
|
2353
|
+
function segmentBodyText(segment, html, format = "flight", vary, shell) {
|
|
2354
|
+
const payload = {
|
|
2355
|
+
segment,
|
|
2356
|
+
html,
|
|
2357
|
+
...vary ? { vary: vary.vary } : {},
|
|
2358
|
+
...vary?.layoutVary ? { layoutVary: vary.layoutVary } : {},
|
|
2359
|
+
...vary?.pageVary ? { pageVary: vary.pageVary } : {},
|
|
2360
|
+
...vary?.route ? { route: vary.route } : {},
|
|
2361
|
+
...vary?.params ? { params: vary.params } : {},
|
|
2362
|
+
...shell ? { shell } : {}
|
|
2363
|
+
};
|
|
2364
|
+
const json = JSON.stringify(payload);
|
|
2365
|
+
return format === "flight" ? `0:${json}` : json;
|
|
2366
|
+
}
|
|
2367
|
+
var SEGMENT_VARY_HEADER = "x-pnext-segment-vary";
|
|
2368
|
+
var SEGMENT_ROUTE_HEADER = "x-pnext-segment-route";
|
|
2369
|
+
var SEGMENT_LAYOUT_VARY_HEADER = "x-pnext-segment-layout-vary";
|
|
2370
|
+
var SEGMENT_PAGE_VARY_HEADER = "x-pnext-segment-page-vary";
|
|
2371
|
+
function buildSegmentMeta(options) {
|
|
2372
|
+
const inlined = !options.postponed && options.bodySizeBytes !== undefined && options.bodySizeBytes <= (options.inlineBudgetBytes ?? 32 * 1024);
|
|
2373
|
+
return {
|
|
2374
|
+
status: options.status,
|
|
2375
|
+
staleTime: options.staleTime,
|
|
2376
|
+
postponed: options.postponed,
|
|
2377
|
+
segmentPaths: [TREE_SEGMENT_PATH, ROUTE_SEGMENT_PATH],
|
|
2378
|
+
...options.bodySizeBytes !== undefined ? { segmentSizes: { [ROUTE_SEGMENT_PATH]: options.bodySizeBytes } } : {},
|
|
2379
|
+
...inlined ? { inlinedSegmentPaths: [ROUTE_SEGMENT_PATH] } : {},
|
|
2380
|
+
...options.prefetchHints ? { prefetchHints: options.prefetchHints } : {},
|
|
2381
|
+
...options.vary ? {
|
|
2382
|
+
vary: varyNamesFor(options.vary, "body"),
|
|
2383
|
+
...options.vary.params.length > 0 || options.vary.search ? {
|
|
2384
|
+
layoutVary: varyNamesFor(options.vary, "layout"),
|
|
2385
|
+
pageVary: varyNamesFor(options.vary, "page")
|
|
2386
|
+
} : {}
|
|
2387
|
+
} : {}
|
|
2388
|
+
};
|
|
2389
|
+
}
|
|
2390
|
+
function segmentBodyResponse(body, staleTimeSeconds, postponed = false, prerendered = false, deploymentId, segment = ROUTE_SEGMENT_PATH, vary, shell) {
|
|
2391
|
+
const cacheable = prerendered && !postponed;
|
|
2392
|
+
return new Response(segmentBodyText(segment, body, "flight", vary, shell), {
|
|
2393
|
+
status: 200,
|
|
2394
|
+
headers: {
|
|
2395
|
+
"content-type": RSC_CONTENT_TYPE_HEADER,
|
|
2396
|
+
"x-nextjs-stale-time": String(staleTimeSeconds),
|
|
2397
|
+
"x-nextjs-postponed": "2",
|
|
2398
|
+
...postponed ? { "x-pnext-segment-postponed": "1" } : {},
|
|
2399
|
+
...prerendered ? { "x-nextjs-prerender": "1" } : {},
|
|
2400
|
+
...deploymentId ? { "x-nextjs-deployment-id": deploymentId } : {},
|
|
2401
|
+
...vary ? { [SEGMENT_VARY_HEADER]: vary.vary.join(",") } : {},
|
|
2402
|
+
...vary?.layoutVary ? { [SEGMENT_LAYOUT_VARY_HEADER]: vary.layoutVary.join(",") } : {},
|
|
2403
|
+
...vary?.pageVary ? { [SEGMENT_PAGE_VARY_HEADER]: vary.pageVary.join(",") } : {},
|
|
2404
|
+
...vary?.route ? { [SEGMENT_ROUTE_HEADER]: vary.route } : {},
|
|
2405
|
+
"cache-control": cacheable ? "s-maxage=31536000, stale-while-revalidate" : "private, no-store"
|
|
2406
|
+
}
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
function segmentDir(outPath, routeId) {
|
|
2410
|
+
return `${outPath}/segments/${routeId}`;
|
|
2411
|
+
}
|
|
2412
|
+
function treeSegmentFile(outPath, routeId) {
|
|
2413
|
+
return `${segmentDir(outPath, routeId)}/_tree.segment.rsc`;
|
|
2414
|
+
}
|
|
2415
|
+
function bodySegmentFile(outPath, routeId) {
|
|
2416
|
+
return `${segmentDir(outPath, routeId)}/index.segment.rsc`;
|
|
2417
|
+
}
|
|
2418
|
+
function segmentMetaFile(outPath, routeId) {
|
|
2419
|
+
return `${segmentDir(outPath, routeId)}/route.segment.meta`;
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
// src/compat/bundler/wasm.ts
|
|
2423
|
+
import { createHash } from "crypto";
|
|
2424
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2425
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
2426
|
+
import path3 from "path";
|
|
2427
|
+
var WASM_MODULE_FILTER = /\.wasm\?module(?:[?#].*)?$/;
|
|
2428
|
+
var manifestWasmBindings = new Map;
|
|
2429
|
+
function outPathKey(outPath) {
|
|
2430
|
+
return path3.resolve(outPath);
|
|
2431
|
+
}
|
|
2432
|
+
function sourcePathFromSpecifier(specifier, resolveDir) {
|
|
2433
|
+
const [sourcePath] = specifier.split(/[?#]/, 1);
|
|
2434
|
+
if (!sourcePath)
|
|
2435
|
+
return;
|
|
2436
|
+
return path3.isAbsolute(sourcePath) ? sourcePath : path3.resolve(resolveDir, sourcePath);
|
|
2437
|
+
}
|
|
2438
|
+
function assetFileName(bytes) {
|
|
2439
|
+
const hash = createHash("sha256").update(bytes).digest("hex").slice(0, 16);
|
|
2440
|
+
return `wasm_${hash}.wasm`;
|
|
2441
|
+
}
|
|
2442
|
+
function registerManifestBinding(outPath, sourcePath, name) {
|
|
2443
|
+
const key = outPathKey(outPath);
|
|
2444
|
+
const bySource = manifestWasmBindings.get(key) ?? new Map;
|
|
2445
|
+
bySource.set(sourcePath, { name, filePath: `server/edge-chunks/${name}` });
|
|
2446
|
+
manifestWasmBindings.set(key, bySource);
|
|
2447
|
+
}
|
|
2448
|
+
function readMiddlewareWasmBindingsForOutPath(outPath) {
|
|
2449
|
+
const key = outPathKey(outPath);
|
|
2450
|
+
const bindings = manifestWasmBindings.get(key);
|
|
2451
|
+
if (!bindings || bindings.size === 0)
|
|
2452
|
+
return [];
|
|
2453
|
+
return [...bindings.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
2454
|
+
}
|
|
2455
|
+
var WASM_FILTER = /\.wasm(?:[?#].*)?$/;
|
|
2456
|
+
var WASM_INSTANCE_NAMESPACE = "pnext-wasm-instance";
|
|
2457
|
+
var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
2458
|
+
function wasmInstanceModuleSource(bytes) {
|
|
2459
|
+
const names = WebAssembly.Module.exports(new WebAssembly.Module(bytes.buffer)).map((entry) => entry.name).filter((name) => IDENTIFIER.test(name));
|
|
2460
|
+
return [
|
|
2461
|
+
`const bytes = Uint8Array.from(atob(${JSON.stringify(Buffer.from(bytes).toString("base64"))}), c => c.charCodeAt(0));`,
|
|
2462
|
+
"const wasmExports = new WebAssembly.Instance(new WebAssembly.Module(bytes), {}).exports;",
|
|
2463
|
+
...names.map((name) => `export const ${name} = wasmExports[${JSON.stringify(name)}];`),
|
|
2464
|
+
"export default wasmExports;"
|
|
2465
|
+
].join(`
|
|
2466
|
+
`);
|
|
2467
|
+
}
|
|
2468
|
+
function registerWasmModuleRuntime(config) {
|
|
2469
|
+
const root = path3.resolve(config.root);
|
|
2470
|
+
if (wasmRuntimeRoots.has(root))
|
|
2471
|
+
return;
|
|
2472
|
+
wasmRuntimeRoots.add(root);
|
|
2473
|
+
Bun.plugin({
|
|
2474
|
+
name: `pnext-compat-wasm-runtime-${root}`,
|
|
2475
|
+
setup(plugin) {
|
|
2476
|
+
plugin.onLoad({ filter: /\.wasm$/ }, async ({ path: file }) => ({
|
|
2477
|
+
contents: wasmInstanceModuleSource(new Uint8Array(await readFile(file))),
|
|
2478
|
+
loader: "js"
|
|
2479
|
+
}));
|
|
2480
|
+
}
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
var wasmRuntimeRoots = new Set;
|
|
2484
|
+
function wasmModulePlugin(config) {
|
|
2485
|
+
const edgeChunkDir = path3.join(config.outPath, "server", "edge-chunks");
|
|
2486
|
+
return {
|
|
2487
|
+
name: "pnext-compat-wasm-module",
|
|
2488
|
+
setup(build) {
|
|
2489
|
+
build.onResolve({ filter: WASM_MODULE_FILTER }, (args) => {
|
|
2490
|
+
const sourcePath = sourcePathFromSpecifier(args.path, args.resolveDir);
|
|
2491
|
+
if (!sourcePath)
|
|
2492
|
+
return;
|
|
2493
|
+
return { path: sourcePath, namespace: "pnext-wasm-module" };
|
|
2494
|
+
});
|
|
2495
|
+
build.onLoad({ filter: /.*/, namespace: "pnext-wasm-module" }, async (args) => {
|
|
2496
|
+
const sourcePath = path3.resolve(args.path);
|
|
2497
|
+
const bytes = new Uint8Array(await readFile(sourcePath));
|
|
2498
|
+
const name = assetFileName(bytes);
|
|
2499
|
+
const outFile = path3.join(edgeChunkDir, name);
|
|
2500
|
+
if (!existsSync2(outFile)) {
|
|
2501
|
+
await mkdir(path3.dirname(outFile), { recursive: true });
|
|
2502
|
+
await writeFile(outFile, bytes);
|
|
2503
|
+
}
|
|
2504
|
+
registerManifestBinding(config.outPath, sourcePath, name);
|
|
2505
|
+
const moduleBytes = JSON.stringify([...bytes]);
|
|
2506
|
+
return {
|
|
2507
|
+
contents: [
|
|
2508
|
+
`const bytes = new Uint8Array(${moduleBytes});`,
|
|
2509
|
+
"const module = new WebAssembly.Module(bytes.buffer);",
|
|
2510
|
+
"export default module;"
|
|
2511
|
+
].join(`
|
|
2512
|
+
`),
|
|
2513
|
+
loader: "js"
|
|
2514
|
+
};
|
|
2515
|
+
});
|
|
2516
|
+
build.onResolve({ filter: WASM_FILTER }, (args) => {
|
|
2517
|
+
if (WASM_MODULE_FILTER.test(args.path))
|
|
2518
|
+
return;
|
|
2519
|
+
const sourcePath = sourcePathFromSpecifier(args.path, args.resolveDir);
|
|
2520
|
+
return sourcePath ? { path: sourcePath, namespace: WASM_INSTANCE_NAMESPACE } : undefined;
|
|
2521
|
+
});
|
|
2522
|
+
build.onLoad({ filter: /.*/, namespace: WASM_INSTANCE_NAMESPACE }, async (args) => ({
|
|
2523
|
+
contents: wasmInstanceModuleSource(new Uint8Array(await readFile(path3.resolve(args.path)))),
|
|
2524
|
+
loader: "js"
|
|
2525
|
+
}));
|
|
2526
|
+
}
|
|
2527
|
+
};
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
export { getOtelApi, SPAN_TYPE, setOtelAppRoot, startRootSpan, setRootSpanRoute, endRootSpan, endRootSpanIfUnclosed, rootOtelContext, activeOtelContext, withChildSpan, withRenderBodySpan, markRenderSpanError, withRouteHandlerSpan, withPagesApiHandlerSpan, withPagesDataSpan, emitStartResponseSpan, emitClientComponentLoadingSpan, withMiddlewareSpan, emitLeafSpan, carrierSetter, otelExportInProgress, readNextModuleMetadata, readNextModuleViewport, hasRuntimeMetadata, shouldRenderMetadataInBody, warnNextMetadataBuildIssues, PnextBuildValidationError, validateBuild, TREE_SEGMENT_PATH, DEFAULT_DYNAMIC_STALE_TIME_SECONDS, DEFAULT_STATIC_STALE_TIME_SECONDS, buildRootTreePrefetch, rootTreePrefetchText, treePrefetchResponse, ROUTE_SEGMENT_PATH, buildSegmentMeta, segmentBodyResponse, segmentDir, treeSegmentFile, bodySegmentFile, segmentMetaFile, readMiddlewareWasmBindingsForOutPath, registerWasmModuleRuntime, wasmModulePlugin };
|