@wular/pnext 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/_chunks/{aliases-j47a10ce.js → aliases-pycbtjt1.js} +7 -5
- package/dist/server/_chunks/{analyze-arswqe6s.js → analyze-4d9e00g9.js} +17 -13
- package/dist/server/_chunks/{boot-af0mv3dy.js → boot-bhemypxz.js} +13 -11
- package/dist/server/_chunks/{build-spy3dxp4.js → build-c991dv65.js} +7 -5
- package/dist/server/_chunks/{build-t9h0hec3.js → build-kh5e3x48.js} +977 -1186
- package/dist/server/_chunks/{build-tier-m7yvqz61.js → build-tier-0a96kmx3.js} +59 -75
- package/dist/server/_chunks/{compile-53j02j27.js → compile-040r79gj.js} +2 -2
- package/dist/server/_chunks/{config-n2z7yxps.js → config-0tvz03a6.js} +6 -4
- package/dist/server/_chunks/{config-1yzwexq6.js → config-27rj7830.js} +12 -3
- package/dist/server/_chunks/{create-meec9hs6.js → create-9rvwshsp.js} +4 -3
- package/dist/server/_chunks/{dev-fjmqg6en.js → dev-ex9exynt.js} +2 -2
- package/dist/server/_chunks/{generate-n9sh6hzt.js → generate-myw9hef7.js} +5 -4
- package/dist/server/_chunks/{index-91x12ykq.js → index-0r5eqfc7.js} +6 -1
- package/dist/server/_chunks/{index-3xbr4eyv.js → index-0yjv5v47.js} +3 -3
- package/dist/server/_chunks/{index-ncnes8c6.js → index-11xpbfej.js} +2 -2
- package/dist/server/_chunks/{index-357na4a8.js → index-141vcwk6.js} +1 -1
- package/dist/server/_chunks/{index-nyrba2kr.js → index-1pzm1hdy.js} +11 -11
- package/dist/server/_chunks/{index-fkp000p1.js → index-29pq0kax.js} +2 -2
- package/dist/server/_chunks/{index-wpfhfbs4.js → index-38xpdxwd.js} +4 -4
- package/dist/server/_chunks/{index-tvqkq6e6.js → index-3e075kny.js} +1 -1
- package/dist/server/_chunks/{index-kq8kpzye.js → index-3ycf5ckv.js} +3 -3
- package/dist/server/_chunks/{index-20ppawv7.js → index-4da76t62.js} +3 -3
- package/dist/server/_chunks/{index-cf4rvxv6.js → index-52k54ykj.js} +1 -1
- package/dist/server/_chunks/{index-x93hv0sc.js → index-71885zaq.js} +23 -10
- package/dist/server/_chunks/{index-jepjvcrf.js → index-8ct7rqy3.js} +1 -1
- package/dist/server/_chunks/{index-sjpckxqn.js → index-9f49w76j.js} +1 -1
- package/dist/server/_chunks/{index-4hgjrqh7.js → index-9hz3s0m8.js} +2 -2
- package/dist/server/_chunks/{index-9n2914ww.js → index-akkrvjn6.js} +1 -1
- package/dist/server/_chunks/{index-9ych9ma8.js → index-b7j671dj.js} +2 -2
- package/dist/server/_chunks/index-bzd2ef7t.js +10 -0
- package/dist/server/_chunks/{index-p77b4kcx.js → index-cn86z041.js} +1 -1
- package/dist/server/_chunks/{index-hkdfj58q.js → index-cvr4z22m.js} +1 -1
- package/dist/server/_chunks/{index-y2jr2n72.js → index-d158y67j.js} +4 -4
- package/dist/server/_chunks/{index-yz54pxrh.js → index-d1jsmhhk.js} +4 -9
- package/dist/server/_chunks/{index-ggk2j965.js → index-dgr390q7.js} +56 -50
- package/dist/server/_chunks/{index-sctcgyvv.js → index-drwv61cc.js} +2 -2
- package/dist/server/_chunks/{index-9hx2641q.js → index-entm8bmz.js} +1 -1
- package/dist/server/_chunks/{index-jx7bqvw1.js → index-evhd413j.js} +1 -1
- package/dist/server/_chunks/{index-1011cscr.js → index-fjv96re1.js} +61 -29
- package/dist/server/_chunks/{index-c0g2wf3z.js → index-gcmj16xy.js} +1 -1
- package/dist/server/_chunks/{index-ytjvpbm2.js → index-gkndxkxf.js} +3 -3
- package/dist/server/_chunks/index-hdbwtdv2.js +352 -0
- package/dist/server/_chunks/{index-z84ab1w0.js → index-he6n2bvp.js} +3 -3
- package/dist/server/_chunks/{index-eajaspjk.js → index-j0m1jxqa.js} +1 -1
- package/dist/server/_chunks/{index-4q2gbfwk.js → index-j681c48a.js} +2 -2
- package/dist/server/_chunks/index-jbj7ehef.js +50 -0
- package/dist/server/_chunks/{index-8k7pfejn.js → index-jn9rbhrx.js} +7 -7
- package/dist/server/_chunks/index-jt8e1pje.js +12 -0
- package/dist/server/_chunks/{index-eeaanp2e.js → index-kdhxpwyq.js} +3 -3
- package/dist/server/_chunks/{index-6e4fqv30.js → index-m63czgq5.js} +2 -0
- package/dist/server/_chunks/{index-2dv4y4wd.js → index-n629dy38.js} +16 -10
- package/dist/server/_chunks/{index-sv8m6789.js → index-nf3df4jy.js} +5 -5
- package/dist/server/_chunks/{index-06nyqntx.js → index-q3r9z8mq.js} +1 -1
- package/dist/server/_chunks/{index-3b3at80h.js → index-qcrvt6er.js} +6 -3
- package/dist/server/_chunks/{index-egykcqg3.js → index-rgj5mx84.js} +1 -1
- package/dist/server/_chunks/{index-vvmmknm1.js → index-rjegyfx4.js} +19 -15
- package/dist/server/_chunks/{index-ym67zqxp.js → index-tf4j19ge.js} +1 -1
- package/dist/server/_chunks/{index-5gyr4emz.js → index-tq3b39a5.js} +4 -4
- package/dist/server/_chunks/{index-qn4z5s3c.js → index-typcbcsv.js} +3 -3
- package/dist/server/_chunks/{index-11sfk4hb.js → index-vmr35jjw.js} +1 -1
- package/dist/server/_chunks/{index-danncfhy.js → index-wm36rj4v.js} +1 -1
- package/dist/server/_chunks/{index-3tf1xjsp.js → index-x2m17v9c.js} +11 -11
- package/dist/server/_chunks/{index-z4z9zv3b.js → index-x9c55pzy.js} +141 -3
- package/dist/server/_chunks/{index-k1g3epw0.js → index-xh1nbk46.js} +10 -10
- package/dist/server/_chunks/{index-0374j2b9.js → index-y4d02znn.js} +1 -1
- package/dist/server/_chunks/{index-qm6kmhqs.js → index-y7mzvq2q.js} +1 -1
- package/dist/server/_chunks/{index-rn8dyr1f.js → index-yrjkqtfj.js} +8 -48
- package/dist/server/_chunks/{index-tq0pc7eg.js → index-zfrwq472.js} +3 -3
- package/dist/server/_chunks/{loader-7yw0j98z.js → loader-5en7wpt5.js} +12 -10
- package/dist/server/_chunks/{modules-jn8bmbn8.js → modules-t92favpj.js} +14 -12
- package/dist/server/_chunks/{pipeline-yy9jhydf.js → pipeline-4t9q43ht.js} +25 -21
- package/dist/server/_chunks/{production-jar9ztm3.js → production-385bw8df.js} +14 -3
- package/dist/server/_chunks/{proxy-config-j84dgksn.js → proxy-config-60gprphe.js} +7 -5
- package/dist/server/_chunks/{proxy-w1d0wmsn.js → proxy-gfhmktbk.js} +12 -10
- package/dist/server/_chunks/{router-k1reahfn.js → router-xnrva921.js} +10 -7
- package/dist/server/_chunks/{routes-2s277fc6.js → routes-ht868pdc.js} +12 -10
- package/dist/server/_chunks/{run-pvd8bs1t.js → run-d40d63ag.js} +5 -4
- package/dist/server/_chunks/{server-mt4a994c.js → server-2p8fgqq2.js} +38 -34
- package/dist/server/_chunks/{tsconfig-defaults-1nb3308g.js → tsconfig-defaults-bcn34eqb.js} +5 -4
- package/dist/server/_chunks/{typegen-0qr0459b.js → typegen-dvtcjtaw.js} +15 -13
- package/dist/server/cli/index.js +12 -15
- package/dist/server/cli/start.js +35 -14
- package/dist/server/compat/next/cache.js +5 -5
- package/dist/server/compat/next/config-headers.js +8 -6
- package/dist/server/compat/next/config-loader.js +1 -1
- package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +5 -5
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +5 -5
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +5 -5
- package/dist/server/compat/next/dynamic.js +3 -14
- package/dist/server/compat/next/font/cache.js +6 -4
- package/dist/server/compat/next/font/local.js +7 -5
- package/dist/server/compat/next/font/runtime.js +7 -5
- package/dist/server/compat/next/headers.js +4 -4
- package/dist/server/compat/next/image/config.js +2 -2
- package/dist/server/compat/next/image/optimizer.js +3 -3
- package/dist/server/compat/next/image/static-metadata.js +4 -4
- package/dist/server/compat/next/legacy-request-apis.js +3 -3
- package/dist/server/compat/next/link-transform.js +4 -3
- package/dist/server/compat/next/navigation.js +5 -4
- package/dist/server/compat/next/redirects.js +8 -6
- package/dist/server/compat/next/resource-hints.js +2 -2
- package/dist/server/compat/next/rewrites.js +7 -5
- package/dist/server/compat/next/root-params.js +3 -3
- package/dist/server/compat/next/route-state.js +2 -2
- package/dist/server/compat/next/script.js +2 -2
- package/dist/server/compat/next/server.js +5 -5
- package/dist/server/generation.json +1 -1
- package/package.json +1 -1
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/dev.md +1 -1
- package/reference/getting-started.md +1 -1
- package/reference/rendering.md +4 -4
- package/src/api/dynamic.tsx +84 -4
- package/src/cli/adapters/vercel-warm.ts +40 -29
- package/src/cli/adapters/vercel.ts +95 -1262
- package/src/cli/analyze.ts +3 -2
- package/src/cli/build/cache.ts +6 -6
- package/src/cli/build.ts +33 -33
- package/src/cli/index.ts +4 -6
- package/src/cli/serve/pipeline.ts +16 -10
- package/src/cli/serve/standalone-worker.ts +8 -0
- package/src/cli/serve/standalone.ts +703 -0
- package/src/cli/start.ts +29 -8
- package/src/client/build.ts +1 -1
- package/src/client/reference-stub.ts +2 -34
- package/src/compat/actions/extensions.ts +3 -2
- package/src/compat/bundler/require-context.ts +2 -1
- package/src/compat/bundler/webpack-loaders.ts +3 -2
- package/src/compat/bundler/worker.ts +2 -2
- package/src/compat/css/inline-css.ts +1 -1
- package/src/compat/export/build-complete.ts +1 -1
- package/src/compat/export/emit.ts +4 -4
- package/src/compat/export/standalone.ts +30 -65
- package/src/compat/image-optimizer/optimize.ts +1 -1
- package/src/compat/lifecycle/instrumentation-client.ts +4 -3
- package/src/compat/metadata-artifacts.ts +1 -1
- package/src/compat/next/config-loader.ts +3 -0
- package/src/compat/next/dynamic.tsx +10 -23
- package/src/compat/next/font/cache.ts +2 -1
- package/src/compat/next/font/runtime.ts +1 -1
- package/src/compat/register/image.ts +1 -1
- package/src/compat/typecheck/check.ts +6 -4
- package/src/config.ts +28 -5
- package/src/css/assets.ts +1 -1
- package/src/css/build.ts +16 -9
- package/src/dev/client-chunk-store.ts +2 -1
- package/src/dev/restart/client-key.ts +2 -1
- package/src/dev/restart/global-css.ts +2 -1
- package/src/dev/restart/route-bundle-key.ts +2 -1
- package/src/dev/restart/route-facts.ts +2 -1
- package/src/dev/server.ts +8 -7
- package/src/out-paths.ts +10 -0
- package/src/render/renderer.ts +1 -1
- package/src/resolve/dynamic.ts +4 -0
- package/src/resolve/engine.ts +2 -12
- package/src/resolve/scan-facts.ts +185 -1
- package/src/routing/metadata-files.ts +1 -1
- package/src/runtime/loader.ts +5 -3
- package/src/runtime/module-cache.ts +2 -1
- package/src/runtime/modules.ts +50 -16
- package/src/runtime/prebundle.ts +23 -3
- package/src/runtime/production.ts +105 -40
- package/src/runtime/release-graph.ts +21 -13
- package/src/runtime/vendor-build.ts +45 -23
- package/src/types.ts +2 -3
- package/src/utils/directive.ts +40 -0
- package/src/utils/fs.ts +7 -2
- package/src/utils/resource-query.ts +12 -0
- package/dist/server/_chunks/index-tqn2qnnn.js +0 -241
- package/dist/server/_chunks/index-y36a0ybw.js +0 -57
- package/src/cli/serve/entry.ts +0 -52
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
buildClientEntries,
|
|
11
11
|
emitStaticClientChunks,
|
|
12
12
|
startClientSources
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-1pzm1hdy.js";
|
|
14
14
|
import {
|
|
15
15
|
writeTypegen
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-38xpdxwd.js";
|
|
17
17
|
import {
|
|
18
18
|
handleRouteModule,
|
|
19
19
|
staticRouteParams
|
|
@@ -23,23 +23,23 @@ import {
|
|
|
23
23
|
assertNoServerActionsWithoutCompat,
|
|
24
24
|
materializeRouteFacts,
|
|
25
25
|
scanRoutes
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-jn9rbhrx.js";
|
|
27
27
|
import {
|
|
28
|
-
compiledSpecifiersManifestSuffix,
|
|
29
28
|
devServerModuleHref,
|
|
30
29
|
resetModuleGraphFailure,
|
|
31
30
|
setEmitCompiledSpecifiersManifest,
|
|
32
31
|
setReleaseCompile
|
|
33
|
-
} from "./index-
|
|
32
|
+
} from "./index-fjv96re1.js";
|
|
34
33
|
import"./index-n4hxpng2.js";
|
|
35
34
|
import"./index-x3yn4ywm.js";
|
|
36
35
|
import {
|
|
36
|
+
cacheRoot as cacheRoot2,
|
|
37
37
|
compiledSourceGraph,
|
|
38
38
|
flushDevModuleCaches,
|
|
39
39
|
registerServerRuntime
|
|
40
|
-
} from "./index-
|
|
41
|
-
import"./index-
|
|
42
|
-
import"./index-
|
|
40
|
+
} from "./index-rjegyfx4.js";
|
|
41
|
+
import"./index-0r5eqfc7.js";
|
|
42
|
+
import"./index-3e075kny.js";
|
|
43
43
|
import {
|
|
44
44
|
clientEntryName,
|
|
45
45
|
defaultNotFoundDocument,
|
|
@@ -61,21 +61,22 @@ import {
|
|
|
61
61
|
staticParamsFor,
|
|
62
62
|
staticRouteMetadataKey,
|
|
63
63
|
withDynamicMetadataRoutes
|
|
64
|
-
} from "./index-
|
|
64
|
+
} from "./index-x2m17v9c.js";
|
|
65
65
|
import {
|
|
66
66
|
findLayouts
|
|
67
|
-
} from "./index-
|
|
67
|
+
} from "./index-8ct7rqy3.js";
|
|
68
68
|
import {
|
|
69
69
|
findProxyFile,
|
|
70
70
|
proxyExternalLoadTarget,
|
|
71
71
|
proxyRoutePatterns,
|
|
72
72
|
validateProxyFiles
|
|
73
|
-
} from "./index-
|
|
73
|
+
} from "./index-3ycf5ckv.js";
|
|
74
74
|
import {
|
|
75
75
|
serverBundleTargetForRuntime,
|
|
76
76
|
throwIfModuleGraphFailed
|
|
77
|
-
} from "./index-
|
|
78
|
-
import"./index-
|
|
77
|
+
} from "./index-0yjv5v47.js";
|
|
78
|
+
import"./index-yrjkqtfj.js";
|
|
79
|
+
import"./index-jbj7ehef.js";
|
|
79
80
|
import {
|
|
80
81
|
buildGlobalCss,
|
|
81
82
|
buildNotFoundCss,
|
|
@@ -83,21 +84,21 @@ import {
|
|
|
83
84
|
globalCssSources,
|
|
84
85
|
prepareRouteCssChunks,
|
|
85
86
|
warmCssPipeline
|
|
86
|
-
} from "./index-
|
|
87
|
+
} from "./index-n629dy38.js";
|
|
87
88
|
import {
|
|
88
89
|
createVerboseLogger
|
|
89
90
|
} from "./index-73z4esab.js";
|
|
90
91
|
import {
|
|
91
92
|
emittedAssetNames,
|
|
92
93
|
registerCssRuntime
|
|
93
|
-
} from "./index-
|
|
94
|
+
} from "./index-d158y67j.js";
|
|
94
95
|
import {
|
|
95
96
|
nextCompatEnabled
|
|
96
97
|
} from "./index-web361b8.js";
|
|
97
98
|
import"./index-knp0s912.js";
|
|
98
99
|
import {
|
|
99
100
|
frameworkFingerprint
|
|
100
|
-
} from "./index-
|
|
101
|
+
} from "./index-gcmj16xy.js";
|
|
101
102
|
import"./index-ye9hmsvf.js";
|
|
102
103
|
import {
|
|
103
104
|
setRequestRuntime
|
|
@@ -109,10 +110,10 @@ import {
|
|
|
109
110
|
} from "./index-fp8r0sqs.js";
|
|
110
111
|
import"./index-cjgqs13g.js";
|
|
111
112
|
import"./index-yhxkxghe.js";
|
|
112
|
-
import"./index-
|
|
113
|
+
import"./index-29pq0kax.js";
|
|
113
114
|
import {
|
|
114
115
|
interceptionMarkerLevels
|
|
115
|
-
} from "./index-
|
|
116
|
+
} from "./index-cn86z041.js";
|
|
116
117
|
import {
|
|
117
118
|
ensureEmptyDir,
|
|
118
119
|
listFiles,
|
|
@@ -122,7 +123,7 @@ import {
|
|
|
122
123
|
toPosixPath,
|
|
123
124
|
writeFileAtomic,
|
|
124
125
|
writeText
|
|
125
|
-
} from "./index-
|
|
126
|
+
} from "./index-4da76t62.js";
|
|
126
127
|
import {
|
|
127
128
|
cacheRoot,
|
|
128
129
|
namedBunBinary
|
|
@@ -130,24 +131,27 @@ import {
|
|
|
130
131
|
import"./index-vz0km5qk.js";
|
|
131
132
|
import {
|
|
132
133
|
bootstrapCompat
|
|
133
|
-
} from "./index-
|
|
134
|
+
} from "./index-tq3b39a5.js";
|
|
134
135
|
import {
|
|
135
|
-
readPrebundleStamp,
|
|
136
|
-
runtimeEntryDirs,
|
|
137
|
-
runtimeEntryFiles
|
|
138
|
-
} from "./index-y36a0ybw.js";
|
|
139
|
-
import {
|
|
140
|
-
DEFAULT_OUT_DIR,
|
|
141
136
|
devOutSegment,
|
|
137
|
+
frameworkRuntimeSpecifiers,
|
|
142
138
|
loadConfig,
|
|
143
139
|
pathToFileHref
|
|
144
|
-
} from "./index-
|
|
140
|
+
} from "./index-71885zaq.js";
|
|
141
|
+
import {
|
|
142
|
+
outCachePath
|
|
143
|
+
} from "./index-bzd2ef7t.js";
|
|
145
144
|
import"./index-jcsjq3d1.js";
|
|
146
145
|
import {
|
|
146
|
+
PREBUNDLE_STAMP,
|
|
147
147
|
buildIndexFile,
|
|
148
|
+
buildManifestFile,
|
|
149
|
+
prebundledFile,
|
|
148
150
|
readBuildIndex,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
readPrebundleStamp,
|
|
152
|
+
releaseSourceFile,
|
|
153
|
+
standaloneOriginsFile
|
|
154
|
+
} from "./index-hdbwtdv2.js";
|
|
151
155
|
import {
|
|
152
156
|
bold,
|
|
153
157
|
cyan,
|
|
@@ -170,21 +174,22 @@ import {
|
|
|
170
174
|
} from "./index-kresp2n8.js";
|
|
171
175
|
import"./index-e3a6yx84.js";
|
|
172
176
|
import {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
} from "./index-yz54pxrh.js";
|
|
177
|
+
importMetaRefs,
|
|
178
|
+
moduleSpecifierEdges,
|
|
179
|
+
scanFactsStats,
|
|
180
|
+
spliceSource
|
|
181
|
+
} from "./index-x9c55pzy.js";
|
|
182
|
+
import"./index-d1jsmhhk.js";
|
|
180
183
|
import"./index-7wc9n8be.js";
|
|
181
184
|
import"./index-pym1cezq.js";
|
|
185
|
+
import {
|
|
186
|
+
splitResourceQuery
|
|
187
|
+
} from "./index-jt8e1pje.js";
|
|
182
188
|
import {
|
|
183
189
|
buildParallelPhaseError,
|
|
184
190
|
clearBuildParallelPhases,
|
|
185
191
|
getBuildExtensions,
|
|
186
192
|
getCompatModeExtensions,
|
|
187
|
-
getImportAliasExtensions,
|
|
188
193
|
getRenderExtensions,
|
|
189
194
|
runInitHooks,
|
|
190
195
|
withRouteRuntime
|
|
@@ -193,192 +198,19 @@ import {
|
|
|
193
198
|
escapeRegex
|
|
194
199
|
} from "./index-qjj6gddn.js";
|
|
195
200
|
import"./index-4399bvd2.js";
|
|
196
|
-
import
|
|
197
|
-
__require
|
|
198
|
-
} from "./index-rt9qq1va.js";
|
|
201
|
+
import"./index-rt9qq1va.js";
|
|
199
202
|
|
|
200
203
|
// src/cli/build.ts
|
|
201
|
-
import { copyFile as
|
|
202
|
-
import { existsSync as
|
|
204
|
+
import { copyFile as copyFile3, mkdir as mkdir4, rename as rename3, writeFile as writeFile2 } from "fs/promises";
|
|
205
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, readdirSync as readdirSync3, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
|
|
203
206
|
import { createRequire } from "module";
|
|
204
207
|
import path5 from "path";
|
|
205
208
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
206
209
|
|
|
207
210
|
// src/cli/adapters/vercel.ts
|
|
208
|
-
import { copyFile,
|
|
209
|
-
import {
|
|
210
|
-
import { builtinModules } from "module";
|
|
211
|
-
import path2 from "path";
|
|
212
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
213
|
-
|
|
214
|
-
// src/cli/adapters/vercel-warm.ts
|
|
215
|
-
import { fileURLToPath } from "url";
|
|
216
|
-
|
|
217
|
-
// src/runtime/release-graph.ts
|
|
218
|
-
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
211
|
+
import { copyFile, cp, mkdir, readFile, readdir, rename, rm } from "fs/promises";
|
|
212
|
+
import { constants, existsSync, readdirSync } from "fs";
|
|
219
213
|
import path from "path";
|
|
220
|
-
var layerDirs = {
|
|
221
|
-
"server:server": "rsc",
|
|
222
|
-
"client:client": "ssr"
|
|
223
|
-
};
|
|
224
|
-
var layers = Object.keys(layerDirs);
|
|
225
|
-
var frameworkRoot = realpathSync(path.resolve(__PNEXT_PACKAGE_ROOT__ + "/src/runtime", "..", ".."));
|
|
226
|
-
|
|
227
|
-
// src/cli/adapters/vercel-warm.ts
|
|
228
|
-
var DONE_MARKER = "pnext-warm-done:";
|
|
229
|
-
var COMPILED_MARKER = "pnext-warm-compiled";
|
|
230
|
-
var ATTEMPT_TIMEOUT_MS = 10 * 60000;
|
|
231
|
-
var MAX_ATTEMPTS = 3;
|
|
232
|
-
var FULL_MODE_FLAG = "--full";
|
|
233
|
-
function startWarmChild(config, mode = "full") {
|
|
234
|
-
const children = new Set;
|
|
235
|
-
let disposed = false;
|
|
236
|
-
const spawn = () => {
|
|
237
|
-
if (disposed)
|
|
238
|
-
return;
|
|
239
|
-
const child = spawnWarmProcess(config, mode);
|
|
240
|
-
if (!child)
|
|
241
|
-
return;
|
|
242
|
-
children.add(child);
|
|
243
|
-
child.exited.finally(() => children.delete(child));
|
|
244
|
-
forwardWarmStderr(child);
|
|
245
|
-
return child;
|
|
246
|
-
};
|
|
247
|
-
const killOnExit = () => kill();
|
|
248
|
-
const kill = () => {
|
|
249
|
-
if (disposed)
|
|
250
|
-
return;
|
|
251
|
-
disposed = true;
|
|
252
|
-
process.off("exit", killOnExit);
|
|
253
|
-
for (const child of children)
|
|
254
|
-
child.kill();
|
|
255
|
-
children.clear();
|
|
256
|
-
};
|
|
257
|
-
process.once("exit", killOnExit);
|
|
258
|
-
const first = spawn();
|
|
259
|
-
return {
|
|
260
|
-
prewarm(files) {
|
|
261
|
-
if (!first || files.length === 0)
|
|
262
|
-
return;
|
|
263
|
-
try {
|
|
264
|
-
first.stdin.write(`${JSON.stringify({ prewarm: files })}
|
|
265
|
-
`);
|
|
266
|
-
first.stdin.flush();
|
|
267
|
-
} catch {}
|
|
268
|
-
},
|
|
269
|
-
finish: (log, onCompiled, facts = { clientReferences: [] }) => warmWithRestarts(first, spawn, mode, log, facts, onCompiled).finally(kill),
|
|
270
|
-
kill
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
async function forwardWarmStderr(child) {
|
|
274
|
-
try {
|
|
275
|
-
const reader = child.stderr.getReader();
|
|
276
|
-
for (;; ) {
|
|
277
|
-
const { done, value } = await reader.read();
|
|
278
|
-
if (done)
|
|
279
|
-
return;
|
|
280
|
-
process.stderr.write(value);
|
|
281
|
-
}
|
|
282
|
-
} catch {}
|
|
283
|
-
}
|
|
284
|
-
function spawnWarmProcess(config, mode) {
|
|
285
|
-
const entry = fileURLToPath(new URL(Bun.pathToFileURL(__PNEXT_PACKAGE_ROOT__ + "/src/cli/adapters/vercel-warm.ts").href));
|
|
286
|
-
const argv = mode === "full" ? [config.root, FULL_MODE_FLAG] : [config.root];
|
|
287
|
-
try {
|
|
288
|
-
return Bun.spawn([namedBunBinary("pnext-warm"), "--conditions=react-server", entry, ...argv], {
|
|
289
|
-
cwd: config.root,
|
|
290
|
-
stdin: "pipe",
|
|
291
|
-
stdout: "pipe",
|
|
292
|
-
stderr: "pipe",
|
|
293
|
-
env: process.env
|
|
294
|
-
});
|
|
295
|
-
} catch {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
async function warmWithRestarts(first, spawn, mode, log, facts, onCompiled) {
|
|
300
|
-
const finished = new Map;
|
|
301
|
-
const compiled = () => [...finished.values()].filter((file) => Boolean(file));
|
|
302
|
-
let fired = false;
|
|
303
|
-
const fireOnCompiled = onCompiled ? () => {
|
|
304
|
-
if (fired)
|
|
305
|
-
return;
|
|
306
|
-
fired = true;
|
|
307
|
-
onCompiled(compiled());
|
|
308
|
-
} : undefined;
|
|
309
|
-
let child = first;
|
|
310
|
-
for (let attempt = 1;attempt <= MAX_ATTEMPTS && child; attempt++) {
|
|
311
|
-
const before = finished.size;
|
|
312
|
-
const failure = await runAttempt(child, {
|
|
313
|
-
skip: [...finished.keys()],
|
|
314
|
-
compiled: Object.fromEntries([...finished].filter((entry) => Boolean(entry[1]))),
|
|
315
|
-
...facts
|
|
316
|
-
}, finished, fireOnCompiled);
|
|
317
|
-
if (!failure) {
|
|
318
|
-
log.log(`warmed ${compiled().length} modules`);
|
|
319
|
-
return compiled();
|
|
320
|
-
}
|
|
321
|
-
child = finished.size > before && attempt < MAX_ATTEMPTS ? spawn() : undefined;
|
|
322
|
-
if (child)
|
|
323
|
-
log.log(`warm-up ${failure} after ${finished.size} files; restarting past them`);
|
|
324
|
-
else
|
|
325
|
-
warmIncomplete(failure, finished.size, mode);
|
|
326
|
-
}
|
|
327
|
-
fireOnCompiled?.();
|
|
328
|
-
return compiled();
|
|
329
|
-
}
|
|
330
|
-
async function runAttempt(child, request, finished, onCompiled) {
|
|
331
|
-
try {
|
|
332
|
-
child.stdin.write(`${JSON.stringify(request)}
|
|
333
|
-
`);
|
|
334
|
-
child.stdin.end();
|
|
335
|
-
} catch {}
|
|
336
|
-
const timeout = setTimeout(() => child.kill("SIGKILL"), ATTEMPT_TIMEOUT_MS);
|
|
337
|
-
timeout.unref?.();
|
|
338
|
-
const processLine = (line) => {
|
|
339
|
-
if (!line)
|
|
340
|
-
return;
|
|
341
|
-
if (line === COMPILED_MARKER) {
|
|
342
|
-
onCompiled?.();
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
if (!line.startsWith(DONE_MARKER)) {
|
|
346
|
-
console.log(line);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
const [source, artifact] = line.slice(DONE_MARKER.length).split("\t");
|
|
350
|
-
if (source)
|
|
351
|
-
finished.set(source, artifact || undefined);
|
|
352
|
-
};
|
|
353
|
-
const reader = child.stdout.getReader();
|
|
354
|
-
const decoder = new TextDecoder;
|
|
355
|
-
let buffer = "";
|
|
356
|
-
for (;; ) {
|
|
357
|
-
const { done, value } = await reader.read();
|
|
358
|
-
if (done)
|
|
359
|
-
break;
|
|
360
|
-
buffer += decoder.decode(value, { stream: true });
|
|
361
|
-
let newline;
|
|
362
|
-
while ((newline = buffer.indexOf(`
|
|
363
|
-
`)) >= 0) {
|
|
364
|
-
processLine(buffer.slice(0, newline));
|
|
365
|
-
buffer = buffer.slice(newline + 1);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
if (buffer)
|
|
369
|
-
processLine(buffer);
|
|
370
|
-
const code = await child.exited.finally(() => clearTimeout(timeout));
|
|
371
|
-
if (code === 0)
|
|
372
|
-
return;
|
|
373
|
-
return child.signalCode ? `was killed by ${child.signalCode}` : `exited with code ${code}`;
|
|
374
|
-
}
|
|
375
|
-
function warmIncomplete(failure, done, mode) {
|
|
376
|
-
console.warn(`pnext build: module warm-up ${failure} after warming ${done} file(s). ` + (mode === "full" ? "The function ships without the rest of its module cache and may fail to render those " + "routes at request time, where Vercel's filesystem is read-only." : "The production server compiles the rest on the first request that needs them."));
|
|
377
|
-
}
|
|
378
|
-
if (false) {}
|
|
379
|
-
|
|
380
|
-
// src/cli/adapters/vercel.ts
|
|
381
|
-
var RUNTIME_ROOT = "/var/task";
|
|
382
214
|
var SERVER_FUNCTION = "_pnext";
|
|
383
215
|
var FUNCTION_PLATFORM = {
|
|
384
216
|
architecture: "x86_64",
|
|
@@ -386,127 +218,20 @@ var FUNCTION_PLATFORM = {
|
|
|
386
218
|
cpu: "x64",
|
|
387
219
|
libc: "glibc"
|
|
388
220
|
};
|
|
389
|
-
var
|
|
390
|
-
"node_modules",
|
|
391
|
-
".git",
|
|
392
|
-
".next",
|
|
393
|
-
".pnext",
|
|
394
|
-
".turbo",
|
|
395
|
-
".cache",
|
|
396
|
-
".vercel",
|
|
397
|
-
".tmp"
|
|
398
|
-
];
|
|
399
|
-
var droppedFileSuffixes = [
|
|
400
|
-
".map",
|
|
401
|
-
".d.ts",
|
|
402
|
-
".d.mts",
|
|
403
|
-
".d.cts",
|
|
404
|
-
".DS_Store",
|
|
405
|
-
compiledSpecifiersManifestSuffix
|
|
406
|
-
];
|
|
407
|
-
var packPruningEnabled = true;
|
|
408
|
-
function packRules(config) {
|
|
409
|
-
const devPaths = new Set([config.outRootPath, path2.resolve(config.root, DEFAULT_OUT_DIR)].map((root) => path2.resolve(root, devOutSegment)).filter((dev) => !isInsideDir(dev, config.outPath)));
|
|
410
|
-
devPaths.add(path2.join(config.outRootPath, "pnext-pages-compat"));
|
|
411
|
-
if (!packPruningEnabled) {
|
|
412
|
-
return {
|
|
413
|
-
prunedDirs: new Set(["node_modules", ".git"]),
|
|
414
|
-
droppedSuffixes: [],
|
|
415
|
-
compiled: new Set,
|
|
416
|
-
keep: new Set,
|
|
417
|
-
keepPaths: new Set([path2.resolve(config.outPath)]),
|
|
418
|
-
devPaths
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
const keep = new Set(config.adapter?.keep ?? []);
|
|
422
|
-
const extra = config.adapter?.exclude ?? [];
|
|
423
|
-
const isSuffix = (entry) => entry.startsWith(".") && !prunedDirNames.includes(entry);
|
|
424
|
-
return {
|
|
425
|
-
prunedDirs: new Set([...prunedDirNames, ...extra.filter((entry) => !isSuffix(entry))].filter((name) => !keep.has(name))),
|
|
426
|
-
droppedSuffixes: [...droppedFileSuffixes, ...extra.filter(isSuffix)].filter((suffix) => !keep.has(suffix)),
|
|
427
|
-
compiled: new Set,
|
|
428
|
-
keep,
|
|
429
|
-
keepPaths: new Set([path2.resolve(config.outPath), path2.resolve(config.root, DEFAULT_OUT_DIR)]),
|
|
430
|
-
devPaths
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
function withinKeepPath(pack, source) {
|
|
434
|
-
const resolved = path2.resolve(source);
|
|
435
|
-
for (const keep of pack.keepPaths) {
|
|
436
|
-
if (resolved === keep || resolved.startsWith(`${keep}${path2.sep}`))
|
|
437
|
-
return true;
|
|
438
|
-
}
|
|
439
|
-
return false;
|
|
440
|
-
}
|
|
441
|
-
function shipsDir(pack, name, source, isLink = false) {
|
|
442
|
-
if (pack.devPaths.has(path2.resolve(source)))
|
|
443
|
-
return false;
|
|
444
|
-
if (!pack.prunedDirs.has(name))
|
|
445
|
-
return true;
|
|
446
|
-
return !isLink && withinKeepPath(pack, source);
|
|
447
|
-
}
|
|
448
|
-
function shipsFile(pack, name, source) {
|
|
449
|
-
if (pack.droppedSuffixes.some((suffix) => name.endsWith(suffix)))
|
|
450
|
-
return false;
|
|
451
|
-
if (!pack.compiled.has(path2.resolve(source)) || withinKeepPath(pack, source))
|
|
452
|
-
return true;
|
|
453
|
-
return [...pack.keep].some((entry) => name === entry || entry.startsWith(".") && name.endsWith(entry));
|
|
454
|
-
}
|
|
455
|
-
function releaseCompiledSources(config) {
|
|
456
|
-
flushDevModuleCaches();
|
|
457
|
-
const index = readBuildIndex(config.outPath);
|
|
458
|
-
const graph = compiledSourceGraph(config.outPath, config.workspaceRoot);
|
|
459
|
-
const queue = Object.keys(index.modules).map((key) => releaseSourceFile(key.slice(key.indexOf(":", key.indexOf(":") + 1) + 1), config.root, config.workspaceRoot));
|
|
460
|
-
if (index.proxy)
|
|
461
|
-
queue.push(path2.resolve(config.root, index.proxy.file));
|
|
462
|
-
const script = /\.(?:[cm]?[jt]s|[jt]sx)$/;
|
|
463
|
-
const frozen = (dir, pattern) => (readDirEntries(dir) ?? []).filter((entry) => pattern.test(entry.name) && script.test(entry.name)).forEach((entry) => queue.push(path2.join(dir, entry.name)));
|
|
464
|
-
frozen(config.root, /^(?:pnext|next)\.config\./);
|
|
465
|
-
if (index.instrumentation) {
|
|
466
|
-
for (const dir of [config.root, path2.join(config.root, "src")])
|
|
467
|
-
frozen(dir, /^instrumentation\./);
|
|
468
|
-
}
|
|
469
|
-
const compiled = new Set;
|
|
470
|
-
for (const file of queue) {
|
|
471
|
-
if (compiled.has(file))
|
|
472
|
-
continue;
|
|
473
|
-
compiled.add(file);
|
|
474
|
-
let real = file;
|
|
475
|
-
try {
|
|
476
|
-
real = realpathSync2(file);
|
|
477
|
-
} catch {
|
|
478
|
-
continue;
|
|
479
|
-
}
|
|
480
|
-
compiled.add(real);
|
|
481
|
-
queue.push(...graph.get(file) ?? [], ...graph.get(real) ?? []);
|
|
482
|
-
}
|
|
483
|
-
return compiled;
|
|
484
|
-
}
|
|
221
|
+
var functionDroppedPackages = [/^sharp$/, /^@img\/sharp-libvips/];
|
|
485
222
|
async function writeVercelOutput(config, manifest, options = {}) {
|
|
486
223
|
const log = createVerboseLogger(options.verbose ?? false, "vercel");
|
|
487
|
-
const outputPath =
|
|
224
|
+
const outputPath = path.join(config.root, ".vercel", "output");
|
|
225
|
+
const staticPath = path.join(config.outPath, "static");
|
|
488
226
|
const staticFiles = manifest.staticFiles ?? {};
|
|
489
|
-
const warm = options.warm ?? startWarmChild(config);
|
|
490
227
|
await log.step("prepare output directory", () => emptyDir(outputPath));
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
const warmSettled = warm.finish(log, (modules) => resolveWarmedModules(modules), {
|
|
496
|
-
globalCss: globalCssSources(config),
|
|
497
|
-
clientReferences: [...compiledClientReferenceFiles()]
|
|
498
|
-
});
|
|
499
|
-
warmSettled.catch(() => {
|
|
500
|
-
return;
|
|
501
|
-
});
|
|
502
|
-
const warmedModules = await log.step("warm module cache (compiled)", () => warmedModulesEarly);
|
|
503
|
-
const functionPath = path2.join(outputPath, "functions", `${SERVER_FUNCTION}.func`);
|
|
504
|
-
await writeServerFunction(config, manifest, functionPath, warmedModules, warmSettled, log);
|
|
505
|
-
await log.step("copy static files", () => copyStaticFiles(path2.join(config.outPath, "public"), path2.join(outputPath, "static"), (relative) => !staticFiles[relative] || canServeStaticOnVercel(staticFiles[relative])));
|
|
506
|
-
const overrides = await staticOverrides(path2.join(config.outPath, "public"), staticFiles);
|
|
228
|
+
const functionPath = path.join(outputPath, "functions", `${SERVER_FUNCTION}.func`);
|
|
229
|
+
await writeServerFunction(config.outPath, manifest, functionPath, log);
|
|
230
|
+
await log.step("copy static files", () => copyStaticFiles(staticPath, path.join(outputPath, "static"), (relative) => !staticFiles[relative] || canServeStaticOnVercel(staticFiles[relative])));
|
|
231
|
+
const overrides = await staticOverrides(staticPath, staticFiles);
|
|
507
232
|
const routes = [
|
|
508
233
|
...compatStaticRewrite(config, outputPath),
|
|
509
|
-
...await immutableAssetRoutes(
|
|
234
|
+
...await immutableAssetRoutes(staticPath, manifest.publicAssets),
|
|
510
235
|
...await proxyRoutes(config),
|
|
511
236
|
...staticHeaderRoutes(staticFiles),
|
|
512
237
|
{ handle: "filesystem" },
|
|
@@ -517,17 +242,17 @@ async function writeVercelOutput(config, manifest, options = {}) {
|
|
|
517
242
|
routes,
|
|
518
243
|
...Object.keys(overrides).length > 0 ? { overrides } : {}
|
|
519
244
|
};
|
|
520
|
-
await writeText(
|
|
245
|
+
await writeText(path.join(outputPath, "config.json"), `${JSON.stringify(vercelConfig, null, 2)}
|
|
521
246
|
`);
|
|
522
247
|
}
|
|
523
248
|
async function emptyDir(dir) {
|
|
524
|
-
const parent =
|
|
249
|
+
const parent = path.dirname(dir);
|
|
525
250
|
await mkdir(parent, { recursive: true });
|
|
526
|
-
const staleMarker = `${
|
|
527
|
-
if (
|
|
528
|
-
await rename(dir,
|
|
251
|
+
const staleMarker = `${path.basename(dir)}.stale-`;
|
|
252
|
+
if (existsSync(dir)) {
|
|
253
|
+
await rename(dir, path.join(parent, `${staleMarker}${process.pid.toString(36)}-${Date.now().toString(36)}`));
|
|
529
254
|
}
|
|
530
|
-
const stale = readdirSync(parent).filter((entry) => entry.startsWith(staleMarker)).map((entry) =>
|
|
255
|
+
const stale = readdirSync(parent).filter((entry) => entry.startsWith(staleMarker)).map((entry) => path.join(parent, entry));
|
|
531
256
|
await mkdir(dir, { recursive: true });
|
|
532
257
|
if (stale.length > 0) {
|
|
533
258
|
Bun.spawn(["rm", "-rf", ...stale], { stdout: "ignore", stderr: "ignore" });
|
|
@@ -536,15 +261,15 @@ async function emptyDir(dir) {
|
|
|
536
261
|
function compatStaticRewrite(config, outputPath) {
|
|
537
262
|
if (!nextCompatEnabled(config))
|
|
538
263
|
return [];
|
|
539
|
-
const staticDir =
|
|
540
|
-
const names = readdirSyncSafe(
|
|
264
|
+
const staticDir = path.join(outputPath, "static");
|
|
265
|
+
const names = readdirSyncSafe(path.join(staticDir, "assets")).filter((name) => !existsSync(path.join(staticDir, "_next", "static", name)));
|
|
541
266
|
if (names.length === 0)
|
|
542
267
|
return [];
|
|
543
268
|
const alternation = names.map((name) => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
544
269
|
return [{ src: `^/_next/static/(${alternation})(/.*)?$`, dest: "/assets/$1$2", continue: true }];
|
|
545
270
|
}
|
|
546
271
|
function readdirSyncSafe(dir) {
|
|
547
|
-
return
|
|
272
|
+
return existsSync(dir) ? readdirSync(dir) : [];
|
|
548
273
|
}
|
|
549
274
|
async function proxyRoutes(config) {
|
|
550
275
|
const proxyFile = findProxyFile(config);
|
|
@@ -556,672 +281,120 @@ async function proxyRoutes(config) {
|
|
|
556
281
|
dest: `/${SERVER_FUNCTION}`
|
|
557
282
|
}));
|
|
558
283
|
}
|
|
559
|
-
async function writeServerFunction(
|
|
560
|
-
|
|
561
|
-
await
|
|
562
|
-
const
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
const closure = await traceNodeModulesClosure(config, manifest, functionPath, framework, [...warmedModules, ...release ?? []], pack, log, Boolean(release));
|
|
568
|
-
const replicaPathFor = (file) => {
|
|
569
|
-
if (isInsideDir(pnextRoot, file)) {
|
|
570
|
-
return path2.join(functionPath, pnextTargetRel, path2.relative(pnextRoot, file));
|
|
571
|
-
}
|
|
572
|
-
if (isInsideDir(workspaceRoot, file)) {
|
|
573
|
-
return path2.join(functionPath, path2.relative(workspaceRoot, file));
|
|
574
|
-
}
|
|
575
|
-
return;
|
|
576
|
-
};
|
|
577
|
-
const appRel = path2.relative(workspaceRoot, config.root);
|
|
578
|
-
const packageRoots = workspacePackageRoots(workspaceRoot).map((root) => path2.resolve(root));
|
|
579
|
-
const neededRoots = new Set;
|
|
580
|
-
for (const file of closure.tracedFiles) {
|
|
581
|
-
const root = packageRoots.find((candidate) => isInsideDir(candidate, file));
|
|
582
|
-
if (root)
|
|
583
|
-
neededRoots.add(root);
|
|
584
|
-
}
|
|
585
|
-
for (const relative of closure.workspacePackages) {
|
|
586
|
-
neededRoots.add(path2.resolve(workspaceRoot, relative));
|
|
587
|
-
}
|
|
588
|
-
if (!release) {
|
|
589
|
-
for (const file of globalCssSources(config)) {
|
|
590
|
-
const root = packageRoots.find((candidate) => isInsideDir(candidate, file));
|
|
591
|
-
if (root)
|
|
592
|
-
neededRoots.add(root);
|
|
593
|
-
}
|
|
594
|
-
addWorkspaceDependencies(neededRoots, packageRoots, [path2.resolve(config.root), ...neededRoots]);
|
|
595
|
-
}
|
|
596
|
-
neededRoots.delete(path2.resolve(config.root));
|
|
597
|
-
neededRoots.delete(pnextRoot);
|
|
598
|
-
await log.step("await handler warm-up", () => warmSettled);
|
|
599
|
-
const roots = neededRoots.size + 2;
|
|
600
|
-
await log.step(`copy function tree (${closure.packageCount} packages, ${roots} roots)`, () => Promise.all([
|
|
601
|
-
closure.copy(),
|
|
602
|
-
copyTree(config.root, path2.join(functionPath, appRel), release ? { ...pack, compiled: releaseCompiledSources(config) } : pack, ["public", ".vercel", ".next", ".turbo"]),
|
|
603
|
-
copyPackageTree(pnextRoot, path2.join(functionPath, pnextTargetRel), pack, prebundle && ["config", "dist", ...prebundle.source]),
|
|
604
|
-
...[...neededRoots].map((packageRoot) => copyPackageTree(packageRoot, path2.join(functionPath, path2.relative(workspaceRoot, packageRoot)), pack)),
|
|
605
|
-
...["package.json", "tsconfig.json", "bunfig.toml"].map((name) => path2.join(workspaceRoot, name)).filter((file) => existsSync2(file)).map((file) => copyFile(file, path2.join(functionPath, path2.basename(file))))
|
|
606
|
-
]));
|
|
607
|
-
await log.step("rewrite baked paths", () => rewriteBakedPaths(path2.join(functionPath, appRel, path2.relative(config.root, config.outPath)), [
|
|
608
|
-
...pnextInWorkspace ? [] : [[pnextRoot, toPosixPath(path2.join(RUNTIME_ROOT, pnextTargetRel))]],
|
|
609
|
-
[workspaceRoot, RUNTIME_ROOT]
|
|
610
|
-
]));
|
|
611
|
-
await log.step("inject compat tsconfig paths", () => injectCompatPaths(config, functionPath, pnextRoot, replicaPathFor));
|
|
612
|
-
const startEntry = toPosixPath(path2.join(pnextTargetRel, prebundle ? "dist/server/cli/start.js" : "src/cli/start.ts"));
|
|
613
|
-
await writeText(path2.join(functionPath, "index.mjs"), `import path from 'node:path';
|
|
614
|
-
import { createRequestHandler } from ${JSON.stringify(`./${startEntry}`)};
|
|
284
|
+
async function writeServerFunction(standalonePath, manifest, functionPath, log) {
|
|
285
|
+
await mkdir(path.dirname(functionPath), { recursive: true });
|
|
286
|
+
await log.step("copy standalone", () => cp(standalonePath, functionPath, { recursive: true, verbatimSymlinks: true }));
|
|
287
|
+
const modules = path.join(functionPath, "node_modules");
|
|
288
|
+
const packages = await packageDirs(modules);
|
|
289
|
+
await Promise.all([...packages].filter(([name]) => functionDroppedPackages.some((pattern) => pattern.test(name))).map(([, dirs]) => Promise.all(dirs.map((dir) => rm(dir, { recursive: true, force: true })))));
|
|
290
|
+
await log.step("platform natives", () => replaceHostNatives(packages, log));
|
|
291
|
+
await writeText(path.join(functionPath, "index.mjs"), `import { createRequestHandler } from './server/entry.js';
|
|
615
292
|
|
|
616
|
-
const handlerPromise = createRequestHandler({
|
|
617
|
-
root: path.join(import.meta.dirname, ${JSON.stringify(appRel)}),
|
|
618
|
-
});
|
|
293
|
+
const handlerPromise = createRequestHandler({ root: import.meta.dirname });
|
|
619
294
|
|
|
620
295
|
async function handler(request) {
|
|
621
|
-
return (await handlerPromise)(request);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// Callable for the Node-style launcher, \`fetch\` for the Bun runtime.
|
|
625
|
-
export default Object.assign(handler, { fetch: handler });
|
|
626
|
-
`);
|
|
627
|
-
const maxDuration = manifest.routes.reduce((max, route) => route.maxDuration ? Math.max(max ?? 0, route.maxDuration) : max, undefined);
|
|
628
|
-
await writeText(path2.join(functionPath, ".vc-config.json"), `${JSON.stringify({
|
|
629
|
-
runtime: "bun1.4.x",
|
|
630
|
-
handler: "index.mjs",
|
|
631
|
-
launcherType: "Nodejs",
|
|
632
|
-
architecture: FUNCTION_PLATFORM.architecture,
|
|
633
|
-
useWebApi: true,
|
|
634
|
-
supportsResponseStreaming: true,
|
|
635
|
-
...maxDuration ? { maxDuration } : {}
|
|
636
|
-
}, null, 2)}
|
|
637
|
-
`);
|
|
638
|
-
}
|
|
639
|
-
function addWorkspaceDependencies(roots, packageRoots, from) {
|
|
640
|
-
const byName = new Map;
|
|
641
|
-
for (const root of packageRoots) {
|
|
642
|
-
const name = packageManifest(root)?.name;
|
|
643
|
-
if (name && !byName.has(name))
|
|
644
|
-
byName.set(name, root);
|
|
645
|
-
}
|
|
646
|
-
const queue = [...from];
|
|
647
|
-
const seen = new Set(queue);
|
|
648
|
-
while (queue.length > 0) {
|
|
649
|
-
const manifest = packageManifest(queue.pop());
|
|
650
|
-
if (!manifest)
|
|
651
|
-
continue;
|
|
652
|
-
for (const field of ["dependencies", "optionalDependencies"]) {
|
|
653
|
-
for (const name of Object.keys(manifest[field] ?? {})) {
|
|
654
|
-
const root = byName.get(name);
|
|
655
|
-
if (!root || seen.has(root))
|
|
656
|
-
continue;
|
|
657
|
-
seen.add(root);
|
|
658
|
-
roots.add(root);
|
|
659
|
-
queue.push(root);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
var manifests = new Map;
|
|
665
|
-
function packageManifest(root) {
|
|
666
|
-
const cached = manifests.get(root);
|
|
667
|
-
if (cached !== undefined || manifests.has(root))
|
|
668
|
-
return cached;
|
|
669
|
-
let parsed;
|
|
670
|
-
try {
|
|
671
|
-
parsed = JSON.parse(readFileSync2(path2.join(root, "package.json"), "utf8"));
|
|
672
|
-
} catch {
|
|
673
|
-
parsed = undefined;
|
|
674
|
-
}
|
|
675
|
-
manifests.set(root, parsed);
|
|
676
|
-
return parsed;
|
|
677
|
-
}
|
|
678
|
-
async function copyTree(from, to, pack, excludeNames = [], visited = new Set([realDir(from) ?? path2.resolve(from)])) {
|
|
679
|
-
const exclude = new Set(excludeNames);
|
|
680
|
-
const clone = directoryCloneEnabled ? await directoryCloner() : null;
|
|
681
|
-
if (exclude.size === 0 && !existsSync2(to)) {
|
|
682
|
-
await mkdir(path2.dirname(to), { recursive: true });
|
|
683
|
-
if (clone?.(from, to))
|
|
684
|
-
return normalizeClone(to, from, pack, visited);
|
|
685
|
-
}
|
|
686
|
-
const entries = readDirEntries(from);
|
|
687
|
-
if (!entries)
|
|
688
|
-
return;
|
|
689
|
-
await mkdir(to, { recursive: true });
|
|
690
|
-
await Promise.all(entries.map(async (entry) => {
|
|
691
|
-
const source = path2.join(from, entry.name);
|
|
692
|
-
const target = path2.join(to, entry.name);
|
|
693
|
-
if (exclude.has(entry.name) || !shipsDir(pack, entry.name, source, entry.isSymbolicLink()))
|
|
694
|
-
return;
|
|
695
|
-
if (entry.isSymbolicLink()) {
|
|
696
|
-
const link2 = resolveLinkTarget(source);
|
|
697
|
-
if (!link2)
|
|
698
|
-
return;
|
|
699
|
-
if (link2.isDirectory) {
|
|
700
|
-
if (visited.has(link2.path))
|
|
701
|
-
return;
|
|
702
|
-
visited.add(link2.path);
|
|
703
|
-
return copyTree(link2.path, target, pack, [], visited);
|
|
704
|
-
}
|
|
705
|
-
return shipsFile(pack, entry.name, source) ? linkOrCopyFile(link2.path, target) : undefined;
|
|
706
|
-
}
|
|
707
|
-
if (entry.isDirectory() && clone?.(source, target)) {
|
|
708
|
-
return normalizeClone(target, source, pack, visited);
|
|
709
|
-
}
|
|
710
|
-
if (entry.isDirectory())
|
|
711
|
-
return copyTree(source, target, pack, [], visited);
|
|
712
|
-
if (entry.isFile() && shipsFile(pack, entry.name, source))
|
|
713
|
-
return linkOrCopyFile(source, target);
|
|
714
|
-
}));
|
|
715
|
-
}
|
|
716
|
-
function readDirEntries(dir) {
|
|
717
|
-
try {
|
|
718
|
-
return readdirSync(dir, { withFileTypes: true });
|
|
719
|
-
} catch (error) {
|
|
720
|
-
if (error.code === "ENOENT")
|
|
721
|
-
return;
|
|
722
|
-
throw error;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
var directoryCloneEnabled = true;
|
|
726
|
-
var cloner;
|
|
727
|
-
async function directoryCloner() {
|
|
728
|
-
if (cloner !== undefined)
|
|
729
|
-
return cloner;
|
|
730
|
-
cloner = null;
|
|
731
|
-
if (process.platform === "darwin") {
|
|
732
|
-
try {
|
|
733
|
-
const { dlopen } = await import("bun:ffi");
|
|
734
|
-
const { symbols } = dlopen("libSystem.B.dylib", {
|
|
735
|
-
clonefile: { args: ["cstring", "cstring", "i32"], returns: "i32" }
|
|
736
|
-
});
|
|
737
|
-
cloner = (from, to) => symbols.clonefile(Buffer.from(`${from}\x00`), Buffer.from(`${to}\x00`), 0) === 0;
|
|
738
|
-
} catch {}
|
|
739
|
-
}
|
|
740
|
-
return cloner;
|
|
741
|
-
}
|
|
742
|
-
async function normalizeClone(dir, from, pack, visited) {
|
|
743
|
-
const stack = [[dir, from]];
|
|
744
|
-
const pending = [];
|
|
745
|
-
while (stack.length > 0) {
|
|
746
|
-
const [current, currentFrom] = stack.pop();
|
|
747
|
-
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
748
|
-
const full = path2.join(current, entry.name);
|
|
749
|
-
const source = path2.join(currentFrom, entry.name);
|
|
750
|
-
if (!shipsDir(pack, entry.name, source, entry.isSymbolicLink())) {
|
|
751
|
-
rmSync(full, { recursive: true, force: true });
|
|
752
|
-
} else if (entry.isSymbolicLink()) {
|
|
753
|
-
const link2 = resolveLinkTarget(source);
|
|
754
|
-
rmSync(full, { force: true });
|
|
755
|
-
if (!link2)
|
|
756
|
-
continue;
|
|
757
|
-
if (link2.isDirectory) {
|
|
758
|
-
if (visited.has(link2.path))
|
|
759
|
-
continue;
|
|
760
|
-
visited.add(link2.path);
|
|
761
|
-
pending.push(copyTree(link2.path, full, pack, [], visited));
|
|
762
|
-
} else if (shipsFile(pack, entry.name, source)) {
|
|
763
|
-
pending.push(linkOrCopyFile(link2.path, full));
|
|
764
|
-
}
|
|
765
|
-
} else if (entry.isDirectory()) {
|
|
766
|
-
stack.push([full, source]);
|
|
767
|
-
} else if (!shipsFile(pack, entry.name, source)) {
|
|
768
|
-
rmSync(full, { force: true });
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
await Promise.all(pending);
|
|
773
|
-
}
|
|
774
|
-
async function resolveFrameworkPackage(workspaceRoot) {
|
|
775
|
-
const root = path2.resolve(__PNEXT_PACKAGE_ROOT__ + "/src/cli/adapters", "../../..");
|
|
776
|
-
const packageJson = await readPackageJson(root);
|
|
777
|
-
const packageName = packageJson?.name ?? "pnext";
|
|
778
|
-
const inWorkspace = isInsideDir(workspaceRoot, root) && !root.includes("node_modules");
|
|
779
|
-
return {
|
|
780
|
-
root,
|
|
781
|
-
packageName,
|
|
782
|
-
dependencies: Object.keys(packageJson?.dependencies ?? {}),
|
|
783
|
-
optionalDependencies: Object.keys(packageJson?.optionalDependencies ?? {}),
|
|
784
|
-
inWorkspace,
|
|
785
|
-
targetRel: inWorkspace ? path2.relative(workspaceRoot, root) : path2.join("node_modules", packageName)
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
var packageCopyExcludes = [
|
|
789
|
-
"node_modules",
|
|
790
|
-
".cache",
|
|
791
|
-
".vercel",
|
|
792
|
-
".next",
|
|
793
|
-
".pnext",
|
|
794
|
-
".turbo",
|
|
795
|
-
"test",
|
|
796
|
-
"tests",
|
|
797
|
-
"__tests__"
|
|
798
|
-
];
|
|
799
|
-
async function copyPackageTree(from, to, pack, only) {
|
|
800
|
-
const files = only ?? (await readPackageJson(from))?.files;
|
|
801
|
-
if (!files?.length || files.some((entry) => /[*?[\]{}!]/.test(entry))) {
|
|
802
|
-
return copyTree(from, to, pack, packageCopyExcludes);
|
|
803
|
-
}
|
|
804
|
-
await mkdir(to, { recursive: true });
|
|
805
|
-
await Promise.all([...files, "package.json", "tsconfig.json"].map(async (name) => {
|
|
806
|
-
const source = path2.join(from, name);
|
|
807
|
-
const stats = statSync(source, { throwIfNoEntry: false });
|
|
808
|
-
if (!stats)
|
|
809
|
-
return;
|
|
810
|
-
if (stats.isDirectory())
|
|
811
|
-
return copyTree(source, path2.join(to, name), pack);
|
|
812
|
-
if (!shipsFile(pack, name, source))
|
|
813
|
-
return;
|
|
814
|
-
await mkdir(path2.dirname(path2.join(to, name)), { recursive: true });
|
|
815
|
-
return linkOrCopyFile(source, path2.join(to, name));
|
|
816
|
-
}));
|
|
817
|
-
}
|
|
818
|
-
async function readPackageJson(dir) {
|
|
819
|
-
const file = path2.join(dir, "package.json");
|
|
820
|
-
if (!existsSync2(file))
|
|
821
|
-
return;
|
|
822
|
-
return JSON.parse(await readFile(file, "utf8"));
|
|
823
|
-
}
|
|
824
|
-
var dependencyClosureEnabled = true;
|
|
825
|
-
function skipDependencyClosure() {
|
|
826
|
-
return !dependencyClosureEnabled;
|
|
827
|
-
}
|
|
828
|
-
async function linkOrCopyFile(from, to) {
|
|
829
|
-
try {
|
|
830
|
-
await link(from, to);
|
|
831
|
-
} catch {
|
|
832
|
-
await copyFile(from, to).catch((error) => {
|
|
833
|
-
if (error.code !== "ENOENT")
|
|
834
|
-
throw error;
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
function resolveLinkTarget(link2) {
|
|
839
|
-
const resolved = realDir(link2) ?? realFile(link2);
|
|
840
|
-
if (!resolved)
|
|
841
|
-
return;
|
|
842
|
-
try {
|
|
843
|
-
return { path: resolved, isDirectory: statSync(resolved).isDirectory() };
|
|
844
|
-
} catch {
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
function realFile(file) {
|
|
849
|
-
try {
|
|
850
|
-
return realpathSync2(file);
|
|
851
|
-
} catch {
|
|
852
|
-
return;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
function isInsideDir(root, file) {
|
|
856
|
-
const relative = path2.relative(root, file);
|
|
857
|
-
return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
|
|
858
|
-
}
|
|
859
|
-
function isFrameworkOwnedAliasTarget(frameworkRoot2, target) {
|
|
860
|
-
if (!path2.isAbsolute(target) || !isInsideDir(frameworkRoot2, target))
|
|
861
|
-
return false;
|
|
862
|
-
return !path2.relative(frameworkRoot2, target).split(path2.sep).includes("node_modules");
|
|
863
|
-
}
|
|
864
|
-
function frameworkOwnedAliases(config, frameworkRoot2) {
|
|
865
|
-
return Object.entries(getImportAliasExtensions().aliases(config, "server")).filter(([, target]) => isFrameworkOwnedAliasTarget(frameworkRoot2, target));
|
|
296
|
+
return (await handlerPromise)(request);
|
|
866
297
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
const compilerOptions = parsed.compilerOptions ??= {};
|
|
882
|
-
const paths = compilerOptions.paths ??= {};
|
|
883
|
-
for (const [specifier, target] of aliasTargets) {
|
|
884
|
-
if (paths[specifier])
|
|
885
|
-
continue;
|
|
886
|
-
const relative = toPosixPath(path2.relative(dir, target));
|
|
887
|
-
paths[specifier] = [relative.startsWith(".") ? relative : `./${relative}`];
|
|
888
|
-
}
|
|
889
|
-
compilerOptions.baseUrl ??= ".";
|
|
890
|
-
await rm(file);
|
|
891
|
-
await writeFile(file, `${JSON.stringify(parsed, null, 2)}
|
|
298
|
+
|
|
299
|
+
// Callable for the Node-style launcher, \`fetch\` for the Bun runtime.
|
|
300
|
+
export default Object.assign(handler, { fetch: handler });
|
|
301
|
+
`);
|
|
302
|
+
const maxDuration = manifest.routes.reduce((max, route) => route.maxDuration ? Math.max(max ?? 0, route.maxDuration) : max, undefined);
|
|
303
|
+
await writeText(path.join(functionPath, ".vc-config.json"), `${JSON.stringify({
|
|
304
|
+
runtime: "bun1.4.x",
|
|
305
|
+
handler: "index.mjs",
|
|
306
|
+
launcherType: "Nodejs",
|
|
307
|
+
architecture: FUNCTION_PLATFORM.architecture,
|
|
308
|
+
useWebApi: true,
|
|
309
|
+
supportsResponseStreaming: true,
|
|
310
|
+
...maxDuration ? { maxDuration } : {}
|
|
311
|
+
}, null, 2)}
|
|
892
312
|
`);
|
|
893
|
-
}
|
|
894
313
|
}
|
|
895
|
-
function
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
314
|
+
async function packageDirs(modules) {
|
|
315
|
+
const found = new Map;
|
|
316
|
+
const visit = async (dir, depth) => {
|
|
317
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
318
|
+
for (const entry of entries) {
|
|
319
|
+
if (!entry.isDirectory())
|
|
320
|
+
continue;
|
|
321
|
+
const full = path.join(dir, entry.name);
|
|
322
|
+
if (entry.name === ".bun" || entry.name === ".pnpm") {
|
|
323
|
+
for (const store of await readdir(full, { withFileTypes: true }).catch(() => []))
|
|
324
|
+
if (store.isDirectory())
|
|
325
|
+
await visit(path.join(full, store.name, "node_modules"), 0);
|
|
326
|
+
} else if (entry.name.startsWith("@") && depth === 0) {
|
|
327
|
+
await visit(full, 1);
|
|
328
|
+
} else if (existsSync(path.join(full, "package.json"))) {
|
|
329
|
+
const name = depth === 1 ? `${path.basename(dir)}/${entry.name}` : entry.name;
|
|
330
|
+
found.set(name, [...found.get(name) ?? [], full]);
|
|
331
|
+
await visit(path.join(full, "node_modules"), 0);
|
|
906
332
|
}
|
|
907
|
-
continue;
|
|
908
333
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
continue;
|
|
913
|
-
}
|
|
914
|
-
if (char === "/" && source[index + 1] === "/") {
|
|
915
|
-
while (index < source.length && source[index] !== `
|
|
916
|
-
`)
|
|
917
|
-
index++;
|
|
918
|
-
result += `
|
|
919
|
-
`;
|
|
920
|
-
continue;
|
|
921
|
-
}
|
|
922
|
-
if (char === "/" && source[index + 1] === "*") {
|
|
923
|
-
index += 2;
|
|
924
|
-
while (index < source.length && !(source[index] === "*" && source[index + 1] === "/"))
|
|
925
|
-
index++;
|
|
926
|
-
index++;
|
|
927
|
-
continue;
|
|
928
|
-
}
|
|
929
|
-
result += char;
|
|
930
|
-
}
|
|
931
|
-
return result;
|
|
334
|
+
};
|
|
335
|
+
await visit(modules, 0);
|
|
336
|
+
return found;
|
|
932
337
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
338
|
+
async function readPackageJson(dir) {
|
|
339
|
+
try {
|
|
340
|
+
return JSON.parse(await readFile(path.join(dir, "package.json"), "utf8"));
|
|
341
|
+
} catch {
|
|
937
342
|
return;
|
|
938
|
-
const files = (await listFiles(dir)).filter((file) => bakedPathFileFilter.test(file));
|
|
939
|
-
for (let i = 0;i < files.length; i += BAKED_PATH_CONCURRENCY) {
|
|
940
|
-
await Promise.all(files.slice(i, i + BAKED_PATH_CONCURRENCY).map(async (file) => {
|
|
941
|
-
const source = await readFile(file, "utf8");
|
|
942
|
-
let rewritten = source;
|
|
943
|
-
for (const [from, to] of replacements) {
|
|
944
|
-
if (rewritten.includes(from))
|
|
945
|
-
rewritten = rewritten.replaceAll(from, to);
|
|
946
|
-
}
|
|
947
|
-
if (rewritten === source)
|
|
948
|
-
return;
|
|
949
|
-
await rm(file);
|
|
950
|
-
await writeFile(file, rewritten);
|
|
951
|
-
}));
|
|
952
343
|
}
|
|
953
344
|
}
|
|
954
|
-
async function
|
|
955
|
-
const
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
return parsed;
|
|
961
|
-
}
|
|
962
|
-
} catch {}
|
|
345
|
+
async function replaceHostNatives(packages, log) {
|
|
346
|
+
const manifests = new Map;
|
|
347
|
+
for (const [name, dirs] of packages) {
|
|
348
|
+
const json = await readPackageJson(dirs[0]);
|
|
349
|
+
if (json)
|
|
350
|
+
manifests.set(name, json);
|
|
963
351
|
}
|
|
964
|
-
const source = await readFile(file, "utf8").catch(() => null);
|
|
965
|
-
return source === null ? null : importSpecifiers(source, file);
|
|
966
|
-
}
|
|
967
|
-
async function traceNodeModulesClosure(config, manifest, functionPath, framework, warmedModules, pack, log, release = false) {
|
|
968
|
-
const workspaceRoot = config.workspaceRoot;
|
|
969
|
-
const specifiers = new Set;
|
|
970
|
-
const tracedFiles = new Set;
|
|
971
|
-
const hrefPackageDirs = new Set;
|
|
972
|
-
const frameworkAliasedSpecifiers = new Set(frameworkOwnedAliases(config, path2.resolve(framework.root)).map(([specifier]) => specifier));
|
|
973
|
-
await log.step("trace runtime imports", async () => {
|
|
974
|
-
const queue2 = [];
|
|
975
|
-
const seen2 = tracedFiles;
|
|
976
|
-
const enqueue = (file) => {
|
|
977
|
-
if (!file)
|
|
978
|
-
return;
|
|
979
|
-
const resolved = path2.resolve(file);
|
|
980
|
-
if (seen2.has(resolved) || !existsSync2(resolved))
|
|
981
|
-
return;
|
|
982
|
-
seen2.add(resolved);
|
|
983
|
-
queue2.push(resolved);
|
|
984
|
-
};
|
|
985
|
-
if (!release) {
|
|
986
|
-
for (const route of manifest.routes) {
|
|
987
|
-
if (route.kind === "handler")
|
|
988
|
-
enqueue(route.file);
|
|
989
|
-
}
|
|
990
|
-
enqueue(findProxyFile(config) ?? undefined);
|
|
991
|
-
enqueue(path2.join(config.root, "pnext.config.ts"));
|
|
992
|
-
enqueue(path2.join(config.root, "next.config.js"));
|
|
993
|
-
}
|
|
994
|
-
for (const file of warmedModules)
|
|
995
|
-
enqueue(file);
|
|
996
|
-
const visit = async (file) => {
|
|
997
|
-
if (!scriptFilePattern.test(file))
|
|
998
|
-
return;
|
|
999
|
-
const found = await artifactSpecifiers(file);
|
|
1000
|
-
if (found === null)
|
|
1001
|
-
return;
|
|
1002
|
-
for (const specifier of found) {
|
|
1003
|
-
if (frameworkAliasedSpecifiers.has(specifier))
|
|
1004
|
-
continue;
|
|
1005
|
-
const absolute = absolutePathFromSpecifier(specifier);
|
|
1006
|
-
if (absolute && isInsideDir(framework.root, absolute))
|
|
1007
|
-
continue;
|
|
1008
|
-
if (absolute) {
|
|
1009
|
-
const name2 = packageNameFromPath(absolute);
|
|
1010
|
-
if (name2) {
|
|
1011
|
-
specifiers.add(name2);
|
|
1012
|
-
hrefPackageDirs.add(packageDirFromPath(absolute, name2));
|
|
1013
|
-
} else if (isInsideDir(config.outPath, absolute))
|
|
1014
|
-
enqueue(absolute);
|
|
1015
|
-
continue;
|
|
1016
|
-
}
|
|
1017
|
-
if (/^(?:node:|bun$|bun:|data:)/.test(specifier))
|
|
1018
|
-
continue;
|
|
1019
|
-
const resolved = resolveImport(config.root, file, specifier, config.workspaceRoot);
|
|
1020
|
-
if (resolved && isInsideDir(workspaceRoot, resolved) && !resolved.includes("node_modules")) {
|
|
1021
|
-
enqueue(resolved);
|
|
1022
|
-
}
|
|
1023
|
-
const installed = specifier.startsWith(".") && resolved && packageNameFromPath(resolved);
|
|
1024
|
-
if (installed) {
|
|
1025
|
-
specifiers.add(installed);
|
|
1026
|
-
hrefPackageDirs.add(packageDirFromPath(resolved, installed));
|
|
1027
|
-
}
|
|
1028
|
-
const name = packageNameFromSpecifier(specifier);
|
|
1029
|
-
if (name)
|
|
1030
|
-
specifiers.add(name);
|
|
1031
|
-
}
|
|
1032
|
-
};
|
|
1033
|
-
const READ_BATCH = 64;
|
|
1034
|
-
for (let frontier = queue2.splice(0);frontier.length > 0; frontier = queue2.splice(0)) {
|
|
1035
|
-
for (let index = 0;index < frontier.length; index += READ_BATCH) {
|
|
1036
|
-
await Promise.all(frontier.slice(index, index + READ_BATCH).map(visit));
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
log.log(`traced ${seen2.size} runtime modules`);
|
|
1040
|
-
});
|
|
1041
|
-
const packageDirs = new Map;
|
|
1042
|
-
const nestedCopies = new Map;
|
|
1043
|
-
const workspaceLinks = new Map;
|
|
1044
352
|
const hostNatives = new Map;
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
const queue = [
|
|
1048
|
-
...framework.dependencies.filter((name) => !runtimeDependencies || runtimeDependencies.has(name)).map((name) => ({ name, from: framework.root })),
|
|
1049
|
-
...framework.optionalDependencies.filter((name) => appDependencies.has(name)).map((name) => ({ name, from: framework.root })),
|
|
1050
|
-
...[...specifiers].map((name) => ({ name, from: workspaceRoot }))
|
|
1051
|
-
];
|
|
1052
|
-
const seen = new Set;
|
|
1053
|
-
while (queue.length > 0) {
|
|
1054
|
-
const { name, from, owner } = queue.shift();
|
|
1055
|
-
if (seen.has(name))
|
|
1056
|
-
continue;
|
|
1057
|
-
seen.add(name);
|
|
1058
|
-
if (name === framework.packageName) {
|
|
1059
|
-
if (framework.inWorkspace)
|
|
1060
|
-
workspaceLinks.set(name, framework.targetRel);
|
|
1061
|
-
continue;
|
|
1062
|
-
}
|
|
1063
|
-
const dir = resolvePackageDir(name, [from, workspaceRoot, config.root]);
|
|
1064
|
-
if (!dir)
|
|
1065
|
-
continue;
|
|
1066
|
-
const workspaceRelative = path2.relative(workspaceRoot, dir);
|
|
1067
|
-
if (!workspaceRelative.startsWith("..") && !workspaceRelative.startsWith("node_modules")) {
|
|
1068
|
-
workspaceLinks.set(name, workspaceRelative);
|
|
1069
|
-
continue;
|
|
1070
|
-
}
|
|
1071
|
-
const packageJson = await readPackageJson(dir);
|
|
1072
|
-
const platformBound = Boolean(packageJson?.os ?? packageJson?.cpu);
|
|
1073
|
-
if (packageJson && platformBound && !matchesFunctionPlatform(packageJson)) {
|
|
1074
|
-
hostNatives.set(name, { dir, owner });
|
|
353
|
+
for (const [name, json] of manifests) {
|
|
354
|
+
if (!(json.os ?? json.cpu) || matchesFunctionPlatform(json))
|
|
1075
355
|
continue;
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
const self = { name: packageJson2?.name ?? name, version: packageJson2?.version ?? "" };
|
|
1082
|
-
for (const dependency of [
|
|
1083
|
-
...Object.keys(packageJson2?.dependencies ?? {}),
|
|
1084
|
-
...Object.keys(packageJson2?.optionalDependencies ?? {})
|
|
1085
|
-
]) {
|
|
1086
|
-
const nested = path2.join(packageDir, "node_modules", dependency);
|
|
1087
|
-
const nestedJson = existsSync2(path2.join(nested, "package.json")) ? await readPackageJson(nested) : undefined;
|
|
1088
|
-
if (!nestedJson || nestedJson.os || nestedJson.cpu) {
|
|
1089
|
-
queue.push({ name: dependency, from: packageDir, owner: self });
|
|
1090
|
-
continue;
|
|
1091
|
-
}
|
|
1092
|
-
const nestedTarget = path2.join(target, "node_modules", dependency);
|
|
1093
|
-
if (nestedCopies.has(nestedTarget))
|
|
1094
|
-
continue;
|
|
1095
|
-
nestedCopies.set(nestedTarget, nested);
|
|
1096
|
-
await expand(nested, nestedJson, nestedTarget);
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
await expand(dir, packageJson, path2.join("node_modules", name));
|
|
1100
|
-
}
|
|
1101
|
-
if (hostNatives.size > 0 && !skipDependencyClosure()) {
|
|
1102
|
-
const targets = await log.step(`resolve ${FUNCTION_PLATFORM.os}-${FUNCTION_PLATFORM.cpu} natives (${hostNatives.size} packages)`, () => platformNativePackages(hostNatives, log));
|
|
1103
|
-
for (const [name, dir] of targets)
|
|
1104
|
-
packageDirs.set(name, dir);
|
|
1105
|
-
}
|
|
1106
|
-
const copy = async () => {
|
|
1107
|
-
const entries = skipDependencyClosure() ? [] : [...packageDirs];
|
|
1108
|
-
const batchSize = 16;
|
|
1109
|
-
for (let index = 0;index < entries.length; index += batchSize) {
|
|
1110
|
-
await Promise.all(entries.slice(index, index + batchSize).map(async ([name, dir]) => {
|
|
1111
|
-
const target = path2.join(functionPath, "node_modules", name);
|
|
1112
|
-
await mkdir(path2.dirname(target), { recursive: true });
|
|
1113
|
-
await copyTree(dir, target, pack);
|
|
1114
|
-
}));
|
|
1115
|
-
}
|
|
1116
|
-
for (const [target, dir] of skipDependencyClosure() ? [] : nestedCopies) {
|
|
1117
|
-
await mkdir(path2.dirname(path2.join(functionPath, target)), { recursive: true });
|
|
1118
|
-
await copyTree(dir, path2.join(functionPath, target), pack);
|
|
1119
|
-
}
|
|
1120
|
-
for (const dir of skipDependencyClosure() ? [] : hrefPackageDirs) {
|
|
1121
|
-
const relative = path2.relative(workspaceRoot, dir);
|
|
1122
|
-
const target = path2.join(functionPath, relative);
|
|
1123
|
-
if (relative.startsWith("..") || existsSync2(target))
|
|
1124
|
-
continue;
|
|
1125
|
-
await mkdir(path2.dirname(target), { recursive: true });
|
|
1126
|
-
await copyTree(dir, target, pack);
|
|
1127
|
-
}
|
|
1128
|
-
for (const [name, workspaceRelative] of workspaceLinks) {
|
|
1129
|
-
const linkPath = path2.join(functionPath, "node_modules", name);
|
|
1130
|
-
await mkdir(path2.dirname(linkPath), { recursive: true });
|
|
1131
|
-
const target = path2.relative(path2.dirname(linkPath), path2.join(functionPath, workspaceRelative));
|
|
1132
|
-
if (!existsSync2(linkPath))
|
|
1133
|
-
await symlink(target, linkPath, "dir");
|
|
1134
|
-
}
|
|
1135
|
-
};
|
|
1136
|
-
return {
|
|
1137
|
-
tracedFiles,
|
|
1138
|
-
workspacePackages: [...workspaceLinks.values()],
|
|
1139
|
-
packageCount: packageDirs.size,
|
|
1140
|
-
copy
|
|
1141
|
-
};
|
|
1142
|
-
}
|
|
1143
|
-
function releaseEntries(config, manifest) {
|
|
1144
|
-
if (!existsSync2(buildIndexFile(config.outPath)))
|
|
1145
|
-
return;
|
|
1146
|
-
const index = readBuildIndex(config.outPath);
|
|
1147
|
-
return [
|
|
1148
|
-
...Object.values(index.modules),
|
|
1149
|
-
index.nextConfig,
|
|
1150
|
-
index.instrumentation?.file,
|
|
1151
|
-
index.instrumentation?.edge,
|
|
1152
|
-
...Object.values(index.compat?.cacheHandlers ?? {}),
|
|
1153
|
-
manifest.proxyModule
|
|
1154
|
-
].filter((artifact) => artifact !== undefined).map((artifact) => path2.resolve(config.outPath, artifact));
|
|
1155
|
-
}
|
|
1156
|
-
async function frameworkRuntimePackages(frameworkRoot2) {
|
|
1157
|
-
const src = path2.join(frameworkRoot2, "src");
|
|
1158
|
-
const scanners = {
|
|
1159
|
-
ts: new Bun.Transpiler({ loader: "ts" }),
|
|
1160
|
-
tsx: new Bun.Transpiler({ loader: "tsx" })
|
|
1161
|
-
};
|
|
1162
|
-
const queue = [
|
|
1163
|
-
...runtimeEntryFiles.map((file) => path2.join(src, file)),
|
|
1164
|
-
...runtimeEntryDirs.flatMap((dir) => listSourceFiles(path2.join(src, dir)).filter((file) => /(?<!\.d)\.tsx?$/.test(file)))
|
|
1165
|
-
];
|
|
1166
|
-
const seen = new Set(queue);
|
|
1167
|
-
const packages = new Set;
|
|
1168
|
-
for (const file of queue) {
|
|
1169
|
-
const scanner = file.endsWith(".tsx") || file.endsWith(".jsx") ? scanners.tsx : scanners.ts;
|
|
1170
|
-
for (const edge of scanner.scanImports(await readFile(file, "utf8"))) {
|
|
1171
|
-
if (edge.kind !== "import-statement" && edge.kind !== "dynamic-import")
|
|
1172
|
-
continue;
|
|
1173
|
-
if (!edge.path.startsWith(".")) {
|
|
1174
|
-
const name = packageNameFromSpecifier(edge.path);
|
|
1175
|
-
if (name)
|
|
1176
|
-
packages.add(name);
|
|
1177
|
-
continue;
|
|
1178
|
-
}
|
|
1179
|
-
const target = resolveFrom(edge.path, path2.dirname(file));
|
|
1180
|
-
if (target && !seen.has(target) && isInsideDir(src, target) && scriptFilePattern.test(target)) {
|
|
1181
|
-
seen.add(target);
|
|
1182
|
-
queue.push(target);
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
356
|
+
const owner = [...manifests].find(([, candidate]) => candidate.optionalDependencies?.[name]);
|
|
357
|
+
hostNatives.set(name, {
|
|
358
|
+
dirs: packages.get(name),
|
|
359
|
+
owner: owner && { name: owner[0], version: owner[1].version ?? "" }
|
|
360
|
+
});
|
|
1185
361
|
}
|
|
1186
|
-
|
|
1187
|
-
}
|
|
1188
|
-
function resolveFrom(specifier, dir) {
|
|
1189
|
-
try {
|
|
1190
|
-
return Bun.resolveSync(specifier, dir);
|
|
1191
|
-
} catch {
|
|
362
|
+
if (hostNatives.size === 0)
|
|
1192
363
|
return;
|
|
364
|
+
const targets = await platformNativePackages(hostNatives, manifests, log);
|
|
365
|
+
for (const [name, dir] of targets) {
|
|
366
|
+
for (const host of hostNatives.get(name)?.dirs ?? []) {
|
|
367
|
+
const target = path.join(path.dirname(host), name.split("/").at(-1));
|
|
368
|
+
await rm(host, { recursive: true, force: true });
|
|
369
|
+
await cp(dir, target, { recursive: true, dereference: true });
|
|
370
|
+
}
|
|
1193
371
|
}
|
|
1194
372
|
}
|
|
1195
|
-
function
|
|
1196
|
-
return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() ? listSourceFiles(path2.join(dir, entry.name)) : [path2.join(dir, entry.name)]);
|
|
1197
|
-
}
|
|
1198
|
-
async function platformNativePackages(hostNatives, log) {
|
|
373
|
+
async function platformNativePackages(hostNatives, manifests, log) {
|
|
1199
374
|
const owners = new Map;
|
|
1200
|
-
for (const [name, {
|
|
1201
|
-
const spec = owner ?? { name, version: (
|
|
375
|
+
for (const [name, { owner }] of hostNatives) {
|
|
376
|
+
const spec = owner ?? { name, version: manifests.get(name)?.version ?? "" };
|
|
1202
377
|
if (spec.version)
|
|
1203
378
|
owners.set(spec.name, spec.version);
|
|
1204
379
|
}
|
|
1205
380
|
const specs = [...owners].map(([name, version]) => `${name}@${version}`).sort();
|
|
1206
|
-
const fallback = () => new Map([...hostNatives].map(([name, { dir }]) => [name, dir]));
|
|
1207
381
|
if (specs.length === 0)
|
|
1208
|
-
return
|
|
382
|
+
return new Map;
|
|
1209
383
|
try {
|
|
1210
384
|
const installed = await crossPlatformInstall(specs);
|
|
1211
385
|
const matches = new Map;
|
|
1212
386
|
for (const [name, dir] of installed) {
|
|
1213
|
-
const
|
|
1214
|
-
if (
|
|
387
|
+
const json = await readPackageJson(dir);
|
|
388
|
+
if (json && (json.os ?? json.cpu) && matchesFunctionPlatform(json))
|
|
1215
389
|
matches.set(name, dir);
|
|
1216
390
|
}
|
|
1217
|
-
if (matches.size === 0)
|
|
391
|
+
if (matches.size === 0)
|
|
1218
392
|
throw new Error(`no ${FUNCTION_PLATFORM.os} builds in ${specs.join(" ")}`);
|
|
1219
|
-
}
|
|
1220
393
|
return matches;
|
|
1221
394
|
} catch (error) {
|
|
1222
395
|
console.warn(`vercel adapter: could not fetch ${FUNCTION_PLATFORM.os}-${FUNCTION_PLATFORM.cpu} native packages; the function will carry this machine's builds and fail at runtime:`, error);
|
|
1223
396
|
log.log("falling back to host native packages");
|
|
1224
|
-
return
|
|
397
|
+
return new Map;
|
|
1225
398
|
}
|
|
1226
399
|
}
|
|
1227
400
|
function matchesFunctionPlatform(packageJson) {
|
|
@@ -1236,13 +409,13 @@ function matchesFunctionPlatform(packageJson) {
|
|
|
1236
409
|
}
|
|
1237
410
|
async function crossPlatformInstall(specs) {
|
|
1238
411
|
const key = Bun.hash.xxHash3(`${FUNCTION_PLATFORM.os}-${FUNCTION_PLATFORM.cpu}\x00${specs.join("\x00")}`).toString(16);
|
|
1239
|
-
const dir =
|
|
1240
|
-
const modules =
|
|
1241
|
-
if (!
|
|
412
|
+
const dir = path.join(cacheRoot(), "vercel-natives", key);
|
|
413
|
+
const modules = path.join(dir, "node_modules");
|
|
414
|
+
if (!existsSync(modules)) {
|
|
1242
415
|
const staging = `${dir}.${process.pid.toString(36)}`;
|
|
1243
416
|
await rm(staging, { recursive: true, force: true });
|
|
1244
417
|
await mkdir(staging, { recursive: true });
|
|
1245
|
-
await writeText(
|
|
418
|
+
await writeText(path.join(staging, "package.json"), `{"name":"pnext-natives"}
|
|
1246
419
|
`);
|
|
1247
420
|
const install = Bun.spawn([
|
|
1248
421
|
"bun",
|
|
@@ -1267,101 +440,25 @@ async function crossPlatformInstall(specs) {
|
|
|
1267
440
|
if (entry.startsWith("."))
|
|
1268
441
|
continue;
|
|
1269
442
|
if (!entry.startsWith("@")) {
|
|
1270
|
-
installed.set(entry,
|
|
443
|
+
installed.set(entry, path.join(modules, entry));
|
|
1271
444
|
continue;
|
|
1272
445
|
}
|
|
1273
|
-
for (const scoped of readdirSync(
|
|
1274
|
-
installed.set(`${entry}/${scoped}`,
|
|
446
|
+
for (const scoped of readdirSync(path.join(modules, entry))) {
|
|
447
|
+
installed.set(`${entry}/${scoped}`, path.join(modules, entry, scoped));
|
|
1275
448
|
}
|
|
1276
449
|
}
|
|
1277
450
|
return installed;
|
|
1278
451
|
}
|
|
1279
|
-
var scriptFilePattern = /\.(?:m?js|cjs|jsx|tsx?)$/;
|
|
1280
|
-
var skippedScanDirs = new Set(["node_modules", ".git", ".next", ".pnext", ".turbo", ".vercel"]);
|
|
1281
|
-
function* walkTsconfigFiles(root) {
|
|
1282
|
-
const stack = [root];
|
|
1283
|
-
while (stack.length > 0) {
|
|
1284
|
-
const dir = stack.pop();
|
|
1285
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1286
|
-
const full = path2.join(dir, entry.name);
|
|
1287
|
-
if (entry.isDirectory()) {
|
|
1288
|
-
if (!skippedScanDirs.has(entry.name))
|
|
1289
|
-
stack.push(full);
|
|
1290
|
-
} else if (entry.isFile() && entry.name === "tsconfig.json") {
|
|
1291
|
-
yield full;
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
async function declaredDependencies(root) {
|
|
1297
|
-
const packageJson = await readPackageJson(root);
|
|
1298
|
-
return new Set(["dependencies", "optionalDependencies", "devDependencies"].flatMap((field) => Object.keys(packageJson?.[field] ?? {})));
|
|
1299
|
-
}
|
|
1300
|
-
function absolutePathFromSpecifier(specifier) {
|
|
1301
|
-
if (specifier.startsWith("file://"))
|
|
1302
|
-
return fileURLToPath2(specifier);
|
|
1303
|
-
return path2.isAbsolute(specifier) ? specifier : undefined;
|
|
1304
|
-
}
|
|
1305
|
-
function packageDirFromPath(file, name) {
|
|
1306
|
-
const posix = toPosixPath(file);
|
|
1307
|
-
const marker = `/node_modules/${name}/`;
|
|
1308
|
-
return posix.slice(0, posix.lastIndexOf(marker) + marker.length - 1);
|
|
1309
|
-
}
|
|
1310
|
-
function packageNameFromPath(file) {
|
|
1311
|
-
const parts = toPosixPath(file).split("/node_modules/");
|
|
1312
|
-
const tail = parts.at(-1);
|
|
1313
|
-
if (parts.length < 2 || !tail)
|
|
1314
|
-
return;
|
|
1315
|
-
const segments = tail.split("/");
|
|
1316
|
-
return segments[0]?.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
|
|
1317
|
-
}
|
|
1318
|
-
function packageNameFromSpecifier(specifier) {
|
|
1319
|
-
if (/^[./#]|^file:|^node:|^data:/.test(specifier))
|
|
1320
|
-
return;
|
|
1321
|
-
if (specifier === "bun" || specifier.startsWith("bun:"))
|
|
1322
|
-
return;
|
|
1323
|
-
if (specifier.includes(":"))
|
|
1324
|
-
return;
|
|
1325
|
-
if (specifier.startsWith("@") && !/^@[^/]+\/[^/]+/.test(specifier))
|
|
1326
|
-
return;
|
|
1327
|
-
const parts = specifier.split("/");
|
|
1328
|
-
const name = specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
1329
|
-
if (!name || builtinModules.includes(name))
|
|
1330
|
-
return;
|
|
1331
|
-
return name;
|
|
1332
|
-
}
|
|
1333
|
-
function resolvePackageDir(name, fromDirs) {
|
|
1334
|
-
for (const from of fromDirs) {
|
|
1335
|
-
let dir = path2.resolve(from);
|
|
1336
|
-
while (true) {
|
|
1337
|
-
const candidate = path2.join(dir, "node_modules", name);
|
|
1338
|
-
if (existsSync2(path2.join(candidate, "package.json")))
|
|
1339
|
-
return realDir(candidate);
|
|
1340
|
-
const parent = path2.dirname(dir);
|
|
1341
|
-
if (parent === dir)
|
|
1342
|
-
break;
|
|
1343
|
-
dir = parent;
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
return;
|
|
1347
|
-
}
|
|
1348
|
-
function realDir(dir) {
|
|
1349
|
-
try {
|
|
1350
|
-
return statSync(dir).isDirectory() ? realpathSync2(dir) : undefined;
|
|
1351
|
-
} catch {
|
|
1352
|
-
return;
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
452
|
async function copyStaticFiles(from, to, shouldCopy = () => true) {
|
|
1356
|
-
const files = (await listFiles(from)).filter((file) => shouldCopy(toPosixPath(
|
|
1357
|
-
const directories = new Set(files.map((file) =>
|
|
453
|
+
const files = (await listFiles(from)).filter((file) => shouldCopy(toPosixPath(path.relative(from, file))));
|
|
454
|
+
const directories = new Set(files.map((file) => path.dirname(path.join(to, path.relative(from, file)))));
|
|
1358
455
|
await Promise.all([...directories].map((dir) => mkdir(dir, { recursive: true })));
|
|
1359
|
-
await Promise.all(files.map((file) =>
|
|
456
|
+
await Promise.all(files.map((file) => copyFile(file, path.join(to, path.relative(from, file)), constants.COPYFILE_FICLONE)));
|
|
1360
457
|
}
|
|
1361
458
|
async function staticOverrides(publicPath, staticFiles) {
|
|
1362
459
|
const overrides = {};
|
|
1363
460
|
for (const file of await listFiles(publicPath)) {
|
|
1364
|
-
const relative = toPosixPath(
|
|
461
|
+
const relative = toPosixPath(path.relative(publicPath, file));
|
|
1365
462
|
if (!relative.endsWith("/index.html"))
|
|
1366
463
|
continue;
|
|
1367
464
|
overrides[relative] = { path: relative.replace(/\/index\.html$/, "") };
|
|
@@ -1377,7 +474,7 @@ async function staticOverrides(publicPath, staticFiles) {
|
|
|
1377
474
|
}
|
|
1378
475
|
async function immutableAssetRoutes(publicDir, publicAssets = []) {
|
|
1379
476
|
const app = new Set(publicAssets);
|
|
1380
|
-
const built = publicAssets.length > 0 ? (await listFiles(publicDir)).map((file) => toPosixPath(
|
|
477
|
+
const built = publicAssets.length > 0 ? (await listFiles(publicDir)).map((file) => toPosixPath(path.relative(publicDir, file))).filter((relative) => !app.has(relative) && immutableAssetPath(relative)) : [];
|
|
1381
478
|
const patterns = immutableAssetPatterns(built, publicAssets);
|
|
1382
479
|
return routeSources(patterns, (source) => `^/(?:${source})`).map((src) => ({
|
|
1383
480
|
src,
|
|
@@ -1424,46 +521,212 @@ function canServeStaticOnVercel(metadata) {
|
|
|
1424
521
|
function routeHeaders(metadata) {
|
|
1425
522
|
return metadata.headers.filter(([name]) => name.toLowerCase() !== "content-type");
|
|
1426
523
|
}
|
|
1427
|
-
var maxRouteSourceLength = 2000;
|
|
1428
|
-
function staticHeaderRoutes(staticFiles) {
|
|
1429
|
-
const groups = new Map;
|
|
1430
|
-
for (const [relative, metadata] of Object.entries(staticFiles)) {
|
|
1431
|
-
const extra = routeHeaders(metadata);
|
|
1432
|
-
if (extra.length === 0 || !canServeStaticOnVercel(metadata))
|
|
1433
|
-
continue;
|
|
1434
|
-
const headers = Object.fromEntries(new Headers(extra));
|
|
1435
|
-
const key = JSON.stringify(headers);
|
|
1436
|
-
const group = groups.get(key) ?? { headers, patterns: [] };
|
|
1437
|
-
groups.set(key, group);
|
|
1438
|
-
group.patterns.push(servedPathPattern(relative));
|
|
524
|
+
var maxRouteSourceLength = 2000;
|
|
525
|
+
function staticHeaderRoutes(staticFiles) {
|
|
526
|
+
const groups = new Map;
|
|
527
|
+
for (const [relative, metadata] of Object.entries(staticFiles)) {
|
|
528
|
+
const extra = routeHeaders(metadata);
|
|
529
|
+
if (extra.length === 0 || !canServeStaticOnVercel(metadata))
|
|
530
|
+
continue;
|
|
531
|
+
const headers = Object.fromEntries(new Headers(extra));
|
|
532
|
+
const key = JSON.stringify(headers);
|
|
533
|
+
const group = groups.get(key) ?? { headers, patterns: [] };
|
|
534
|
+
groups.set(key, group);
|
|
535
|
+
group.patterns.push(servedPathPattern(relative));
|
|
536
|
+
}
|
|
537
|
+
return [...groups.values()].flatMap(({ headers, patterns }) => routeSources(patterns, (source) => `^/(?:${source})$`).map((src) => ({
|
|
538
|
+
src,
|
|
539
|
+
methods: ["GET", "HEAD"],
|
|
540
|
+
headers,
|
|
541
|
+
continue: true,
|
|
542
|
+
important: true
|
|
543
|
+
})));
|
|
544
|
+
}
|
|
545
|
+
function routeSources(patterns, wrap) {
|
|
546
|
+
const sources = [];
|
|
547
|
+
for (const pattern of patterns) {
|
|
548
|
+
const last = sources.length - 1;
|
|
549
|
+
if (last >= 0 && wrap(`${sources[last]}|${pattern}`).length <= maxRouteSourceLength) {
|
|
550
|
+
sources[last] += `|${pattern}`;
|
|
551
|
+
} else {
|
|
552
|
+
sources.push(pattern);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return sources.map(wrap);
|
|
556
|
+
}
|
|
557
|
+
function servedPathPattern(relative) {
|
|
558
|
+
if (relative === "index.html")
|
|
559
|
+
return "(?:index\\.html)?";
|
|
560
|
+
if (!relative.endsWith("/index.html"))
|
|
561
|
+
return escapeRegex(relative);
|
|
562
|
+
return `${escapeRegex(relative.slice(0, -"/index.html".length))}(?:/|/index\\.html)?`;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/cli/adapters/vercel-warm.ts
|
|
566
|
+
import { fileURLToPath } from "url";
|
|
567
|
+
|
|
568
|
+
// src/runtime/release-graph.ts
|
|
569
|
+
import { existsSync as existsSync2, readFileSync, realpathSync } from "fs";
|
|
570
|
+
import path2 from "path";
|
|
571
|
+
var layerDirs = {
|
|
572
|
+
"server:server": "rsc",
|
|
573
|
+
"client:client": "ssr"
|
|
574
|
+
};
|
|
575
|
+
var layers = Object.keys(layerDirs);
|
|
576
|
+
var frameworkRoot = realpathSync(path2.resolve(__PNEXT_PACKAGE_ROOT__ + "/src/runtime", "..", ".."));
|
|
577
|
+
|
|
578
|
+
// src/cli/adapters/vercel-warm.ts
|
|
579
|
+
var DONE_MARKER = "pnext-warm-done:";
|
|
580
|
+
var COMPILED_MARKER = "pnext-warm-compiled";
|
|
581
|
+
var ATTEMPT_TIMEOUT_MS = 10 * 60000;
|
|
582
|
+
var MAX_ATTEMPTS = 3;
|
|
583
|
+
var FULL_MODE_FLAG = "--full";
|
|
584
|
+
function startWarmChild(config, mode = "full") {
|
|
585
|
+
const children = new Set;
|
|
586
|
+
let disposed = false;
|
|
587
|
+
const spawn = () => {
|
|
588
|
+
if (disposed)
|
|
589
|
+
return;
|
|
590
|
+
const child = spawnWarmProcess(config, mode);
|
|
591
|
+
if (!child)
|
|
592
|
+
return;
|
|
593
|
+
children.add(child);
|
|
594
|
+
child.exited.finally(() => children.delete(child));
|
|
595
|
+
forwardWarmStderr(child);
|
|
596
|
+
return child;
|
|
597
|
+
};
|
|
598
|
+
const killOnExit = () => kill();
|
|
599
|
+
const kill = () => {
|
|
600
|
+
if (disposed)
|
|
601
|
+
return;
|
|
602
|
+
disposed = true;
|
|
603
|
+
process.off("exit", killOnExit);
|
|
604
|
+
for (const child of children)
|
|
605
|
+
child.kill();
|
|
606
|
+
children.clear();
|
|
607
|
+
};
|
|
608
|
+
process.once("exit", killOnExit);
|
|
609
|
+
const first = spawn();
|
|
610
|
+
return {
|
|
611
|
+
prewarm(files) {
|
|
612
|
+
if (!first || files.length === 0)
|
|
613
|
+
return;
|
|
614
|
+
try {
|
|
615
|
+
first.stdin.write(`${JSON.stringify({ prewarm: files })}
|
|
616
|
+
`);
|
|
617
|
+
first.stdin.flush();
|
|
618
|
+
} catch {}
|
|
619
|
+
},
|
|
620
|
+
finish: (log, onCompiled, facts = { clientReferences: [] }) => warmWithRestarts(first, spawn, mode, log, facts, onCompiled).finally(kill),
|
|
621
|
+
kill
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
async function forwardWarmStderr(child) {
|
|
625
|
+
try {
|
|
626
|
+
const reader = child.stderr.getReader();
|
|
627
|
+
for (;; ) {
|
|
628
|
+
const { done, value } = await reader.read();
|
|
629
|
+
if (done)
|
|
630
|
+
return;
|
|
631
|
+
process.stderr.write(value);
|
|
632
|
+
}
|
|
633
|
+
} catch {}
|
|
634
|
+
}
|
|
635
|
+
function spawnWarmProcess(config, mode) {
|
|
636
|
+
const entry = fileURLToPath(new URL(Bun.pathToFileURL(__PNEXT_PACKAGE_ROOT__ + "/src/cli/adapters/vercel-warm.ts").href));
|
|
637
|
+
const argv = mode === "full" ? [config.root, FULL_MODE_FLAG] : [config.root];
|
|
638
|
+
try {
|
|
639
|
+
return Bun.spawn([namedBunBinary("pnext-warm"), "--conditions=react-server", entry, ...argv], {
|
|
640
|
+
cwd: config.root,
|
|
641
|
+
stdin: "pipe",
|
|
642
|
+
stdout: "pipe",
|
|
643
|
+
stderr: "pipe",
|
|
644
|
+
env: process.env
|
|
645
|
+
});
|
|
646
|
+
} catch {
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
async function warmWithRestarts(first, spawn, mode, log, facts, onCompiled) {
|
|
651
|
+
const finished = new Map;
|
|
652
|
+
const compiled = () => [...finished.values()].filter((file) => Boolean(file));
|
|
653
|
+
let fired = false;
|
|
654
|
+
const fireOnCompiled = onCompiled ? () => {
|
|
655
|
+
if (fired)
|
|
656
|
+
return;
|
|
657
|
+
fired = true;
|
|
658
|
+
onCompiled(compiled());
|
|
659
|
+
} : undefined;
|
|
660
|
+
let child = first;
|
|
661
|
+
for (let attempt = 1;attempt <= MAX_ATTEMPTS && child; attempt++) {
|
|
662
|
+
const before = finished.size;
|
|
663
|
+
const failure = await runAttempt(child, {
|
|
664
|
+
skip: [...finished.keys()],
|
|
665
|
+
compiled: Object.fromEntries([...finished].filter((entry) => Boolean(entry[1]))),
|
|
666
|
+
...facts
|
|
667
|
+
}, finished, fireOnCompiled);
|
|
668
|
+
if (!failure) {
|
|
669
|
+
log.log(`warmed ${compiled().length} modules`);
|
|
670
|
+
return compiled();
|
|
671
|
+
}
|
|
672
|
+
child = finished.size > before && attempt < MAX_ATTEMPTS ? spawn() : undefined;
|
|
673
|
+
if (child)
|
|
674
|
+
log.log(`warm-up ${failure} after ${finished.size} files; restarting past them`);
|
|
675
|
+
else
|
|
676
|
+
warmIncomplete(failure, finished.size, mode);
|
|
1439
677
|
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
methods: ["GET", "HEAD"],
|
|
1443
|
-
headers,
|
|
1444
|
-
continue: true,
|
|
1445
|
-
important: true
|
|
1446
|
-
})));
|
|
678
|
+
fireOnCompiled?.();
|
|
679
|
+
return compiled();
|
|
1447
680
|
}
|
|
1448
|
-
function
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
681
|
+
async function runAttempt(child, request, finished, onCompiled) {
|
|
682
|
+
try {
|
|
683
|
+
child.stdin.write(`${JSON.stringify(request)}
|
|
684
|
+
`);
|
|
685
|
+
child.stdin.end();
|
|
686
|
+
} catch {}
|
|
687
|
+
const timeout = setTimeout(() => child.kill("SIGKILL"), ATTEMPT_TIMEOUT_MS);
|
|
688
|
+
timeout.unref?.();
|
|
689
|
+
const processLine = (line) => {
|
|
690
|
+
if (!line)
|
|
691
|
+
return;
|
|
692
|
+
if (line === COMPILED_MARKER) {
|
|
693
|
+
onCompiled?.();
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (!line.startsWith(DONE_MARKER)) {
|
|
697
|
+
console.log(line);
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
const [source, artifact] = line.slice(DONE_MARKER.length).split("\t");
|
|
701
|
+
if (source)
|
|
702
|
+
finished.set(source, artifact || undefined);
|
|
703
|
+
};
|
|
704
|
+
const reader = child.stdout.getReader();
|
|
705
|
+
const decoder = new TextDecoder;
|
|
706
|
+
let buffer = "";
|
|
707
|
+
for (;; ) {
|
|
708
|
+
const { done, value } = await reader.read();
|
|
709
|
+
if (done)
|
|
710
|
+
break;
|
|
711
|
+
buffer += decoder.decode(value, { stream: true });
|
|
712
|
+
let newline;
|
|
713
|
+
while ((newline = buffer.indexOf(`
|
|
714
|
+
`)) >= 0) {
|
|
715
|
+
processLine(buffer.slice(0, newline));
|
|
716
|
+
buffer = buffer.slice(newline + 1);
|
|
1456
717
|
}
|
|
1457
718
|
}
|
|
1458
|
-
|
|
719
|
+
if (buffer)
|
|
720
|
+
processLine(buffer);
|
|
721
|
+
const code = await child.exited.finally(() => clearTimeout(timeout));
|
|
722
|
+
if (code === 0)
|
|
723
|
+
return;
|
|
724
|
+
return child.signalCode ? `was killed by ${child.signalCode}` : `exited with code ${code}`;
|
|
1459
725
|
}
|
|
1460
|
-
function
|
|
1461
|
-
|
|
1462
|
-
return "(?:index\\.html)?";
|
|
1463
|
-
if (!relative.endsWith("/index.html"))
|
|
1464
|
-
return escapeRegex(relative);
|
|
1465
|
-
return `${escapeRegex(relative.slice(0, -"/index.html".length))}(?:/|/index\\.html)?`;
|
|
726
|
+
function warmIncomplete(failure, done, mode) {
|
|
727
|
+
console.warn(`pnext build: module warm-up ${failure} after warming ${done} file(s). ` + (mode === "full" ? "The function ships without the rest of its module cache and may fail to render those " + "routes at request time, where Vercel's filesystem is read-only." : "The production server compiles the rest on the first request that needs them."));
|
|
1466
728
|
}
|
|
729
|
+
if (false) {}
|
|
1467
730
|
|
|
1468
731
|
// src/cli/build.ts
|
|
1469
732
|
import { runWithCacheScope } from "../../../src/request/cache.ts";
|
|
@@ -1471,10 +734,10 @@ import { runWithCacheScope } from "../../../src/request/cache.ts";
|
|
|
1471
734
|
// src/cli/build/cache.ts
|
|
1472
735
|
import { createHash } from "crypto";
|
|
1473
736
|
import { existsSync as existsSync3 } from "fs";
|
|
1474
|
-
import { lstat, mkdir as mkdir2, readFile as readFile2, readdir, readlink } from "fs/promises";
|
|
737
|
+
import { lstat, mkdir as mkdir2, readFile as readFile2, readdir as readdir2, readlink } from "fs/promises";
|
|
1475
738
|
import path3 from "path";
|
|
1476
739
|
var CACHE_VERSION = 2;
|
|
1477
|
-
var CACHE_SEGMENTS = ["
|
|
740
|
+
var CACHE_SEGMENTS = ["build"];
|
|
1478
741
|
var SKIP_INPUT_DIRS = new Set([
|
|
1479
742
|
".claude",
|
|
1480
743
|
".git",
|
|
@@ -1511,7 +774,7 @@ async function lookupBuildCache(config, options) {
|
|
|
1511
774
|
return { enabled: true, context, inputs, reason: `output (${changed || "unknown"})` };
|
|
1512
775
|
}
|
|
1513
776
|
try {
|
|
1514
|
-
const manifest = resolveManifest(JSON.parse(await readFile2(
|
|
777
|
+
const manifest = resolveManifest(JSON.parse(await readFile2(buildManifestFile(config.outPath), "utf8")), config.outPath, config.root);
|
|
1515
778
|
return { enabled: true, context, inputs, manifest, reason: "hit" };
|
|
1516
779
|
} catch {
|
|
1517
780
|
return { enabled: true, context, inputs, reason: "manifest" };
|
|
@@ -1538,7 +801,7 @@ function cacheEnabled(options) {
|
|
|
1538
801
|
return options.adapter === undefined && options.debugBuildPaths === undefined && options.buildMode === undefined && options.debugPrerender !== true;
|
|
1539
802
|
}
|
|
1540
803
|
function cacheDir(outPath) {
|
|
1541
|
-
return path3.join(outPath, ...CACHE_SEGMENTS);
|
|
804
|
+
return path3.join(outCachePath(outPath), ...CACHE_SEGMENTS);
|
|
1542
805
|
}
|
|
1543
806
|
function recordFile(outPath) {
|
|
1544
807
|
return path3.join(cacheDir(outPath), "result.json");
|
|
@@ -1605,7 +868,7 @@ async function inputRecords(config, previous) {
|
|
|
1605
868
|
async function collectModuleGraphInputs(config, files) {
|
|
1606
869
|
let parsed;
|
|
1607
870
|
try {
|
|
1608
|
-
parsed = JSON.parse(await readFile2(path3.join(config.outPath, "
|
|
871
|
+
parsed = JSON.parse(await readFile2(path3.join(outCachePath(config.outPath), "server", "graph.json"), "utf8"));
|
|
1609
872
|
} catch {
|
|
1610
873
|
return;
|
|
1611
874
|
}
|
|
@@ -1618,7 +881,7 @@ async function collectModuleGraphInputs(config, files) {
|
|
|
1618
881
|
}
|
|
1619
882
|
}
|
|
1620
883
|
async function collectTree(root, prefix, files, outPath, dir = root) {
|
|
1621
|
-
const entries = await
|
|
884
|
+
const entries = await readdir2(dir, { withFileTypes: true }).catch(() => []);
|
|
1622
885
|
await Promise.all(entries.map(async (entry) => {
|
|
1623
886
|
const file = path3.join(dir, entry.name);
|
|
1624
887
|
if (file === outPath || file.startsWith(`${outPath}${path3.sep}`))
|
|
@@ -1643,7 +906,7 @@ function addFile(files, key, file) {
|
|
|
1643
906
|
}
|
|
1644
907
|
async function outputSnapshot(outPath) {
|
|
1645
908
|
const files = new Map;
|
|
1646
|
-
const entries = await
|
|
909
|
+
const entries = await readdir2(outPath, { withFileTypes: true }).catch(() => []);
|
|
1647
910
|
await Promise.all(entries.map(async (entry) => {
|
|
1648
911
|
if (entry.name === "cache" || entry.name === "dev")
|
|
1649
912
|
return;
|
|
@@ -1669,7 +932,7 @@ function changedFiles(before, after) {
|
|
|
1669
932
|
return [...new Set([...Object.keys(before), ...Object.keys(after)])].filter((file) => before[file] !== after[file]);
|
|
1670
933
|
}
|
|
1671
934
|
async function collectOutputTree(root, dir, files) {
|
|
1672
|
-
const entries = await
|
|
935
|
+
const entries = await readdir2(dir, { withFileTypes: true });
|
|
1673
936
|
await Promise.all(entries.map(async (entry) => {
|
|
1674
937
|
const file = path3.join(dir, entry.name);
|
|
1675
938
|
if (entry.isDirectory())
|
|
@@ -1686,32 +949,559 @@ function toPosix(file) {
|
|
|
1686
949
|
return path3.sep === "/" ? file : file.split(path3.sep).join("/");
|
|
1687
950
|
}
|
|
1688
951
|
|
|
1689
|
-
// src/cli/serve/
|
|
1690
|
-
import {
|
|
1691
|
-
import {
|
|
952
|
+
// src/cli/serve/standalone.ts
|
|
953
|
+
import { createHash as createHash2 } from "crypto";
|
|
954
|
+
import { constants as constants2, existsSync as existsSync4, readFileSync as readFileSync2, readdirSync as readdirSync2, realpathSync as realpathSync2, statSync } from "fs";
|
|
955
|
+
import { copyFile as copyFile2, mkdir as mkdir3, readFile as readFile3, rename as rename2, rm as rm2, writeFile } from "fs/promises";
|
|
956
|
+
import { builtinModules } from "module";
|
|
1692
957
|
import path4 from "path";
|
|
1693
|
-
|
|
1694
|
-
|
|
958
|
+
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
959
|
+
var frameworkRoot2 = realpathSync2(path4.resolve(__PNEXT_PACKAGE_ROOT__ + "/src/cli/serve", "..", "..", ".."));
|
|
960
|
+
var frameworkPackage = JSON.parse(readFileSync2(path4.join(frameworkRoot2, "package.json"), "utf8"));
|
|
961
|
+
var runtimeDependencies = new Set(Object.keys(frameworkPackage.dependencies ?? {}));
|
|
962
|
+
var buildOnlyModule = /^(?:build|modules|loader|compile|esbuild|dev|run|typegen|analyze|create)$/;
|
|
963
|
+
var builtins = new Set(builtinModules);
|
|
964
|
+
var scriptFile = /\.(?:[cm]?[jt]sx?)$/;
|
|
965
|
+
function frameworkStartEntry() {
|
|
966
|
+
return readPrebundleStamp(frameworkRoot2, frameworkFingerprint()) ? path4.join(frameworkRoot2, "dist", "server", "cli", "start.js") : path4.join(frameworkRoot2, "src", "cli", "start.ts");
|
|
967
|
+
}
|
|
968
|
+
function startStandalone(config) {
|
|
969
|
+
const input = {
|
|
970
|
+
outPath: config.outPath,
|
|
971
|
+
root: config.root,
|
|
972
|
+
workspaceRoot: config.workspaceRoot
|
|
973
|
+
};
|
|
974
|
+
const modules = path4.join(config.workspaceRoot, "node_modules");
|
|
975
|
+
const cacheFile = existsSync4(modules) && path4.join(modules, ".cache", "pnext", `standalone-${frameworkTraceKey()}.json`);
|
|
976
|
+
if (cacheFile && existsSync4(cacheFile)) {
|
|
977
|
+
try {
|
|
978
|
+
return Promise.resolve(JSON.parse(readFileSync2(cacheFile, "utf8")));
|
|
979
|
+
} catch {}
|
|
980
|
+
}
|
|
981
|
+
const framework = new Promise((resolve, reject) => {
|
|
982
|
+
const worker = new Worker(new URL("./standalone-worker.ts", Bun.pathToFileURL(__PNEXT_PACKAGE_ROOT__ + "/src/cli/serve/standalone.ts").href));
|
|
983
|
+
worker.unref?.();
|
|
984
|
+
worker.onmessage = (event) => {
|
|
985
|
+
resolve(event.data);
|
|
986
|
+
worker.terminate();
|
|
987
|
+
};
|
|
988
|
+
worker.onerror = (event) => {
|
|
989
|
+
reject(new Error(event.message));
|
|
990
|
+
worker.terminate();
|
|
991
|
+
};
|
|
992
|
+
worker.postMessage(input);
|
|
993
|
+
}).catch(() => traceFramework(input));
|
|
994
|
+
if (cacheFile)
|
|
995
|
+
framework.then(async (snapshot) => {
|
|
996
|
+
await mkdir3(path4.dirname(cacheFile), { recursive: true });
|
|
997
|
+
const temporary = `${cacheFile}.${process.pid}.tmp`;
|
|
998
|
+
await writeFile(temporary, JSON.stringify(snapshot));
|
|
999
|
+
await rename2(temporary, cacheFile);
|
|
1000
|
+
}).catch(() => {
|
|
1001
|
+
return;
|
|
1002
|
+
});
|
|
1003
|
+
return framework;
|
|
1004
|
+
}
|
|
1005
|
+
function frameworkTraceKey() {
|
|
1006
|
+
const startEntry = frameworkStartEntry();
|
|
1007
|
+
const packages = [...runtimeDependencies, ...frameworkRuntimeSpecifiers()].map((specifier) => {
|
|
1008
|
+
const file = resolveEdge(specifier, startEntry);
|
|
1009
|
+
return file ? `${file}\x00${statSync(file).mtimeMs}` : specifier;
|
|
1010
|
+
});
|
|
1011
|
+
return createHash2("sha256").update(JSON.stringify([frameworkFingerprint(), startEntry, packages])).digest("hex").slice(0, 16);
|
|
1012
|
+
}
|
|
1013
|
+
async function traceFramework(config) {
|
|
1014
|
+
const tracer = createTracer(config);
|
|
1015
|
+
const startEntry = frameworkStartEntry();
|
|
1016
|
+
await tracer.add([
|
|
1017
|
+
{ file: startEntry, app: false },
|
|
1018
|
+
...frameworkRuntimeSpecifiers().flatMap((specifier) => {
|
|
1019
|
+
const file = resolveEdge(specifier, startEntry);
|
|
1020
|
+
return file ? [{ file, app: false }] : [];
|
|
1021
|
+
})
|
|
1022
|
+
]);
|
|
1023
|
+
return tracer.snapshot();
|
|
1024
|
+
}
|
|
1025
|
+
async function writeStandalone(config, framework = startStandalone(config)) {
|
|
1026
|
+
const outPath = config.outPath;
|
|
1027
|
+
const cache = cacheRoot2(outPath);
|
|
1028
|
+
const index = readBuildIndex(outPath);
|
|
1029
|
+
const manifestFile = buildManifestFile(outPath);
|
|
1030
|
+
const manifest = JSON.parse(await readFile3(manifestFile, "utf8"));
|
|
1031
|
+
const startEntry = frameworkStartEntry();
|
|
1032
|
+
const snapshot = await framework;
|
|
1033
|
+
const copier = createCopier(outPath);
|
|
1034
|
+
const rewrittenFramework = new Map(snapshot.rewritten);
|
|
1035
|
+
for (const [dest, source] of snapshot.files)
|
|
1036
|
+
copier.copy(dest, source, rewrittenFramework.get(dest));
|
|
1037
|
+
const tracer = createTracer(config, snapshot, (dest) => copier.copy(dest, tracer.trace.files.get(dest), tracer.trace.rewritten.get(dest)));
|
|
1038
|
+
const { trace, place } = tracer;
|
|
1039
|
+
await tracer.add([
|
|
1040
|
+
...Object.values(index.modules),
|
|
1041
|
+
...index.dependencies ?? [],
|
|
1042
|
+
index.nextConfig,
|
|
1043
|
+
index.instrumentation?.file,
|
|
1044
|
+
index.instrumentation?.edge,
|
|
1045
|
+
...Object.values(index.compat?.cacheHandlers ?? {}),
|
|
1046
|
+
...Object.values(index.fonts ?? {}).flatMap((font) => font.files),
|
|
1047
|
+
manifest.proxyModule,
|
|
1048
|
+
...(manifest.actions ?? []).map((action) => action.modulePath)
|
|
1049
|
+
].flatMap((artifact) => artifact ? [{ file: path4.resolve(outPath, artifact), app: true }] : []));
|
|
1050
|
+
addAppFiles(config, index, trace);
|
|
1051
|
+
tracer.flush();
|
|
1052
|
+
await copier.settle();
|
|
1053
|
+
const cachePrefix = `${toPosixPath(path4.relative(outPath, cache))}/`;
|
|
1054
|
+
const relocate = (value) => {
|
|
1055
|
+
if (typeof value === "string")
|
|
1056
|
+
return value.startsWith(cachePrefix) ? `server/${value.slice(cachePrefix.length)}` : value;
|
|
1057
|
+
if (Array.isArray(value))
|
|
1058
|
+
return value.map(relocate);
|
|
1059
|
+
if (value && typeof value === "object")
|
|
1060
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, relocate(item)]));
|
|
1061
|
+
return value;
|
|
1062
|
+
};
|
|
1063
|
+
const indexFile = buildIndexFile(outPath);
|
|
1064
|
+
await writeFile(indexFile, JSON.stringify(relocate(JSON.parse(await readFile3(indexFile, "utf8")))));
|
|
1065
|
+
const shippedManifest = relocate(JSON.parse(await readFile3(manifestFile, "utf8")));
|
|
1066
|
+
for (const route of shippedManifest.routes) {
|
|
1067
|
+
if (route.sourceFiles)
|
|
1068
|
+
route.sourceFiles = route.sourceFiles.filter((file) => !file.startsWith("../"));
|
|
1069
|
+
}
|
|
1070
|
+
await writeFile(manifestFile, `${JSON.stringify(shippedManifest, null, 2)}
|
|
1071
|
+
`);
|
|
1072
|
+
await writeFile(path4.join(outPath, "server", "entry.js"), `export * from ${JSON.stringify(relativeSpecifier("server", place(startEntry)))}
|
|
1073
|
+
`);
|
|
1074
|
+
await writeFile(path4.join(outPath, "package.json"), `{ "type": "module" }
|
|
1075
|
+
`);
|
|
1076
|
+
const origins = Object.fromEntries([...trace.files].filter(([dest]) => dest.startsWith("node_modules/")));
|
|
1077
|
+
const originsFile = standaloneOriginsFile(outPath);
|
|
1078
|
+
await mkdir3(path4.dirname(originsFile), { recursive: true });
|
|
1079
|
+
await writeFile(originsFile, JSON.stringify({ release: outPath, origins }));
|
|
1080
|
+
}
|
|
1081
|
+
function setFile(trace, dest, source) {
|
|
1082
|
+
if (!trace.files.has(dest))
|
|
1083
|
+
trace.fresh.push(dest);
|
|
1084
|
+
trace.files.set(dest, source);
|
|
1085
|
+
}
|
|
1086
|
+
function createTracer(config, from, onReady) {
|
|
1087
|
+
const outPath = config.outPath;
|
|
1088
|
+
const cache = cacheRoot2(outPath);
|
|
1089
|
+
const trace = {
|
|
1090
|
+
files: new Map(from?.files),
|
|
1091
|
+
fresh: [],
|
|
1092
|
+
rewritten: new Map(from?.rewritten)
|
|
1093
|
+
};
|
|
1094
|
+
const claims = new Map(from?.claims);
|
|
1095
|
+
const place = createPlacer(outPath, cache, claims);
|
|
1096
|
+
const standalones = new Set(from?.standalones);
|
|
1097
|
+
const shipped = (file) => installed(file) || isInside(frameworkRoot2, file) && !isInside(config.root, file);
|
|
1098
|
+
const seen = new Set(from?.seen);
|
|
1099
|
+
const reads = new Map;
|
|
1100
|
+
const prefetch = (file) => {
|
|
1101
|
+
if (scriptFile.test(file) && !reads.has(file))
|
|
1102
|
+
reads.set(file, readFile3(file, "utf8").catch(() => {
|
|
1103
|
+
return;
|
|
1104
|
+
}));
|
|
1105
|
+
};
|
|
1106
|
+
const queue = [];
|
|
1107
|
+
const enqueue = (file, app) => {
|
|
1108
|
+
if (seen.has(`${app}\x00${file}`))
|
|
1109
|
+
return;
|
|
1110
|
+
queue.push({ file, app });
|
|
1111
|
+
prefetch(file);
|
|
1112
|
+
};
|
|
1113
|
+
const flush = () => {
|
|
1114
|
+
for (const dest of trace.fresh.splice(0))
|
|
1115
|
+
onReady?.(dest);
|
|
1116
|
+
};
|
|
1117
|
+
const run = async (items) => {
|
|
1118
|
+
for (const item of items)
|
|
1119
|
+
enqueue(item.file, item.app);
|
|
1120
|
+
for (let item = queue.shift();item; item = queue.shift(), flush()) {
|
|
1121
|
+
const { file, app } = item;
|
|
1122
|
+
if (seen.has(`${app}\x00${file}`))
|
|
1123
|
+
continue;
|
|
1124
|
+
seen.add(`${app}\x00${file}`);
|
|
1125
|
+
const nested = enclosingStandalone(file, outPath);
|
|
1126
|
+
if (nested) {
|
|
1127
|
+
if (!standalones.has(nested)) {
|
|
1128
|
+
standalones.add(nested);
|
|
1129
|
+
addTree(nested, path4.posix.dirname(path4.posix.dirname(place(path4.join(nested, "server", "entry.js")))), trace);
|
|
1130
|
+
}
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
const dest = place(file);
|
|
1134
|
+
setFile(trace, dest, file);
|
|
1135
|
+
if (!isInside(outPath, file) && !isInside(cache, file))
|
|
1136
|
+
addPackageFiles(file, trace, place);
|
|
1137
|
+
if (!scriptFile.test(file))
|
|
1138
|
+
continue;
|
|
1139
|
+
const release = isInside(outPath, file) || isInside(cache, file);
|
|
1140
|
+
const framework = !release && isInside(frameworkRoot2, file) && !installedIn(frameworkRoot2, file);
|
|
1141
|
+
prefetch(file);
|
|
1142
|
+
const source = await reads.get(file);
|
|
1143
|
+
if (source === undefined)
|
|
1144
|
+
continue;
|
|
1145
|
+
const edits = new Map;
|
|
1146
|
+
for (const edge of scanEdges(file, source)) {
|
|
1147
|
+
if (edge.url) {
|
|
1148
|
+
const target2 = urlTarget(edge.specifier, file);
|
|
1149
|
+
if (!target2)
|
|
1150
|
+
continue;
|
|
1151
|
+
const appFile = release && !isInside(outPath, target2) && !isInside(cache, target2) && !shipped(target2);
|
|
1152
|
+
if (appFile && scriptFile.test(target2))
|
|
1153
|
+
continue;
|
|
1154
|
+
if (!statSync(target2, { throwIfNoEntry: false })?.isFile())
|
|
1155
|
+
continue;
|
|
1156
|
+
const at = appFile ? toPosixPath(path4.join("server", "assets", path4.relative(config.workspaceRoot, target2))) : place(target2);
|
|
1157
|
+
if (appFile)
|
|
1158
|
+
setFile(trace, at, target2);
|
|
1159
|
+
else
|
|
1160
|
+
enqueue(target2, release);
|
|
1161
|
+
if (release) {
|
|
1162
|
+
const relative = relativeSpecifier(path4.dirname(dest), at);
|
|
1163
|
+
if (relative !== edge.specifier)
|
|
1164
|
+
edits.set(edge.specifier, relative);
|
|
1165
|
+
}
|
|
1166
|
+
continue;
|
|
1167
|
+
}
|
|
1168
|
+
const bare = isPackageSpecifier(edge.specifier);
|
|
1169
|
+
const name = bare ? packageName(edge.specifier) : undefined;
|
|
1170
|
+
if (bare && !name && !edge.specifier.startsWith("#"))
|
|
1171
|
+
continue;
|
|
1172
|
+
if (name && framework && !app && (edge.require || !runtimeDependencies.has(name)))
|
|
1173
|
+
continue;
|
|
1174
|
+
const target = resolveEdge(edge.specifier, file, edge.require);
|
|
1175
|
+
if (!target)
|
|
1176
|
+
continue;
|
|
1177
|
+
if (edge.dynamic && framework && buildOnlyModule.test(moduleName(target)))
|
|
1178
|
+
continue;
|
|
1179
|
+
enqueue(target, release);
|
|
1180
|
+
for (const counterpart of frameworkCounterparts(target))
|
|
1181
|
+
enqueue(counterpart, release);
|
|
1182
|
+
if (release || name && !place(target).startsWith(`node_modules/${name}/`)) {
|
|
1183
|
+
const relative = relativeSpecifier(path4.dirname(dest), place(target));
|
|
1184
|
+
if (relative !== edge.specifier)
|
|
1185
|
+
edits.set(edge.specifier, relative);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
if (edits.size > 0)
|
|
1189
|
+
trace.rewritten.set(dest, rewriteSpecifiers(file, source, edits));
|
|
1190
|
+
}
|
|
1191
|
+
flush();
|
|
1192
|
+
};
|
|
1193
|
+
const snapshot = () => ({
|
|
1194
|
+
files: [...trace.files],
|
|
1195
|
+
rewritten: [...trace.rewritten],
|
|
1196
|
+
seen: [...seen],
|
|
1197
|
+
claims: [...claims],
|
|
1198
|
+
standalones: [...standalones]
|
|
1199
|
+
});
|
|
1200
|
+
return { trace, place, add: run, snapshot, flush };
|
|
1201
|
+
}
|
|
1202
|
+
var prunedDirNames = [
|
|
1203
|
+
"node_modules",
|
|
1204
|
+
".git",
|
|
1205
|
+
".next",
|
|
1206
|
+
".pnext",
|
|
1207
|
+
".turbo",
|
|
1208
|
+
".cache",
|
|
1209
|
+
".vercel",
|
|
1210
|
+
".tmp"
|
|
1211
|
+
];
|
|
1212
|
+
var standaloneEntries = new Set(["server", "static", "node_modules", "package.json"]);
|
|
1213
|
+
function addAppFiles(config, index, trace) {
|
|
1214
|
+
const { keep = [], exclude = [] } = config.adapter ?? {};
|
|
1215
|
+
const named = (entries, name) => entries.some((entry) => name === entry || entry.startsWith(".") && name.endsWith(entry));
|
|
1216
|
+
for (const dest of trace.files.keys()) {
|
|
1217
|
+
const segments = dest.split("/");
|
|
1218
|
+
if (dest.startsWith("node_modules/") && segments.some((name) => named(exclude, name)))
|
|
1219
|
+
trace.files.delete(dest);
|
|
1220
|
+
}
|
|
1221
|
+
if (keep.length === 0)
|
|
1222
|
+
return;
|
|
1223
|
+
const compiled = compiledSources(config, index);
|
|
1224
|
+
const outTop = path4.relative(config.root, config.outRootPath).split(path4.sep)[0];
|
|
1225
|
+
const visit = (dir, kept) => {
|
|
1226
|
+
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
1227
|
+
const file = path4.join(dir, entry.name);
|
|
1228
|
+
if (entry.isDirectory()) {
|
|
1229
|
+
const pruned = prunedDirNames.includes(entry.name) && !named(keep, entry.name);
|
|
1230
|
+
if (pruned || dir === config.root && entry.name === outTop)
|
|
1231
|
+
continue;
|
|
1232
|
+
visit(file, kept || named(keep, entry.name));
|
|
1233
|
+
continue;
|
|
1234
|
+
}
|
|
1235
|
+
if (!entry.isFile() || compiled.has(file) && !named(keep, entry.name))
|
|
1236
|
+
continue;
|
|
1237
|
+
const env = entry.name.startsWith(".env");
|
|
1238
|
+
if (env ? !keep.includes(entry.name) : !kept && !named(keep, entry.name))
|
|
1239
|
+
continue;
|
|
1240
|
+
const relative = toPosixPath(path4.relative(config.root, file));
|
|
1241
|
+
if (!standaloneEntries.has(relative.split("/")[0]))
|
|
1242
|
+
setFile(trace, relative, file);
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
visit(config.root, false);
|
|
1246
|
+
}
|
|
1247
|
+
function compiledSources(config, index) {
|
|
1248
|
+
flushDevModuleCaches();
|
|
1249
|
+
const graph = compiledSourceGraph(config.outPath, config.workspaceRoot);
|
|
1250
|
+
const queue = Object.keys(index.modules).map((key) => releaseSourceFile(key.slice(key.indexOf(":", key.indexOf(":") + 1) + 1), config.root, config.workspaceRoot));
|
|
1251
|
+
if (index.proxy)
|
|
1252
|
+
queue.push(path4.resolve(config.root, index.proxy.file));
|
|
1253
|
+
for (const name of readdirSync2(config.root))
|
|
1254
|
+
if (/^(?:pnext|next|instrumentation)\.config\.|^instrumentation\./.test(name) && scriptFile.test(name))
|
|
1255
|
+
queue.push(path4.join(config.root, name));
|
|
1256
|
+
const compiled = new Set;
|
|
1257
|
+
for (const file of queue) {
|
|
1258
|
+
if (compiled.has(file))
|
|
1259
|
+
continue;
|
|
1260
|
+
compiled.add(file);
|
|
1261
|
+
queue.push(...graph.get(file) ?? []);
|
|
1262
|
+
}
|
|
1263
|
+
for (const css of index.globalCss)
|
|
1264
|
+
compiled.add(path4.resolve(config.root, css));
|
|
1265
|
+
return compiled;
|
|
1266
|
+
}
|
|
1267
|
+
function createPlacer(outPath, cache, claims = new Map) {
|
|
1268
|
+
const packageDir = (root, name) => {
|
|
1269
|
+
const owner = claims.get(name);
|
|
1270
|
+
if (owner === undefined)
|
|
1271
|
+
claims.set(name, root);
|
|
1272
|
+
if (owner === undefined || owner === root)
|
|
1273
|
+
return `node_modules/${name}`;
|
|
1274
|
+
const key = createHash2("sha256").update(root).digest("hex").slice(0, 12);
|
|
1275
|
+
return `node_modules/.pnext/${key}/node_modules/${name}`;
|
|
1276
|
+
};
|
|
1277
|
+
return (file) => {
|
|
1278
|
+
if (isInside(cache, file))
|
|
1279
|
+
return toPosixPath(path4.join("server", path4.relative(cache, file)));
|
|
1280
|
+
if (isInside(outPath, file))
|
|
1281
|
+
return toPosixPath(path4.relative(outPath, file));
|
|
1282
|
+
const framework = !installed(frameworkRoot2) && isInside(frameworkRoot2, file) && !installedIn(frameworkRoot2, file);
|
|
1283
|
+
if (framework) {
|
|
1284
|
+
const dir = packageDir(frameworkRoot2, frameworkPackage.name);
|
|
1285
|
+
return `${dir}/${toPosixPath(path4.relative(frameworkRoot2, file))}`;
|
|
1286
|
+
}
|
|
1287
|
+
const posix = toPosixPath(file);
|
|
1288
|
+
const at = posix.lastIndexOf("/node_modules/");
|
|
1289
|
+
if (at !== -1) {
|
|
1290
|
+
const rest = posix.slice(at + "/node_modules/".length).split("/");
|
|
1291
|
+
const length = rest[0].startsWith("@") ? 2 : 1;
|
|
1292
|
+
const name2 = rest.slice(0, length).join("/");
|
|
1293
|
+
const root2 = `${posix.slice(0, at)}/node_modules/${name2}`;
|
|
1294
|
+
return [packageDir(root2, name2), ...rest.slice(length)].join("/");
|
|
1295
|
+
}
|
|
1296
|
+
const root = packageRoot(path4.dirname(file));
|
|
1297
|
+
const name = root && readPackageName(root);
|
|
1298
|
+
if (!root || !name)
|
|
1299
|
+
throw new Error(`pnext build: cannot place ${file} in the standalone output`);
|
|
1300
|
+
return `${packageDir(root, name)}/${toPosixPath(path4.relative(root, file))}`;
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
var standaloneDirs = new Map;
|
|
1304
|
+
function enclosingStandalone(file, outPath) {
|
|
1305
|
+
const dir = path4.dirname(file);
|
|
1306
|
+
if (dir === path4.dirname(dir))
|
|
1307
|
+
return;
|
|
1308
|
+
if (standaloneDirs.has(dir))
|
|
1309
|
+
return standaloneDirs.get(dir);
|
|
1310
|
+
const own = dir !== outPath && existsSync4(path4.join(dir, "server", "build-index.json")) && existsSync4(path4.join(dir, "server", "entry.js"));
|
|
1311
|
+
const found = own ? dir : enclosingStandalone(dir, outPath);
|
|
1312
|
+
standaloneDirs.set(dir, found);
|
|
1313
|
+
return found;
|
|
1314
|
+
}
|
|
1315
|
+
function addTree(root, dest, trace) {
|
|
1316
|
+
const visit = (dir, seen) => {
|
|
1317
|
+
const real = realpathSync2(dir);
|
|
1318
|
+
if (seen.has(real))
|
|
1319
|
+
return;
|
|
1320
|
+
seen.add(real);
|
|
1321
|
+
for (const name of readdirSync2(dir)) {
|
|
1322
|
+
const file = path4.join(dir, name);
|
|
1323
|
+
const stat = statSync(file, { throwIfNoEntry: false });
|
|
1324
|
+
if (stat?.isDirectory())
|
|
1325
|
+
visit(file, seen);
|
|
1326
|
+
else if (stat?.isFile())
|
|
1327
|
+
setFile(trace, `${dest}/${toPosixPath(path4.relative(root, file))}`, realpathSync2(file));
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
visit(root, new Set);
|
|
1331
|
+
}
|
|
1332
|
+
function installed(file) {
|
|
1333
|
+
return toPosixPath(file).includes("/node_modules/");
|
|
1334
|
+
}
|
|
1335
|
+
function installedIn(root, file) {
|
|
1336
|
+
return path4.relative(root, file).split(path4.sep).includes("node_modules");
|
|
1337
|
+
}
|
|
1338
|
+
var transpilers = new Map;
|
|
1339
|
+
function scanEdges(file, source) {
|
|
1340
|
+
const ext = path4.extname(file);
|
|
1341
|
+
const loader = ext === ".tsx" || ext === ".jsx" ? "tsx" : /\.[cm]?ts$/.test(ext) ? "ts" : "js";
|
|
1342
|
+
let transpiler = transpilers.get(loader);
|
|
1343
|
+
if (!transpiler) {
|
|
1344
|
+
transpiler = new Bun.Transpiler({
|
|
1345
|
+
loader,
|
|
1346
|
+
tsconfig: { compilerOptions: { jsx: "react-jsx", jsxImportSource: "preact" } }
|
|
1347
|
+
});
|
|
1348
|
+
transpilers.set(loader, transpiler);
|
|
1349
|
+
}
|
|
1350
|
+
let imports;
|
|
1351
|
+
try {
|
|
1352
|
+
imports = transpiler.scanImports(source);
|
|
1353
|
+
} catch {
|
|
1354
|
+
return [];
|
|
1355
|
+
}
|
|
1356
|
+
const edges = imports.map((entry) => ({
|
|
1357
|
+
specifier: entry.path,
|
|
1358
|
+
dynamic: entry.kind === "dynamic-import",
|
|
1359
|
+
require: entry.kind === "require-call"
|
|
1360
|
+
}));
|
|
1361
|
+
const refs = importMetaRefs(file, source);
|
|
1362
|
+
for (const url of refs.urls)
|
|
1363
|
+
edges.push({ specifier: url.specifier, dynamic: false, url: true });
|
|
1364
|
+
for (const ref of refs.resolves)
|
|
1365
|
+
edges.push({ specifier: ref.specifier, dynamic: false });
|
|
1366
|
+
if (loader === "tsx")
|
|
1367
|
+
edges.push({ specifier: "preact/jsx-runtime", dynamic: false }, { specifier: "preact/jsx-dev-runtime", dynamic: false });
|
|
1368
|
+
return edges;
|
|
1369
|
+
}
|
|
1370
|
+
var resolved = new Map;
|
|
1371
|
+
function resolveEdge(specifier, from, require2 = false) {
|
|
1372
|
+
if (/^(?:node:|bun:|data:|https?:)/.test(specifier) || specifier === "bun")
|
|
1373
|
+
return;
|
|
1374
|
+
const bare = require2 ? specifier : splitResourceQuery(specifier).path;
|
|
1375
|
+
if (builtins.has(bare))
|
|
1376
|
+
return;
|
|
1377
|
+
const dir = path4.dirname(from);
|
|
1378
|
+
const key = `${dir}\x00${bare}`;
|
|
1379
|
+
if (resolved.has(key))
|
|
1380
|
+
return resolved.get(key);
|
|
1381
|
+
let target;
|
|
1695
1382
|
try {
|
|
1696
|
-
const
|
|
1697
|
-
|
|
1383
|
+
const request = bare.startsWith("file:") ? fileURLToPath2(bare) : bare;
|
|
1384
|
+
target = realpathSync2(Bun.resolveSync(request, dir));
|
|
1385
|
+
if (!statSync(target).isFile())
|
|
1386
|
+
target = undefined;
|
|
1698
1387
|
} catch {
|
|
1699
|
-
|
|
1388
|
+
target = undefined;
|
|
1700
1389
|
}
|
|
1390
|
+
resolved.set(key, target);
|
|
1391
|
+
return target;
|
|
1701
1392
|
}
|
|
1702
|
-
function
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1393
|
+
function frameworkCounterparts(file) {
|
|
1394
|
+
const counterpart = prebundledFile(file);
|
|
1395
|
+
if (counterpart === file)
|
|
1396
|
+
return [];
|
|
1397
|
+
return [counterpart, path4.join(frameworkRoot2, PREBUNDLE_STAMP)];
|
|
1705
1398
|
}
|
|
1706
|
-
|
|
1707
|
-
const
|
|
1708
|
-
const
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1399
|
+
function moduleName(file) {
|
|
1400
|
+
const base = path4.basename(file, path4.extname(file));
|
|
1401
|
+
const chunk = path4.basename(path4.dirname(file)) === "_chunks";
|
|
1402
|
+
return chunk && isInside(path4.join(frameworkRoot2, "dist"), file) ? base.replace(/-[a-z0-9]{8}$/, "") : base;
|
|
1403
|
+
}
|
|
1404
|
+
function packageName(specifier) {
|
|
1405
|
+
if (specifier.startsWith("#"))
|
|
1406
|
+
return;
|
|
1407
|
+
const parts = specifier.split("/");
|
|
1408
|
+
const name = specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
1409
|
+
return name && !builtins.has(name) ? name : undefined;
|
|
1410
|
+
}
|
|
1411
|
+
function addPackageFiles(file, trace, place) {
|
|
1412
|
+
const inStore = installed(file);
|
|
1413
|
+
for (let dir = path4.dirname(file);dir !== path4.dirname(dir); dir = path4.dirname(dir)) {
|
|
1414
|
+
const manifest = path4.join(dir, "package.json");
|
|
1415
|
+
const found = existsSync4(manifest);
|
|
1416
|
+
if (found)
|
|
1417
|
+
setFile(trace, place(manifest), manifest);
|
|
1418
|
+
if (found && dir === frameworkRoot2) {
|
|
1419
|
+
for (const name of ["tsconfig.json", path4.join("config", "ts", "react.json")]) {
|
|
1420
|
+
const extra = path4.join(dir, name);
|
|
1421
|
+
if (existsSync4(extra))
|
|
1422
|
+
setFile(trace, place(extra), extra);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
const parent = path4.basename(path4.dirname(dir));
|
|
1426
|
+
const packageTop = parent === "node_modules" || parent.startsWith("@") && path4.basename(path4.dirname(path4.dirname(dir))) === "node_modules";
|
|
1427
|
+
if (inStore ? packageTop : found && readPackageName(dir))
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
function packageRoot(dir) {
|
|
1432
|
+
for (;dir !== path4.dirname(dir); dir = path4.dirname(dir)) {
|
|
1433
|
+
if (existsSync4(path4.join(dir, "package.json")))
|
|
1434
|
+
return dir;
|
|
1435
|
+
}
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
function readPackageName(dir) {
|
|
1439
|
+
try {
|
|
1440
|
+
return JSON.parse(readFileSync2(path4.join(dir, "package.json"), "utf8")).name;
|
|
1441
|
+
} catch {
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
function relativeSpecifier(fromDir, to) {
|
|
1446
|
+
const relative = toPosixPath(path4.relative(fromDir, to));
|
|
1447
|
+
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
1448
|
+
}
|
|
1449
|
+
function rewriteSpecifiers(file, source, edits) {
|
|
1450
|
+
const refs = importMetaRefs(file, source);
|
|
1451
|
+
const spans = [...moduleSpecifierEdges(source, file), ...refs.urls, ...refs.resolves];
|
|
1452
|
+
const changes = spans.flatMap((span) => {
|
|
1453
|
+
const value = edits.get(span.specifier);
|
|
1454
|
+
return value === undefined ? [] : [{ start: span.start, end: span.end, value: JSON.stringify(value) }];
|
|
1455
|
+
});
|
|
1456
|
+
changes.sort((a, b) => a.start - b.start);
|
|
1457
|
+
return changes.length > 0 ? spliceSource(source, changes) : source;
|
|
1458
|
+
}
|
|
1459
|
+
function urlTarget(specifier, from) {
|
|
1460
|
+
try {
|
|
1461
|
+
const url = new URL(specifier, pathToFileURL(from));
|
|
1462
|
+
return url.protocol === "file:" ? fileURLToPath2(url) : undefined;
|
|
1463
|
+
} catch {
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
function isPackageSpecifier(specifier) {
|
|
1468
|
+
if (specifier === "." || specifier === "..")
|
|
1469
|
+
return false;
|
|
1470
|
+
if (specifier.startsWith("./") || specifier.startsWith("../"))
|
|
1471
|
+
return false;
|
|
1472
|
+
return !path4.isAbsolute(specifier) && !specifier.startsWith("file:");
|
|
1473
|
+
}
|
|
1474
|
+
function createCopier(outPath) {
|
|
1475
|
+
const dirs = new Map;
|
|
1476
|
+
const copied = new Set;
|
|
1477
|
+
const pending = [];
|
|
1478
|
+
const ensureDir = (dir) => {
|
|
1479
|
+
let made = dirs.get(dir);
|
|
1480
|
+
if (!made) {
|
|
1481
|
+
made = mkdir3(dir, { recursive: true });
|
|
1482
|
+
dirs.set(dir, made);
|
|
1483
|
+
}
|
|
1484
|
+
return made;
|
|
1485
|
+
};
|
|
1486
|
+
const copy = (dest, source, contents) => {
|
|
1487
|
+
if (copied.has(dest))
|
|
1488
|
+
return;
|
|
1489
|
+
copied.add(dest);
|
|
1490
|
+
const target = path4.join(outPath, dest);
|
|
1491
|
+
pending.push(ensureDir(path4.dirname(target)).then(async () => {
|
|
1492
|
+
if (contents !== undefined) {
|
|
1493
|
+
if (target !== source)
|
|
1494
|
+
await rm2(target, { force: true });
|
|
1495
|
+
return writeFile(target, contents);
|
|
1496
|
+
}
|
|
1497
|
+
if (target !== source)
|
|
1498
|
+
await copyFile2(source, target, constants2.COPYFILE_FICLONE);
|
|
1499
|
+
}));
|
|
1500
|
+
};
|
|
1501
|
+
return { copy, settle: () => Promise.all(pending) };
|
|
1502
|
+
}
|
|
1503
|
+
function isInside(root, file) {
|
|
1504
|
+
return file === root || file.startsWith(`${root}${path4.sep}`);
|
|
1715
1505
|
}
|
|
1716
1506
|
|
|
1717
1507
|
// src/cli/build.ts
|
|
@@ -1765,9 +1555,10 @@ async function runBuild(root, options, lifecycle) {
|
|
|
1765
1555
|
const warmMode = options.adapter === "vercel" ? "full" : "compile";
|
|
1766
1556
|
const warm = startWarmChild(config, warmMode);
|
|
1767
1557
|
lifecycle.warm = warm;
|
|
1558
|
+
const standalone = startStandalone(config);
|
|
1768
1559
|
const publicFiles = await log.step("prepare output directory", async () => {
|
|
1769
|
-
await ensureEmptyDir(config.
|
|
1770
|
-
return copyPublicDir(config.publicPath, path5.join(config.outPath, "
|
|
1560
|
+
await ensureEmptyDir(config.outRootPath, [devOutSegment, "pnext-pages-compat"]);
|
|
1561
|
+
return copyPublicDir(config.publicPath, path5.join(config.outPath, "static"));
|
|
1771
1562
|
});
|
|
1772
1563
|
const documentCss = Promise.resolve().then(() => buildGlobalCss(config, { verbose })).then(() => buildNotFoundCss(config, { verbose }));
|
|
1773
1564
|
documentCss.catch(() => {
|
|
@@ -1851,7 +1642,7 @@ async function runBuild(root, options, lifecycle) {
|
|
|
1851
1642
|
const clientBundles = log.step(`client bundles (${clientRoutes.length} route${clientRoutes.length === 1 ? "" : "s"})`, () => buildClientEntries({
|
|
1852
1643
|
config,
|
|
1853
1644
|
routes: clientRoutes,
|
|
1854
|
-
outDir: path5.join(config.outPath, "
|
|
1645
|
+
outDir: path5.join(config.outPath, "static", "assets"),
|
|
1855
1646
|
verbose,
|
|
1856
1647
|
hasServerActions: actionSources.length > 0,
|
|
1857
1648
|
pipeline: clientSources
|
|
@@ -1879,7 +1670,7 @@ async function runBuild(root, options, lifecycle) {
|
|
|
1879
1670
|
await clientBundles;
|
|
1880
1671
|
const proxyModule = await proxyBuild;
|
|
1881
1672
|
await partytownLib;
|
|
1882
|
-
await emitStaticClientChunks(config, path5.join(config.outPath, "
|
|
1673
|
+
await emitStaticClientChunks(config, path5.join(config.outPath, "static", "assets"));
|
|
1883
1674
|
if (verbose) {
|
|
1884
1675
|
const sources = sourceCacheStats();
|
|
1885
1676
|
log.log(`source cache \u2014 ${sources.reads} reads, ${sources.hits} shared, ${sources.files} files \xB7 parses ${JSON.stringify(scanFactsStats())}`);
|
|
@@ -2054,7 +1845,7 @@ async function runBuild(root, options, lifecycle) {
|
|
|
2054
1845
|
html: rendered.value.html,
|
|
2055
1846
|
status: rendered.value.status
|
|
2056
1847
|
});
|
|
2057
|
-
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "
|
|
1848
|
+
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "static"), file));
|
|
2058
1849
|
const revalidateSeconds = combineRevalidate(segmentConfig?.revalidate, rendered.revalidateSeconds);
|
|
2059
1850
|
const defaultExpireTime = buildCompat().defaultExpireTimeSeconds();
|
|
2060
1851
|
const effectiveCacheLife = cacheLife ?? (rendered.expireSeconds !== undefined || rendered.staleSeconds !== undefined ? {
|
|
@@ -2116,8 +1907,8 @@ Route (app)`);
|
|
|
2116
1907
|
await emitProxyServerArtifacts(config, proxyModule);
|
|
2117
1908
|
if (config.compat?.next) {
|
|
2118
1909
|
const sourceApp = path5.join(config.appPath, "..", "source-app");
|
|
2119
|
-
const layoutRoot =
|
|
2120
|
-
const hasTopLevelRootLayout = ["tsx", "ts", "jsx", "js"].some((ext) =>
|
|
1910
|
+
const layoutRoot = existsSync5(sourceApp) ? sourceApp : config.appPath;
|
|
1911
|
+
const hasTopLevelRootLayout = ["tsx", "ts", "jsx", "js"].some((ext) => existsSync5(path5.join(layoutRoot, `layout.${ext}`)));
|
|
2121
1912
|
const pseudos = hasTopLevelRootLayout ? ["_not-found.html", "_global-error.html"] : ["_not-found.html"];
|
|
2122
1913
|
for (const pseudo of pseudos) {
|
|
2123
1914
|
if (!(pseudo in staticFiles)) {
|
|
@@ -2147,21 +1938,19 @@ Route (app)`);
|
|
|
2147
1938
|
};
|
|
2148
1939
|
await writeBuildManifest(config.outPath, manifest);
|
|
2149
1940
|
log.log(`wrote manifest.json (${routes.length} route${routes.length === 1 ? "" : "s"})`);
|
|
2150
|
-
await log.step("server entry", () => emitServerEntry(config.outPath));
|
|
2151
1941
|
for (const hook of getBuildExtensions().completeHooks) {
|
|
2152
1942
|
await hook({ config, manifest, log });
|
|
2153
1943
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
clientReferences: [...compiledClientReferenceFiles()]
|
|
2160
|
-
}));
|
|
2161
|
-
}
|
|
2162
|
-
if (!existsSync4(buildIndexFile(config.outPath))) {
|
|
1944
|
+
await log.step("warm module cache", () => warm.finish(log, undefined, {
|
|
1945
|
+
globalCss: globalCssSources(config),
|
|
1946
|
+
clientReferences: [...compiledClientReferenceFiles()]
|
|
1947
|
+
}));
|
|
1948
|
+
if (!existsSync5(buildIndexFile(config.outPath))) {
|
|
2163
1949
|
throw new Error("pnext build: the server compile did not complete (see the error above).");
|
|
2164
1950
|
}
|
|
1951
|
+
await log.step("standalone output", () => writeStandalone(config, standalone));
|
|
1952
|
+
if (options.adapter === "vercel")
|
|
1953
|
+
await log.step("vercel adapter output", () => writeVercelOutput(config, manifest, { verbose }));
|
|
2165
1954
|
throwIfModuleGraphFailed();
|
|
2166
1955
|
const buildDurationMs = performance.now() - startedAt;
|
|
2167
1956
|
const phases = await settleBuildParallelPhases();
|
|
@@ -2207,7 +1996,7 @@ async function logInterceptionPrerenders(config, routes) {
|
|
|
2207
1996
|
return prerenders;
|
|
2208
1997
|
}
|
|
2209
1998
|
function routeFileExportsStaticParams(file) {
|
|
2210
|
-
if (!
|
|
1999
|
+
if (!existsSync5(file))
|
|
2211
2000
|
return false;
|
|
2212
2001
|
const source = readTextSync(file);
|
|
2213
2002
|
return /\bexport\s+(?:async\s+)?function\s+generateStaticParams\b/.test(source) || /\bexport\s+const\s+generateStaticParams\b/.test(source);
|
|
@@ -2226,22 +2015,24 @@ function interceptionDisplayRoute(route, filled) {
|
|
|
2226
2015
|
}
|
|
2227
2016
|
async function writeBuildManifest(outPath, manifest) {
|
|
2228
2017
|
assertManifestServerArtifacts(outPath, manifest);
|
|
2229
|
-
const file =
|
|
2230
|
-
const temporary =
|
|
2231
|
-
await
|
|
2232
|
-
await
|
|
2018
|
+
const file = buildManifestFile(outPath);
|
|
2019
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
2020
|
+
await mkdir4(path5.dirname(file), { recursive: true });
|
|
2021
|
+
await writeFile2(temporary, serializeBuildManifest(manifest));
|
|
2022
|
+
await rename3(temporary, file);
|
|
2233
2023
|
}
|
|
2234
2024
|
function assertManifestServerArtifacts(outPath, manifest) {
|
|
2235
2025
|
const artifacts = [
|
|
2236
2026
|
...manifest.proxyModule ? [manifest.proxyModule] : [],
|
|
2237
2027
|
...manifest.actions?.map((action) => action.modulePath) ?? []
|
|
2238
2028
|
];
|
|
2029
|
+
const outRoot = path5.dirname(outPath);
|
|
2239
2030
|
for (const artifact of artifacts) {
|
|
2240
2031
|
const file = path5.resolve(outPath, artifact);
|
|
2241
|
-
if (
|
|
2032
|
+
if (!file.startsWith(`${outRoot}${path5.sep}`)) {
|
|
2242
2033
|
throw new Error(`Build manifest server artifact escapes output directory: ${artifact}`);
|
|
2243
2034
|
}
|
|
2244
|
-
if (!
|
|
2035
|
+
if (!existsSync5(file)) {
|
|
2245
2036
|
throw new Error(`Build manifest server artifact is missing: ${artifact}`);
|
|
2246
2037
|
}
|
|
2247
2038
|
}
|
|
@@ -2333,7 +2124,7 @@ async function renderShellWithCacheMeta(config, route, render) {
|
|
|
2333
2124
|
var DYNAMIC_EXPIRE_SECONDS = 300;
|
|
2334
2125
|
function routeDeclaresShortLivedCache(route) {
|
|
2335
2126
|
for (const file of route.sourceFiles) {
|
|
2336
|
-
if (!
|
|
2127
|
+
if (!existsSync5(file))
|
|
2337
2128
|
continue;
|
|
2338
2129
|
const source = readTextSync(file);
|
|
2339
2130
|
for (const literal of source.matchAll(/cacheLife\s*\(\s*\{[^}]*\bexpire\s*:\s*([^,}]+)/gs)) {
|
|
@@ -2515,7 +2306,7 @@ async function emitConcreteNextPageArtifacts(config, route, routePath, rendered)
|
|
|
2515
2306
|
function staleTimeFromRouteSources(route) {
|
|
2516
2307
|
let found;
|
|
2517
2308
|
for (const file of route.sourceFiles) {
|
|
2518
|
-
if (!
|
|
2309
|
+
if (!existsSync5(file))
|
|
2519
2310
|
continue;
|
|
2520
2311
|
const source = readTextSync(file);
|
|
2521
2312
|
for (const literal of source.matchAll(/cacheLife\s*\(\s*\{[^}]*\bstale\s*:\s*([^,}]+)/gs)) {
|
|
@@ -2533,7 +2324,7 @@ function staleTimeFromRouteSources(route) {
|
|
|
2533
2324
|
}
|
|
2534
2325
|
function readTextSync(file) {
|
|
2535
2326
|
try {
|
|
2536
|
-
return
|
|
2327
|
+
return existsSync5(file) && statSync2(file).isFile() ? readFileSync3(file, "utf8") : "";
|
|
2537
2328
|
} catch {
|
|
2538
2329
|
return "";
|
|
2539
2330
|
}
|
|
@@ -2791,7 +2582,7 @@ function routeSourcesUseHttpFallback(root, route) {
|
|
|
2791
2582
|
for (const file of route.sourceFiles) {
|
|
2792
2583
|
if (!file.startsWith(root) || file.includes(`${path5.sep}node_modules${path5.sep}`))
|
|
2793
2584
|
continue;
|
|
2794
|
-
if (!
|
|
2585
|
+
if (!existsSync5(file))
|
|
2795
2586
|
continue;
|
|
2796
2587
|
const source = readTextSync(file);
|
|
2797
2588
|
if (/\b(?:notFound|forbidden|unauthorized)\s*\(\s*\)/.test(source))
|
|
@@ -2803,7 +2594,7 @@ function routeSourcesUseRequestApi(root, route) {
|
|
|
2803
2594
|
for (const file of route.sourceFiles) {
|
|
2804
2595
|
if (!file.startsWith(root) || file.includes(`${path5.sep}node_modules${path5.sep}`))
|
|
2805
2596
|
continue;
|
|
2806
|
-
if (!
|
|
2597
|
+
if (!existsSync5(file))
|
|
2807
2598
|
continue;
|
|
2808
2599
|
const source = readTextSync(file).replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
2809
2600
|
if (/\b(?:connection|cookies|headers|draftMode)\s*\(\s*\)/.test(source))
|
|
@@ -2813,7 +2604,7 @@ function routeSourcesUseRequestApi(root, route) {
|
|
|
2813
2604
|
}
|
|
2814
2605
|
function routeSourcesHaveDynamicHead(route) {
|
|
2815
2606
|
for (const file of route.sourceFiles) {
|
|
2816
|
-
if (!
|
|
2607
|
+
if (!existsSync5(file))
|
|
2817
2608
|
continue;
|
|
2818
2609
|
const source = readTextSync(file);
|
|
2819
2610
|
const match = /export\s+(?:async\s+)?function\s+(?:generateMetadata|generateViewport)\s*\([^)]*\)\s*(?::[^{]+)?\{/.exec(source);
|
|
@@ -2890,11 +2681,11 @@ async function renderNotFoundDocuments({
|
|
|
2890
2681
|
};
|
|
2891
2682
|
await documentCss;
|
|
2892
2683
|
if (await shouldBuildGlobalNotFound(config)) {
|
|
2893
|
-
await log.step("global not-found", async () => writeText(path5.join(config.outPath, "
|
|
2684
|
+
await log.step("global not-found", async () => writeText(path5.join(config.outPath, "static", "404.html"), await render()));
|
|
2894
2685
|
}
|
|
2895
2686
|
if (!config.compat?.next)
|
|
2896
2687
|
return;
|
|
2897
|
-
if (
|
|
2688
|
+
if (existsSync5(path5.join(config.outPath, "static", "404.html")))
|
|
2898
2689
|
return;
|
|
2899
2690
|
return defaultNotFoundDocument();
|
|
2900
2691
|
}
|
|
@@ -2902,7 +2693,7 @@ async function shouldBuildGlobalNotFound(config) {
|
|
|
2902
2693
|
const file = ["tsx", "ts", "jsx", "js"].flatMap((ext) => [
|
|
2903
2694
|
path5.join(config.appPath, `global-not-found.${ext}`),
|
|
2904
2695
|
path5.join(config.appPath, `not-found.${ext}`)
|
|
2905
|
-
]).find((candidate) =>
|
|
2696
|
+
]).find((candidate) => existsSync5(candidate));
|
|
2906
2697
|
if (!file)
|
|
2907
2698
|
return false;
|
|
2908
2699
|
return !/\bexport\s+const\s+dynamic\s*=\s*['"]force-dynamic['"]/.test(await readText(file));
|
|
@@ -2911,21 +2702,21 @@ async function emitProxyServerArtifacts(config, proxyModule) {
|
|
|
2911
2702
|
if (!config.compat?.next || !proxyModule)
|
|
2912
2703
|
return;
|
|
2913
2704
|
const compiled = path5.resolve(config.outPath, proxyModule);
|
|
2914
|
-
if (!
|
|
2705
|
+
if (!existsSync5(compiled))
|
|
2915
2706
|
return;
|
|
2916
2707
|
const serverDir = path5.join(config.root, ".next", "server");
|
|
2917
2708
|
await mkdir4(serverDir, { recursive: true });
|
|
2918
2709
|
const middlewareFile = path5.join(serverDir, "middleware.js");
|
|
2919
|
-
await
|
|
2920
|
-
const files = ["middleware.js"].filter((name) =>
|
|
2921
|
-
await
|
|
2710
|
+
await copyFile3(compiled, middlewareFile);
|
|
2711
|
+
const files = ["middleware.js"].filter((name) => existsSync5(path5.join(serverDir, name)));
|
|
2712
|
+
await writeFile2(path5.join(serverDir, "middleware.js.nft.json"), `${JSON.stringify({ version: 1, files })}
|
|
2922
2713
|
`);
|
|
2923
2714
|
}
|
|
2924
2715
|
async function emitNextNotFoundArtifacts(config, fallback404) {
|
|
2925
2716
|
if (!config.compat?.next)
|
|
2926
2717
|
return;
|
|
2927
|
-
const source = path5.join(config.outPath, "
|
|
2928
|
-
const html =
|
|
2718
|
+
const source = path5.join(config.outPath, "static", "404.html");
|
|
2719
|
+
const html = existsSync5(source) ? readFileSync3(source, "utf8") : fallback404;
|
|
2929
2720
|
if (html === undefined)
|
|
2930
2721
|
return;
|
|
2931
2722
|
const serverDir = path5.join(config.root, ".next", "server");
|
|
@@ -2933,21 +2724,21 @@ async function emitNextNotFoundArtifacts(config, fallback404) {
|
|
|
2933
2724
|
const notFoundDir = path5.join(serverDir, "app", "_not-found");
|
|
2934
2725
|
await mkdir4(pagesDir, { recursive: true });
|
|
2935
2726
|
await mkdir4(notFoundDir, { recursive: true });
|
|
2936
|
-
await
|
|
2937
|
-
await
|
|
2938
|
-
await
|
|
2727
|
+
await writeFile2(path5.join(pagesDir, "404.html"), html);
|
|
2728
|
+
await writeFile2(path5.join(serverDir, "app", "_not-found.html"), html);
|
|
2729
|
+
await writeFile2(path5.join(serverDir, "app", "_not-found.rsc"), html);
|
|
2939
2730
|
const pagesManifestFile = path5.join(serverDir, "pages-manifest.json");
|
|
2940
2731
|
let pagesManifest = {};
|
|
2941
2732
|
try {
|
|
2942
|
-
pagesManifest = JSON.parse(
|
|
2733
|
+
pagesManifest = JSON.parse(readFileSync3(pagesManifestFile, "utf8"));
|
|
2943
2734
|
} catch {}
|
|
2944
2735
|
pagesManifest["/404"] = "pages/404.html";
|
|
2945
|
-
await
|
|
2736
|
+
await writeFile2(pagesManifestFile, `${JSON.stringify(pagesManifest, null, 2)}
|
|
2946
2737
|
`);
|
|
2947
2738
|
const clientReferenceManifest = "page_client-reference-manifest.js";
|
|
2948
|
-
await
|
|
2739
|
+
await writeFile2(path5.join(notFoundDir, clientReferenceManifest), `self.__RSC_MANIFEST={}
|
|
2949
2740
|
`);
|
|
2950
|
-
await
|
|
2741
|
+
await writeFile2(path5.join(notFoundDir, "page.js.nft.json"), `${JSON.stringify({ version: 1, files: [clientReferenceManifest] }, null, 2)}
|
|
2951
2742
|
`);
|
|
2952
2743
|
}
|
|
2953
2744
|
async function collectStaticModuleMetadata(config, routes) {
|
|
@@ -2959,7 +2750,7 @@ async function collectStaticModuleMetadata(config, routes) {
|
|
|
2959
2750
|
if (route.kind !== "page")
|
|
2960
2751
|
continue;
|
|
2961
2752
|
for (const file of findLayouts(config.appPath, route.file)) {
|
|
2962
|
-
if (
|
|
2753
|
+
if (existsSync5(file))
|
|
2963
2754
|
files.add(file);
|
|
2964
2755
|
}
|
|
2965
2756
|
files.add(route.file);
|
|
@@ -2994,8 +2785,8 @@ async function collectStaticRouteMetadata(config, routes, staticMetadataFiles) {
|
|
|
2994
2785
|
for (const params of paramSets) {
|
|
2995
2786
|
const routePath = fillRoutePath(route.route, params);
|
|
2996
2787
|
const base = route.interception ? staticMetadataForRouteFromFiles(staticMetadataFiles, config.appPath, route.file, routePath) : staticMetadataForPathFromFiles(staticMetadataFiles, routePath);
|
|
2997
|
-
const
|
|
2998
|
-
metadata[staticRouteMetadataKey(routePath)] =
|
|
2788
|
+
const resolved2 = await withDynamicMetadataRoutes(base, config.appPath, route.file, routePath, (file) => importMetadataModule(config, file));
|
|
2789
|
+
metadata[staticRouteMetadataKey(routePath)] = resolved2;
|
|
2999
2790
|
}
|
|
3000
2791
|
}
|
|
3001
2792
|
return metadata;
|
|
@@ -3052,10 +2843,10 @@ async function buildStaticRouteHandler(config, route, options = {}) {
|
|
|
3052
2843
|
const body = await settleBeforeNextTask(response.clone().arrayBuffer());
|
|
3053
2844
|
if (!body)
|
|
3054
2845
|
continue;
|
|
3055
|
-
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "
|
|
2846
|
+
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "static"), file));
|
|
3056
2847
|
if (!skipPhysicalWrite) {
|
|
3057
2848
|
await mkdir4(path5.dirname(file), { recursive: true });
|
|
3058
|
-
await
|
|
2849
|
+
await writeFile2(file, new Uint8Array(body));
|
|
3059
2850
|
}
|
|
3060
2851
|
const revalidateSeconds = combineRevalidate(route.segmentConfig?.revalidate, rendered.revalidateSeconds);
|
|
3061
2852
|
staticFiles[relative] = {
|
|
@@ -3087,7 +2878,7 @@ function settleBeforeNextTask(value) {
|
|
|
3087
2878
|
});
|
|
3088
2879
|
}
|
|
3089
2880
|
async function handlerHasEntirelyCachedIo(route) {
|
|
3090
|
-
if (route.synthetic || !
|
|
2881
|
+
if (route.synthetic || !existsSync5(route.file))
|
|
3091
2882
|
return false;
|
|
3092
2883
|
const source = await readText(route.file);
|
|
3093
2884
|
if (route.metadataRoute && metadataDefaultUsesCache(source))
|
|
@@ -3128,7 +2919,7 @@ function metadataDefaultUsesCache(source) {
|
|
|
3128
2919
|
return /\bexport\s+default\s+(?:async\s+)?function\b[^(]*\([^)]*\)\s*(?::[^{]*)?\{\s*(?:\/\/[^\n]*\n\s*|\/\*[\s\S]*?\*\/\s*)*['"]use cache['"]/.test(source);
|
|
3129
2920
|
}
|
|
3130
2921
|
async function usesUnstableCache(route) {
|
|
3131
|
-
if (route.synthetic || !
|
|
2922
|
+
if (route.synthetic || !existsSync5(route.file))
|
|
3132
2923
|
return false;
|
|
3133
2924
|
const source = await readText(route.file);
|
|
3134
2925
|
const localNames = [];
|
|
@@ -3154,7 +2945,7 @@ async function staticHandlerDynamicUsage(route) {
|
|
|
3154
2945
|
if (route.segmentConfig?.dynamic === "force-static" || route.segmentConfig?.dynamic === "error") {
|
|
3155
2946
|
return;
|
|
3156
2947
|
}
|
|
3157
|
-
if (route.synthetic || !
|
|
2948
|
+
if (route.synthetic || !existsSync5(route.file))
|
|
3158
2949
|
return;
|
|
3159
2950
|
const source = await readText(route.file);
|
|
3160
2951
|
if (/\b(?:request|req)\.url\b/.test(source))
|
|
@@ -3262,8 +3053,8 @@ function routeMetadataImageFiles(appPath, routeFile) {
|
|
|
3262
3053
|
let dir = path5.dirname(routeFile);
|
|
3263
3054
|
const root = path5.resolve(appPath);
|
|
3264
3055
|
while (dir.startsWith(root)) {
|
|
3265
|
-
if (
|
|
3266
|
-
for (const entry of
|
|
3056
|
+
if (existsSync5(dir)) {
|
|
3057
|
+
for (const entry of readdirSync3(dir)) {
|
|
3267
3058
|
if (/^(opengraph-image|twitter-image)\d*\.(tsx?|jsx?|mjs|png|jpe?g|gif|webp|svg)$/.test(entry)) {
|
|
3268
3059
|
return true;
|
|
3269
3060
|
}
|
|
@@ -3284,7 +3075,7 @@ async function copyStaticMetadataFiles(config, staticFiles, metadataFiles = disc
|
|
|
3284
3075
|
continue;
|
|
3285
3076
|
}
|
|
3286
3077
|
await mkdir4(path5.dirname(target), { recursive: true });
|
|
3287
|
-
await
|
|
3078
|
+
await copyFile3(metadataFile.file, target);
|
|
3288
3079
|
staticFiles[metadataFile.outputPath] = {
|
|
3289
3080
|
status: 200,
|
|
3290
3081
|
headers: [
|
|
@@ -3296,7 +3087,7 @@ async function copyStaticMetadataFiles(config, staticFiles, metadataFiles = disc
|
|
|
3296
3087
|
}
|
|
3297
3088
|
function staticHtmlPath(outPath, routePath, flatLayout = false) {
|
|
3298
3089
|
if (routePath === "/")
|
|
3299
|
-
return path5.join(outPath, "
|
|
3090
|
+
return path5.join(outPath, "static", "index.html");
|
|
3300
3091
|
const normalized = routePath.replace(/^\/|\/$/g, "");
|
|
3301
3092
|
if (flatLayout)
|
|
3302
3093
|
return safePublicPath(outPath, `${normalized}.html`);
|
|
@@ -3360,13 +3151,13 @@ function staticRouteHandlerPath(outPath, routePath) {
|
|
|
3360
3151
|
return safePublicPath(outPath, routePath.replace(/^\/+/, "") || "index");
|
|
3361
3152
|
}
|
|
3362
3153
|
function staticOutputCollision(outPath, file) {
|
|
3363
|
-
const publicPath = path5.join(outPath, "
|
|
3364
|
-
if (
|
|
3154
|
+
const publicPath = path5.join(outPath, "static");
|
|
3155
|
+
if (existsSync5(file) && statSync2(file).isDirectory()) {
|
|
3365
3156
|
return `${toPosixPath(path5.relative(publicPath, file))} already exists as a directory`;
|
|
3366
3157
|
}
|
|
3367
3158
|
let dir = path5.dirname(file);
|
|
3368
3159
|
while (dir !== publicPath && dir !== path5.dirname(dir)) {
|
|
3369
|
-
if (
|
|
3160
|
+
if (existsSync5(dir)) {
|
|
3370
3161
|
if (!statSync2(dir).isDirectory()) {
|
|
3371
3162
|
return `${toPosixPath(path5.relative(publicPath, dir))} already exists as a file`;
|
|
3372
3163
|
}
|
|
@@ -3407,8 +3198,8 @@ async function requestApiBailoutReason(route) {
|
|
|
3407
3198
|
function ownSourceFiles(route) {
|
|
3408
3199
|
const frameworkRoot3 = path5.resolve(fileURLToPath3(Bun.pathToFileURL(__PNEXT_PACKAGE_ROOT__ + "/src/cli/build.ts").href), "..", "..");
|
|
3409
3200
|
return route.sourceFiles.filter((file) => {
|
|
3410
|
-
const
|
|
3411
|
-
return !
|
|
3201
|
+
const resolved2 = path5.resolve(file);
|
|
3202
|
+
return !resolved2.includes(`${path5.sep}node_modules${path5.sep}`) && !resolved2.startsWith(frameworkRoot3 + path5.sep);
|
|
3412
3203
|
});
|
|
3413
3204
|
}
|
|
3414
3205
|
async function schedulesDeferredWork(route) {
|
|
@@ -3501,7 +3292,7 @@ function realFilePath(file) {
|
|
|
3501
3292
|
}
|
|
3502
3293
|
}
|
|
3503
3294
|
function safePublicPath(outPath, ...segments) {
|
|
3504
|
-
const publicPath = path5.join(outPath, "
|
|
3295
|
+
const publicPath = path5.join(outPath, "static");
|
|
3505
3296
|
const file = path5.join(publicPath, ...segments);
|
|
3506
3297
|
const relative = path5.relative(publicPath, file);
|
|
3507
3298
|
if (relative.startsWith("..") || path5.isAbsolute(relative)) {
|
|
@@ -3519,7 +3310,7 @@ async function copyPartytownLib(config) {
|
|
|
3519
3310
|
console.warn("pnext build: experimental.nextScriptWorkers is enabled but no Partytown package was found (@qwik.dev/partytown or @builder.io/partytown); worker scripts will 404 the library until it is installed");
|
|
3520
3311
|
return;
|
|
3521
3312
|
}
|
|
3522
|
-
const target = path5.join(config.outPath, "
|
|
3313
|
+
const target = path5.join(config.outPath, "static", "_next", "static", "~partytown");
|
|
3523
3314
|
await mkdir4(target, { recursive: true });
|
|
3524
3315
|
await copyPublicDir(libDir, target);
|
|
3525
3316
|
}
|
|
@@ -3529,7 +3320,7 @@ function resolvePartytownLibDir(root) {
|
|
|
3529
3320
|
try {
|
|
3530
3321
|
const pkgJson = requireFromRoot.resolve(`${pkg}/package.json`);
|
|
3531
3322
|
const libDir = path5.join(path5.dirname(pkgJson), "lib");
|
|
3532
|
-
if (
|
|
3323
|
+
if (existsSync5(libDir) && statSync2(libDir).isDirectory())
|
|
3533
3324
|
return libDir;
|
|
3534
3325
|
} catch {}
|
|
3535
3326
|
}
|
|
@@ -3540,7 +3331,7 @@ async function copyPublicDir(from, to) {
|
|
|
3540
3331
|
for (const relative of files) {
|
|
3541
3332
|
const target = path5.join(to, relative);
|
|
3542
3333
|
await mkdir4(path5.dirname(target), { recursive: true });
|
|
3543
|
-
await
|
|
3334
|
+
await copyFile3(path5.join(from, relative), target);
|
|
3544
3335
|
}
|
|
3545
3336
|
return files;
|
|
3546
3337
|
}
|