@wular/pnext 0.1.7 → 0.1.9
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-fhv4dt06.js} +7 -5
- package/dist/server/_chunks/{analyze-arswqe6s.js → analyze-09kx9q6r.js} +17 -13
- package/dist/server/_chunks/{boot-af0mv3dy.js → boot-8aj7efqk.js} +13 -11
- package/dist/server/_chunks/{build-spy3dxp4.js → build-jda155c9.js} +7 -5
- package/dist/server/_chunks/{build-tier-m7yvqz61.js → build-tier-qrkpfsk1.js} +59 -75
- package/dist/server/_chunks/{build-t9h0hec3.js → build-wspv5h60.js} +1004 -1191
- package/dist/server/_chunks/{compile-53j02j27.js → compile-040r79gj.js} +2 -2
- package/dist/server/_chunks/{config-n2z7yxps.js → config-7h84p6q8.js} +6 -4
- package/dist/server/_chunks/{config-1yzwexq6.js → config-d4hqyygy.js} +12 -3
- package/dist/server/_chunks/{create-meec9hs6.js → create-skj8wzt5.js} +4 -3
- package/dist/server/_chunks/{dev-fjmqg6en.js → dev-pennd36n.js} +2 -2
- package/dist/server/_chunks/{generate-n9sh6hzt.js → generate-d8vb1d21.js} +5 -4
- package/dist/server/_chunks/{index-eeaanp2e.js → index-0qt2vapb.js} +3 -3
- package/dist/server/_chunks/{index-91x12ykq.js → index-0r5eqfc7.js} +6 -1
- package/dist/server/_chunks/{index-9ych9ma8.js → index-0wm2p3ks.js} +2 -2
- package/dist/server/_chunks/{index-357na4a8.js → index-141vcwk6.js} +1 -1
- package/dist/server/_chunks/{index-2dv4y4wd.js → index-1y0cesgn.js} +16 -10
- package/dist/server/_chunks/{index-ytjvpbm2.js → index-26gwrm07.js} +3 -3
- package/dist/server/_chunks/{index-8k7pfejn.js → index-3r6qpe8a.js} +7 -7
- package/dist/server/_chunks/{index-rn8dyr1f.js → index-42fef2rv.js} +8 -48
- package/dist/server/_chunks/{index-ncnes8c6.js → index-47gx7trn.js} +2 -2
- package/dist/server/_chunks/{index-20ppawv7.js → index-4qsce64w.js} +3 -3
- package/dist/server/_chunks/{index-1011cscr.js → index-4vf121ws.js} +61 -29
- package/dist/server/_chunks/{index-cf4rvxv6.js → index-52k54ykj.js} +1 -1
- package/dist/server/_chunks/{index-nyrba2kr.js → index-53fnn598.js} +11 -11
- package/dist/server/_chunks/{index-4hgjrqh7.js → index-6tb725m8.js} +2 -2
- package/dist/server/_chunks/{index-3xbr4eyv.js → index-912z4mfx.js} +3 -3
- package/dist/server/_chunks/{index-sjpckxqn.js → index-9f49w76j.js} +1 -1
- package/dist/server/_chunks/{index-jepjvcrf.js → index-aarf1brn.js} +1 -1
- package/dist/server/_chunks/{index-9n2914ww.js → index-akkrvjn6.js} +1 -1
- package/dist/server/_chunks/index-bzd2ef7t.js +10 -0
- package/dist/server/_chunks/{index-sv8m6789.js → index-cqcwwxfp.js} +5 -5
- package/dist/server/_chunks/{index-yz54pxrh.js → index-d1jsmhhk.js} +4 -9
- package/dist/server/_chunks/{index-vvmmknm1.js → index-da0fphj0.js} +19 -15
- package/dist/server/_chunks/{index-sctcgyvv.js → index-drwv61cc.js} +2 -2
- package/dist/server/_chunks/{index-z84ab1w0.js → index-e176wk6x.js} +3 -3
- package/dist/server/_chunks/{index-9hx2641q.js → index-entm8bmz.js} +1 -1
- package/dist/server/_chunks/index-fpghsgb4.js +352 -0
- package/dist/server/_chunks/{index-jx7bqvw1.js → index-hr63fvzn.js} +1 -1
- package/dist/server/_chunks/{index-eajaspjk.js → index-j0m1jxqa.js} +1 -1
- package/dist/server/_chunks/index-jbj7ehef.js +50 -0
- package/dist/server/_chunks/{index-egykcqg3.js → index-jexsy9a8.js} +1 -1
- package/dist/server/_chunks/{index-fkp000p1.js → index-jjppzw0s.js} +2 -2
- package/dist/server/_chunks/index-jt8e1pje.js +12 -0
- package/dist/server/_chunks/{index-ggk2j965.js → index-kpdph69z.js} +56 -50
- package/dist/server/_chunks/{index-6e4fqv30.js → index-m63czgq5.js} +2 -0
- package/dist/server/_chunks/{index-c0g2wf3z.js → index-md5jchzy.js} +1 -1
- package/dist/server/_chunks/{index-tvqkq6e6.js → index-n814hcky.js} +1 -1
- package/dist/server/_chunks/{index-06nyqntx.js → index-q3r9z8mq.js} +1 -1
- package/dist/server/_chunks/{index-4q2gbfwk.js → index-qjrh7w2g.js} +2 -2
- package/dist/server/_chunks/{index-3b3at80h.js → index-s61bx2aj.js} +6 -3
- package/dist/server/_chunks/{index-ym67zqxp.js → index-tf4j19ge.js} +1 -1
- package/dist/server/_chunks/{index-qn4z5s3c.js → index-typcbcsv.js} +3 -3
- package/dist/server/_chunks/{index-p77b4kcx.js → index-veycp46e.js} +1 -1
- package/dist/server/_chunks/{index-11sfk4hb.js → index-vmr35jjw.js} +1 -1
- package/dist/server/_chunks/{index-kq8kpzye.js → index-vqs3rebe.js} +3 -3
- package/dist/server/_chunks/{index-danncfhy.js → index-wm36rj4v.js} +1 -1
- package/dist/server/_chunks/{index-z4z9zv3b.js → index-x9c55pzy.js} +141 -3
- package/dist/server/_chunks/{index-y2jr2n72.js → index-xrsg0041.js} +4 -4
- package/dist/server/_chunks/{index-k1g3epw0.js → index-xs3411qh.js} +10 -10
- package/dist/server/_chunks/{index-0374j2b9.js → index-y4d02znn.js} +1 -1
- package/dist/server/_chunks/{index-wpfhfbs4.js → index-y71a76dn.js} +4 -4
- package/dist/server/_chunks/{index-qm6kmhqs.js → index-y7mzvq2q.js} +1 -1
- package/dist/server/_chunks/{index-hkdfj58q.js → index-y9bygr95.js} +1 -1
- package/dist/server/_chunks/{index-3tf1xjsp.js → index-yghskk8w.js} +11 -11
- package/dist/server/_chunks/{index-5gyr4emz.js → index-yzcpr3yw.js} +4 -4
- package/dist/server/_chunks/{index-x93hv0sc.js → index-zedjt25v.js} +23 -10
- package/dist/server/_chunks/{index-tq0pc7eg.js → index-zfrwq472.js} +3 -3
- package/dist/server/_chunks/{loader-7yw0j98z.js → loader-w1e0n5sm.js} +12 -10
- package/dist/server/_chunks/{modules-jn8bmbn8.js → modules-730j14cm.js} +14 -12
- package/dist/server/_chunks/{pipeline-yy9jhydf.js → pipeline-yjdnwbhm.js} +25 -21
- package/dist/server/_chunks/{production-jar9ztm3.js → production-1xe9b7wd.js} +14 -3
- package/dist/server/_chunks/{proxy-config-j84dgksn.js → proxy-config-9r9e0jvn.js} +7 -5
- package/dist/server/_chunks/{proxy-w1d0wmsn.js → proxy-pnevsbfd.js} +12 -10
- package/dist/server/_chunks/{router-k1reahfn.js → router-rzge0vz8.js} +10 -7
- package/dist/server/_chunks/{routes-2s277fc6.js → routes-0x8wjvcj.js} +12 -10
- package/dist/server/_chunks/{run-pvd8bs1t.js → run-tk90r3ac.js} +5 -4
- package/dist/server/_chunks/{server-mt4a994c.js → server-gev78ejc.js} +38 -34
- package/dist/server/_chunks/{tsconfig-defaults-1nb3308g.js → tsconfig-defaults-qe9wd6ne.js} +5 -4
- package/dist/server/_chunks/{typegen-0qr0459b.js → typegen-0yw8sry8.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 +101 -1265
- 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 +727 -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-53fnn598.js";
|
|
14
14
|
import {
|
|
15
15
|
writeTypegen
|
|
16
|
-
} from "./index-
|
|
16
|
+
} from "./index-y71a76dn.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-3r6qpe8a.js";
|
|
27
27
|
import {
|
|
28
|
-
compiledSpecifiersManifestSuffix,
|
|
29
28
|
devServerModuleHref,
|
|
30
29
|
resetModuleGraphFailure,
|
|
31
30
|
setEmitCompiledSpecifiersManifest,
|
|
32
31
|
setReleaseCompile
|
|
33
|
-
} from "./index-
|
|
32
|
+
} from "./index-4vf121ws.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-da0fphj0.js";
|
|
41
|
+
import"./index-0r5eqfc7.js";
|
|
42
|
+
import"./index-n814hcky.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-yghskk8w.js";
|
|
65
65
|
import {
|
|
66
66
|
findLayouts
|
|
67
|
-
} from "./index-
|
|
67
|
+
} from "./index-aarf1brn.js";
|
|
68
68
|
import {
|
|
69
69
|
findProxyFile,
|
|
70
70
|
proxyExternalLoadTarget,
|
|
71
71
|
proxyRoutePatterns,
|
|
72
72
|
validateProxyFiles
|
|
73
|
-
} from "./index-
|
|
73
|
+
} from "./index-vqs3rebe.js";
|
|
74
74
|
import {
|
|
75
75
|
serverBundleTargetForRuntime,
|
|
76
76
|
throwIfModuleGraphFailed
|
|
77
|
-
} from "./index-
|
|
78
|
-
import"./index-
|
|
77
|
+
} from "./index-912z4mfx.js";
|
|
78
|
+
import"./index-42fef2rv.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-1y0cesgn.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-xrsg0041.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-md5jchzy.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-jjppzw0s.js";
|
|
113
114
|
import {
|
|
114
115
|
interceptionMarkerLevels
|
|
115
|
-
} from "./index-
|
|
116
|
+
} from "./index-veycp46e.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-4qsce64w.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-yzcpr3yw.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-zedjt25v.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-fpghsgb4.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,692 +261,140 @@ 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
|
-
return [{ src: `^/_next/static/(${alternation})(/.*)?$`, dest: "/assets/$1$2", continue: true }];
|
|
545
|
-
}
|
|
546
|
-
function readdirSyncSafe(dir) {
|
|
547
|
-
return existsSync2(dir) ? readdirSync(dir) : [];
|
|
548
|
-
}
|
|
549
|
-
async function proxyRoutes(config) {
|
|
550
|
-
const proxyFile = findProxyFile(config);
|
|
551
|
-
if (!proxyFile)
|
|
552
|
-
return [];
|
|
553
|
-
const proxyModule = await import(pathToFileHref(proxyFile));
|
|
554
|
-
return [...proxyRoutePatterns(proxyModule.config), "^.*(?:%|//).*$"].map((src) => ({
|
|
555
|
-
src,
|
|
556
|
-
dest: `/${SERVER_FUNCTION}`
|
|
557
|
-
}));
|
|
558
|
-
}
|
|
559
|
-
async function writeServerFunction(config, manifest, functionPath, warmedModules, warmSettled, log) {
|
|
560
|
-
const workspaceRoot = config.workspaceRoot;
|
|
561
|
-
await mkdir(functionPath, { recursive: true });
|
|
562
|
-
const pack = packRules(config);
|
|
563
|
-
const framework = await resolveFrameworkPackage(workspaceRoot);
|
|
564
|
-
const { root: pnextRoot, inWorkspace: pnextInWorkspace, targetRel: pnextTargetRel } = framework;
|
|
565
|
-
const release = releaseEntries(config, manifest);
|
|
566
|
-
const prebundle = release ? readPrebundleStamp(pnextRoot, frameworkFingerprint()) : undefined;
|
|
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}`)};
|
|
615
|
-
|
|
616
|
-
const handlerPromise = createRequestHandler({
|
|
617
|
-
root: path.join(import.meta.dirname, ${JSON.stringify(appRel)}),
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
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
|
-
}
|
|
269
|
+
return [{ src: `^/_next/static/(${alternation})(/.*)?$`, dest: "/assets/$1$2", continue: true }];
|
|
854
270
|
}
|
|
855
|
-
function
|
|
856
|
-
|
|
857
|
-
return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
|
|
271
|
+
function readdirSyncSafe(dir) {
|
|
272
|
+
return existsSync(dir) ? readdirSync(dir) : [];
|
|
858
273
|
}
|
|
859
|
-
function
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
274
|
+
async function proxyRoutes(config) {
|
|
275
|
+
const proxyFile = findProxyFile(config);
|
|
276
|
+
if (!proxyFile)
|
|
277
|
+
return [];
|
|
278
|
+
const proxyModule = await import(pathToFileHref(proxyFile));
|
|
279
|
+
return [...proxyRoutePatterns(proxyModule.config), "^.*(?:%|//).*$"].map((src) => ({
|
|
280
|
+
src,
|
|
281
|
+
dest: `/${SERVER_FUNCTION}`
|
|
282
|
+
}));
|
|
863
283
|
}
|
|
864
|
-
function
|
|
865
|
-
|
|
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';
|
|
292
|
+
|
|
293
|
+
const handlerPromise = createRequestHandler({ root: import.meta.dirname });
|
|
294
|
+
|
|
295
|
+
async function handler(request) {
|
|
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
|
-
}
|
|
909
|
-
if (char === '"') {
|
|
910
|
-
inString = true;
|
|
911
|
-
result += char;
|
|
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
333
|
}
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
return
|
|
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)
|
|
353
|
+
for (const [name, json] of manifests) {
|
|
354
|
+
if (!(json.os ?? json.cpu) || matchesFunctionPlatform(json))
|
|
1065
355
|
continue;
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
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 });
|
|
1075
|
-
continue;
|
|
1076
|
-
}
|
|
1077
|
-
packageDirs.set(name, dir);
|
|
1078
|
-
if (!packageJson)
|
|
1079
|
-
continue;
|
|
1080
|
-
const expand = async (packageDir, packageJson2, target) => {
|
|
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,9 +474,9 @@ 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
|
-
return routeSources(patterns, (source) => `^/(?:${source})
|
|
479
|
+
return routeSources(patterns, (source) => `^/(?:${source})$`).map((src) => ({
|
|
1383
480
|
src,
|
|
1384
481
|
headers: { "cache-control": immutableCacheControl },
|
|
1385
482
|
continue: true,
|
|
@@ -1389,13 +486,13 @@ async function immutableAssetRoutes(publicDir, publicAssets = []) {
|
|
|
1389
486
|
function immutableAssetPatterns(built, publicAssets) {
|
|
1390
487
|
const appDirs = new Set(publicAssets.flatMap(ancestorDirs));
|
|
1391
488
|
const prefixes = [...new Set(immutableAssetPrefixes())];
|
|
1392
|
-
const patterns = prefixes.filter((prefix) => !appDirs.has(prefix)).map(escapeRegex);
|
|
489
|
+
const patterns = prefixes.filter((prefix) => !appDirs.has(prefix)).map((prefix) => `${escapeRegex(prefix)}.+`);
|
|
1393
490
|
for (const relative of built) {
|
|
1394
491
|
const prefix = prefixes.find((prefix2) => relative.startsWith(prefix2));
|
|
1395
492
|
if (!prefix || !appDirs.has(prefix))
|
|
1396
493
|
continue;
|
|
1397
494
|
const dir = ancestorDirs(relative).find((dir2) => dir2.length > prefix.length && !appDirs.has(dir2));
|
|
1398
|
-
patterns.push(dir ? escapeRegex(requestPath(dir)) :
|
|
495
|
+
patterns.push(dir ? `${escapeRegex(requestPath(dir))}.+` : escapeRegex(requestPath(relative)));
|
|
1399
496
|
}
|
|
1400
497
|
return [...new Set(patterns)];
|
|
1401
498
|
}
|
|
@@ -1437,33 +534,199 @@ function staticHeaderRoutes(staticFiles) {
|
|
|
1437
534
|
groups.set(key, group);
|
|
1438
535
|
group.patterns.push(servedPathPattern(relative));
|
|
1439
536
|
}
|
|
1440
|
-
return [...groups.values()].flatMap(({ headers, patterns }) => routeSources(patterns, (source) => `^/(?:${source})$`).map((src) => ({
|
|
1441
|
-
src,
|
|
1442
|
-
methods: ["GET", "HEAD"],
|
|
1443
|
-
headers,
|
|
1444
|
-
continue: true,
|
|
1445
|
-
important: true
|
|
1446
|
-
})));
|
|
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
|
+
}
|
|
1447
649
|
}
|
|
1448
|
-
function
|
|
1449
|
-
const
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
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();
|
|
1456
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);
|
|
1457
677
|
}
|
|
1458
|
-
|
|
678
|
+
fireOnCompiled?.();
|
|
679
|
+
return compiled();
|
|
1459
680
|
}
|
|
1460
|
-
function
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
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);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
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}`;
|
|
725
|
+
}
|
|
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,581 @@ 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
|
+
const stat = statSync(target2, { throwIfNoEntry: false });
|
|
1155
|
+
if (stat?.isDirectory() && !release && packageDataDir(target2, file))
|
|
1156
|
+
for (const asset of dataFiles(target2))
|
|
1157
|
+
setFile(trace, place(asset), asset);
|
|
1158
|
+
if (!stat?.isFile())
|
|
1159
|
+
continue;
|
|
1160
|
+
const at = appFile ? toPosixPath(path4.join("server", "assets", path4.relative(config.workspaceRoot, target2))) : place(target2);
|
|
1161
|
+
if (appFile)
|
|
1162
|
+
setFile(trace, at, target2);
|
|
1163
|
+
else
|
|
1164
|
+
enqueue(target2, release);
|
|
1165
|
+
if (release) {
|
|
1166
|
+
const relative = relativeSpecifier(path4.dirname(dest), at);
|
|
1167
|
+
if (relative !== edge.specifier)
|
|
1168
|
+
edits.set(edge.specifier, relative);
|
|
1169
|
+
}
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
const bare = isPackageSpecifier(edge.specifier);
|
|
1173
|
+
const name = bare ? packageName(edge.specifier) : undefined;
|
|
1174
|
+
if (bare && !name && !edge.specifier.startsWith("#"))
|
|
1175
|
+
continue;
|
|
1176
|
+
if (name && framework && !app && (edge.require || !runtimeDependencies.has(name)))
|
|
1177
|
+
continue;
|
|
1178
|
+
const target = resolveEdge(edge.specifier, file, edge.require);
|
|
1179
|
+
if (!target)
|
|
1180
|
+
continue;
|
|
1181
|
+
if (edge.dynamic && framework && buildOnlyModule.test(moduleName(target)))
|
|
1182
|
+
continue;
|
|
1183
|
+
enqueue(target, release);
|
|
1184
|
+
for (const counterpart of frameworkCounterparts(target))
|
|
1185
|
+
enqueue(counterpart, release);
|
|
1186
|
+
if (release || name && !place(target).startsWith(`node_modules/${name}/`)) {
|
|
1187
|
+
const relative = relativeSpecifier(path4.dirname(dest), place(target));
|
|
1188
|
+
if (relative !== edge.specifier)
|
|
1189
|
+
edits.set(edge.specifier, relative);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
if (edits.size > 0)
|
|
1193
|
+
trace.rewritten.set(dest, rewriteSpecifiers(file, source, edits));
|
|
1194
|
+
}
|
|
1195
|
+
flush();
|
|
1196
|
+
};
|
|
1197
|
+
const snapshot = () => ({
|
|
1198
|
+
files: [...trace.files],
|
|
1199
|
+
rewritten: [...trace.rewritten],
|
|
1200
|
+
seen: [...seen],
|
|
1201
|
+
claims: [...claims],
|
|
1202
|
+
standalones: [...standalones]
|
|
1203
|
+
});
|
|
1204
|
+
return { trace, place, add: run, snapshot, flush };
|
|
1205
|
+
}
|
|
1206
|
+
var prunedDirNames = [
|
|
1207
|
+
"node_modules",
|
|
1208
|
+
".git",
|
|
1209
|
+
".next",
|
|
1210
|
+
".pnext",
|
|
1211
|
+
".turbo",
|
|
1212
|
+
".cache",
|
|
1213
|
+
".vercel",
|
|
1214
|
+
".tmp"
|
|
1215
|
+
];
|
|
1216
|
+
var standaloneEntries = new Set(["server", "static", "node_modules", "package.json"]);
|
|
1217
|
+
function addAppFiles(config, index, trace) {
|
|
1218
|
+
const { keep = [], exclude = [] } = config.adapter ?? {};
|
|
1219
|
+
const named = (entries, name) => entries.some((entry) => name === entry || entry.startsWith(".") && name.endsWith(entry));
|
|
1220
|
+
for (const dest of trace.files.keys()) {
|
|
1221
|
+
const segments = dest.split("/");
|
|
1222
|
+
if (dest.startsWith("node_modules/") && segments.some((name) => named(exclude, name)))
|
|
1223
|
+
trace.files.delete(dest);
|
|
1224
|
+
}
|
|
1225
|
+
if (keep.length === 0)
|
|
1226
|
+
return;
|
|
1227
|
+
const compiled = compiledSources(config, index);
|
|
1228
|
+
const outTop = path4.relative(config.root, config.outRootPath).split(path4.sep)[0];
|
|
1229
|
+
const visit = (dir, kept) => {
|
|
1230
|
+
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
1231
|
+
const file = path4.join(dir, entry.name);
|
|
1232
|
+
if (entry.isDirectory()) {
|
|
1233
|
+
const pruned = prunedDirNames.includes(entry.name) && !named(keep, entry.name);
|
|
1234
|
+
if (pruned || dir === config.root && entry.name === outTop)
|
|
1235
|
+
continue;
|
|
1236
|
+
visit(file, kept || named(keep, entry.name));
|
|
1237
|
+
continue;
|
|
1238
|
+
}
|
|
1239
|
+
if (!entry.isFile() || compiled.has(file) && !named(keep, entry.name))
|
|
1240
|
+
continue;
|
|
1241
|
+
const env = entry.name.startsWith(".env");
|
|
1242
|
+
if (env ? !keep.includes(entry.name) : !kept && !named(keep, entry.name))
|
|
1243
|
+
continue;
|
|
1244
|
+
const relative = toPosixPath(path4.relative(config.root, file));
|
|
1245
|
+
if (!standaloneEntries.has(relative.split("/")[0]))
|
|
1246
|
+
setFile(trace, relative, file);
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
visit(config.root, false);
|
|
1250
|
+
}
|
|
1251
|
+
function compiledSources(config, index) {
|
|
1252
|
+
flushDevModuleCaches();
|
|
1253
|
+
const graph = compiledSourceGraph(config.outPath, config.workspaceRoot);
|
|
1254
|
+
const queue = Object.keys(index.modules).map((key) => releaseSourceFile(key.slice(key.indexOf(":", key.indexOf(":") + 1) + 1), config.root, config.workspaceRoot));
|
|
1255
|
+
if (index.proxy)
|
|
1256
|
+
queue.push(path4.resolve(config.root, index.proxy.file));
|
|
1257
|
+
for (const name of readdirSync2(config.root))
|
|
1258
|
+
if (/^(?:pnext|next|instrumentation)\.config\.|^instrumentation\./.test(name) && scriptFile.test(name))
|
|
1259
|
+
queue.push(path4.join(config.root, name));
|
|
1260
|
+
const compiled = new Set;
|
|
1261
|
+
for (const file of queue) {
|
|
1262
|
+
if (compiled.has(file))
|
|
1263
|
+
continue;
|
|
1264
|
+
compiled.add(file);
|
|
1265
|
+
queue.push(...graph.get(file) ?? []);
|
|
1266
|
+
}
|
|
1267
|
+
for (const css of index.globalCss)
|
|
1268
|
+
compiled.add(path4.resolve(config.root, css));
|
|
1269
|
+
return compiled;
|
|
1270
|
+
}
|
|
1271
|
+
function createPlacer(outPath, cache, claims = new Map) {
|
|
1272
|
+
const packageDir = (root, name) => {
|
|
1273
|
+
const owner = claims.get(name);
|
|
1274
|
+
if (owner === undefined)
|
|
1275
|
+
claims.set(name, root);
|
|
1276
|
+
if (owner === undefined || owner === root)
|
|
1277
|
+
return `node_modules/${name}`;
|
|
1278
|
+
const key = createHash2("sha256").update(root).digest("hex").slice(0, 12);
|
|
1279
|
+
return `node_modules/.pnext/${key}/node_modules/${name}`;
|
|
1280
|
+
};
|
|
1281
|
+
return (file) => {
|
|
1282
|
+
if (isInside(cache, file))
|
|
1283
|
+
return toPosixPath(path4.join("server", path4.relative(cache, file)));
|
|
1284
|
+
if (isInside(outPath, file))
|
|
1285
|
+
return toPosixPath(path4.relative(outPath, file));
|
|
1286
|
+
const framework = !installed(frameworkRoot2) && isInside(frameworkRoot2, file) && !installedIn(frameworkRoot2, file);
|
|
1287
|
+
if (framework) {
|
|
1288
|
+
const dir = packageDir(frameworkRoot2, frameworkPackage.name);
|
|
1289
|
+
return `${dir}/${toPosixPath(path4.relative(frameworkRoot2, file))}`;
|
|
1290
|
+
}
|
|
1291
|
+
const owner = installedPackage(file);
|
|
1292
|
+
if (owner)
|
|
1293
|
+
return [packageDir(owner.root, owner.name), ...owner.rest].join("/");
|
|
1294
|
+
const root = packageRoot(path4.dirname(file));
|
|
1295
|
+
const name = root && readPackageName(root);
|
|
1296
|
+
if (!root || !name)
|
|
1297
|
+
throw new Error(`pnext build: cannot place ${file} in the standalone output`);
|
|
1298
|
+
return `${packageDir(root, name)}/${toPosixPath(path4.relative(root, file))}`;
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
var standaloneDirs = new Map;
|
|
1302
|
+
function enclosingStandalone(file, outPath) {
|
|
1303
|
+
const dir = path4.dirname(file);
|
|
1304
|
+
if (dir === path4.dirname(dir))
|
|
1305
|
+
return;
|
|
1306
|
+
if (standaloneDirs.has(dir))
|
|
1307
|
+
return standaloneDirs.get(dir);
|
|
1308
|
+
const own = dir !== outPath && existsSync4(path4.join(dir, "server", "build-index.json")) && existsSync4(path4.join(dir, "server", "entry.js"));
|
|
1309
|
+
const found = own ? dir : enclosingStandalone(dir, outPath);
|
|
1310
|
+
standaloneDirs.set(dir, found);
|
|
1311
|
+
return found;
|
|
1312
|
+
}
|
|
1313
|
+
function addTree(root, dest, trace) {
|
|
1314
|
+
const visit = (dir, seen) => {
|
|
1315
|
+
const real = realpathSync2(dir);
|
|
1316
|
+
if (seen.has(real))
|
|
1317
|
+
return;
|
|
1318
|
+
seen.add(real);
|
|
1319
|
+
for (const name of readdirSync2(dir)) {
|
|
1320
|
+
const file = path4.join(dir, name);
|
|
1321
|
+
const stat = statSync(file, { throwIfNoEntry: false });
|
|
1322
|
+
if (stat?.isDirectory())
|
|
1323
|
+
visit(file, seen);
|
|
1324
|
+
else if (stat?.isFile())
|
|
1325
|
+
setFile(trace, `${dest}/${toPosixPath(path4.relative(root, file))}`, realpathSync2(file));
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
visit(root, new Set);
|
|
1329
|
+
}
|
|
1330
|
+
function installedPackage(file) {
|
|
1331
|
+
const posix = toPosixPath(file);
|
|
1332
|
+
const at = posix.lastIndexOf("/node_modules/");
|
|
1333
|
+
if (at === -1)
|
|
1334
|
+
return;
|
|
1335
|
+
const rest = posix.slice(at + "/node_modules/".length).split("/");
|
|
1336
|
+
const length = rest[0].startsWith("@") ? 2 : 1;
|
|
1337
|
+
const name = rest.slice(0, length).join("/");
|
|
1338
|
+
return { root: `${posix.slice(0, at)}/node_modules/${name}`, name, rest: rest.slice(length) };
|
|
1339
|
+
}
|
|
1340
|
+
function installed(file) {
|
|
1341
|
+
return toPosixPath(file).includes("/node_modules/");
|
|
1342
|
+
}
|
|
1343
|
+
function installedIn(root, file) {
|
|
1344
|
+
return path4.relative(root, file).split(path4.sep).includes("node_modules");
|
|
1345
|
+
}
|
|
1346
|
+
var transpilers = new Map;
|
|
1347
|
+
function scanEdges(file, source) {
|
|
1348
|
+
const ext = path4.extname(file);
|
|
1349
|
+
const loader = ext === ".tsx" || ext === ".jsx" ? "tsx" : /\.[cm]?ts$/.test(ext) ? "ts" : "js";
|
|
1350
|
+
let transpiler = transpilers.get(loader);
|
|
1351
|
+
if (!transpiler) {
|
|
1352
|
+
transpiler = new Bun.Transpiler({
|
|
1353
|
+
loader,
|
|
1354
|
+
tsconfig: { compilerOptions: { jsx: "react-jsx", jsxImportSource: "preact" } }
|
|
1355
|
+
});
|
|
1356
|
+
transpilers.set(loader, transpiler);
|
|
1357
|
+
}
|
|
1358
|
+
let imports;
|
|
1359
|
+
try {
|
|
1360
|
+
imports = transpiler.scanImports(source);
|
|
1361
|
+
} catch {
|
|
1362
|
+
return [];
|
|
1363
|
+
}
|
|
1364
|
+
const edges = imports.map((entry) => ({
|
|
1365
|
+
specifier: entry.path,
|
|
1366
|
+
dynamic: entry.kind === "dynamic-import",
|
|
1367
|
+
require: entry.kind === "require-call"
|
|
1368
|
+
}));
|
|
1369
|
+
const refs = importMetaRefs(file, source);
|
|
1370
|
+
for (const url of refs.urls)
|
|
1371
|
+
edges.push({ specifier: url.specifier, dynamic: false, url: true });
|
|
1372
|
+
for (const ref of refs.resolves)
|
|
1373
|
+
edges.push({ specifier: ref.specifier, dynamic: false });
|
|
1374
|
+
if (loader === "tsx")
|
|
1375
|
+
edges.push({ specifier: "preact/jsx-runtime", dynamic: false }, { specifier: "preact/jsx-dev-runtime", dynamic: false });
|
|
1376
|
+
return edges;
|
|
1377
|
+
}
|
|
1378
|
+
var resolved = new Map;
|
|
1379
|
+
function resolveEdge(specifier, from, require2 = false) {
|
|
1380
|
+
if (/^(?:node:|bun:|data:|https?:)/.test(specifier) || specifier === "bun")
|
|
1381
|
+
return;
|
|
1382
|
+
const bare = require2 ? specifier : splitResourceQuery(specifier).path;
|
|
1383
|
+
if (builtins.has(bare))
|
|
1384
|
+
return;
|
|
1385
|
+
const dir = path4.dirname(from);
|
|
1386
|
+
const key = `${dir}\x00${bare}`;
|
|
1387
|
+
if (resolved.has(key))
|
|
1388
|
+
return resolved.get(key);
|
|
1389
|
+
let target;
|
|
1695
1390
|
try {
|
|
1696
|
-
const
|
|
1697
|
-
|
|
1391
|
+
const request = bare.startsWith("file:") ? fileURLToPath2(bare) : bare;
|
|
1392
|
+
target = realpathSync2(Bun.resolveSync(request, dir));
|
|
1393
|
+
if (!statSync(target).isFile())
|
|
1394
|
+
target = undefined;
|
|
1698
1395
|
} catch {
|
|
1699
|
-
|
|
1396
|
+
target = undefined;
|
|
1700
1397
|
}
|
|
1398
|
+
resolved.set(key, target);
|
|
1399
|
+
return target;
|
|
1400
|
+
}
|
|
1401
|
+
function frameworkCounterparts(file) {
|
|
1402
|
+
const counterpart = prebundledFile(file);
|
|
1403
|
+
if (counterpart === file)
|
|
1404
|
+
return [];
|
|
1405
|
+
return [counterpart, path4.join(frameworkRoot2, PREBUNDLE_STAMP)];
|
|
1701
1406
|
}
|
|
1702
|
-
function
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1407
|
+
function moduleName(file) {
|
|
1408
|
+
const base = path4.basename(file, path4.extname(file));
|
|
1409
|
+
const chunk = path4.basename(path4.dirname(file)) === "_chunks";
|
|
1410
|
+
return chunk && isInside(path4.join(frameworkRoot2, "dist"), file) ? base.replace(/-[a-z0-9]{8}$/, "") : base;
|
|
1705
1411
|
}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
const
|
|
1710
|
-
const
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1412
|
+
function packageName(specifier) {
|
|
1413
|
+
if (specifier.startsWith("#"))
|
|
1414
|
+
return;
|
|
1415
|
+
const parts = specifier.split("/");
|
|
1416
|
+
const name = specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
1417
|
+
return name && !builtins.has(name) ? name : undefined;
|
|
1418
|
+
}
|
|
1419
|
+
function addPackageFiles(file, trace, place) {
|
|
1420
|
+
const inStore = installed(file);
|
|
1421
|
+
for (let dir = path4.dirname(file);dir !== path4.dirname(dir); dir = path4.dirname(dir)) {
|
|
1422
|
+
const manifest = path4.join(dir, "package.json");
|
|
1423
|
+
const found = existsSync4(manifest);
|
|
1424
|
+
if (found)
|
|
1425
|
+
setFile(trace, place(manifest), manifest);
|
|
1426
|
+
if (found && dir === frameworkRoot2) {
|
|
1427
|
+
for (const name of ["tsconfig.json", path4.join("config", "ts", "react.json")]) {
|
|
1428
|
+
const extra = path4.join(dir, name);
|
|
1429
|
+
if (existsSync4(extra))
|
|
1430
|
+
setFile(trace, place(extra), extra);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
const parent = path4.basename(path4.dirname(dir));
|
|
1434
|
+
const packageTop = parent === "node_modules" || parent.startsWith("@") && path4.basename(path4.dirname(path4.dirname(dir))) === "node_modules";
|
|
1435
|
+
if (inStore ? packageTop : found && readPackageName(dir))
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
function packageDataDir(dir, from) {
|
|
1440
|
+
const root = installedPackage(from)?.root ?? packageRoot(path4.dirname(from));
|
|
1441
|
+
if (!root || !isInside(root, dir) || isInside(dir, path4.dirname(from)))
|
|
1442
|
+
return false;
|
|
1443
|
+
return !path4.relative(root, dir).split(path4.sep).includes("node_modules");
|
|
1444
|
+
}
|
|
1445
|
+
function dataFiles(dir) {
|
|
1446
|
+
return readdirSync2(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
1447
|
+
const file = path4.join(dir, entry.name);
|
|
1448
|
+
if (entry.isDirectory())
|
|
1449
|
+
return entry.name === "node_modules" ? [] : dataFiles(file);
|
|
1450
|
+
return entry.isFile() ? [file] : [];
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
function packageRoot(dir) {
|
|
1454
|
+
for (;dir !== path4.dirname(dir); dir = path4.dirname(dir)) {
|
|
1455
|
+
if (existsSync4(path4.join(dir, "package.json")))
|
|
1456
|
+
return dir;
|
|
1457
|
+
}
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
function readPackageName(dir) {
|
|
1461
|
+
try {
|
|
1462
|
+
return JSON.parse(readFileSync2(path4.join(dir, "package.json"), "utf8")).name;
|
|
1463
|
+
} catch {
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
function relativeSpecifier(fromDir, to) {
|
|
1468
|
+
const relative = toPosixPath(path4.relative(fromDir, to));
|
|
1469
|
+
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
1470
|
+
}
|
|
1471
|
+
function rewriteSpecifiers(file, source, edits) {
|
|
1472
|
+
const refs = importMetaRefs(file, source);
|
|
1473
|
+
const spans = [...moduleSpecifierEdges(source, file), ...refs.urls, ...refs.resolves];
|
|
1474
|
+
const changes = spans.flatMap((span) => {
|
|
1475
|
+
const value = edits.get(span.specifier);
|
|
1476
|
+
return value === undefined ? [] : [{ start: span.start, end: span.end, value: JSON.stringify(value) }];
|
|
1477
|
+
});
|
|
1478
|
+
changes.sort((a, b) => a.start - b.start);
|
|
1479
|
+
return changes.length > 0 ? spliceSource(source, changes) : source;
|
|
1480
|
+
}
|
|
1481
|
+
function urlTarget(specifier, from) {
|
|
1482
|
+
try {
|
|
1483
|
+
const url = new URL(specifier, pathToFileURL(from));
|
|
1484
|
+
return url.protocol === "file:" ? path4.resolve(fileURLToPath2(url)) : undefined;
|
|
1485
|
+
} catch {
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
function isPackageSpecifier(specifier) {
|
|
1490
|
+
if (specifier === "." || specifier === "..")
|
|
1491
|
+
return false;
|
|
1492
|
+
if (specifier.startsWith("./") || specifier.startsWith("../"))
|
|
1493
|
+
return false;
|
|
1494
|
+
return !path4.isAbsolute(specifier) && !specifier.startsWith("file:");
|
|
1495
|
+
}
|
|
1496
|
+
function createCopier(outPath) {
|
|
1497
|
+
const dirs = new Map;
|
|
1498
|
+
const copied = new Set;
|
|
1499
|
+
const pending = [];
|
|
1500
|
+
const ensureDir = (dir) => {
|
|
1501
|
+
let made = dirs.get(dir);
|
|
1502
|
+
if (!made) {
|
|
1503
|
+
made = mkdir3(dir, { recursive: true });
|
|
1504
|
+
dirs.set(dir, made);
|
|
1505
|
+
}
|
|
1506
|
+
return made;
|
|
1507
|
+
};
|
|
1508
|
+
const copy = (dest, source, contents) => {
|
|
1509
|
+
if (copied.has(dest))
|
|
1510
|
+
return;
|
|
1511
|
+
copied.add(dest);
|
|
1512
|
+
const target = path4.join(outPath, dest);
|
|
1513
|
+
pending.push(ensureDir(path4.dirname(target)).then(async () => {
|
|
1514
|
+
if (contents !== undefined) {
|
|
1515
|
+
if (target !== source)
|
|
1516
|
+
await rm2(target, { force: true });
|
|
1517
|
+
return writeFile(target, contents);
|
|
1518
|
+
}
|
|
1519
|
+
if (target !== source)
|
|
1520
|
+
await copyFile2(source, target, constants2.COPYFILE_FICLONE);
|
|
1521
|
+
}));
|
|
1522
|
+
};
|
|
1523
|
+
return { copy, settle: () => Promise.all(pending) };
|
|
1524
|
+
}
|
|
1525
|
+
function isInside(root, file) {
|
|
1526
|
+
return file === root || file.startsWith(`${root}${path4.sep}`);
|
|
1715
1527
|
}
|
|
1716
1528
|
|
|
1717
1529
|
// src/cli/build.ts
|
|
@@ -1765,9 +1577,10 @@ async function runBuild(root, options, lifecycle) {
|
|
|
1765
1577
|
const warmMode = options.adapter === "vercel" ? "full" : "compile";
|
|
1766
1578
|
const warm = startWarmChild(config, warmMode);
|
|
1767
1579
|
lifecycle.warm = warm;
|
|
1580
|
+
const standalone = startStandalone(config);
|
|
1768
1581
|
const publicFiles = await log.step("prepare output directory", async () => {
|
|
1769
|
-
await ensureEmptyDir(config.
|
|
1770
|
-
return copyPublicDir(config.publicPath, path5.join(config.outPath, "
|
|
1582
|
+
await ensureEmptyDir(config.outRootPath, [devOutSegment, "pnext-pages-compat"]);
|
|
1583
|
+
return copyPublicDir(config.publicPath, path5.join(config.outPath, "static"));
|
|
1771
1584
|
});
|
|
1772
1585
|
const documentCss = Promise.resolve().then(() => buildGlobalCss(config, { verbose })).then(() => buildNotFoundCss(config, { verbose }));
|
|
1773
1586
|
documentCss.catch(() => {
|
|
@@ -1851,7 +1664,7 @@ async function runBuild(root, options, lifecycle) {
|
|
|
1851
1664
|
const clientBundles = log.step(`client bundles (${clientRoutes.length} route${clientRoutes.length === 1 ? "" : "s"})`, () => buildClientEntries({
|
|
1852
1665
|
config,
|
|
1853
1666
|
routes: clientRoutes,
|
|
1854
|
-
outDir: path5.join(config.outPath, "
|
|
1667
|
+
outDir: path5.join(config.outPath, "static", "assets"),
|
|
1855
1668
|
verbose,
|
|
1856
1669
|
hasServerActions: actionSources.length > 0,
|
|
1857
1670
|
pipeline: clientSources
|
|
@@ -1879,7 +1692,7 @@ async function runBuild(root, options, lifecycle) {
|
|
|
1879
1692
|
await clientBundles;
|
|
1880
1693
|
const proxyModule = await proxyBuild;
|
|
1881
1694
|
await partytownLib;
|
|
1882
|
-
await emitStaticClientChunks(config, path5.join(config.outPath, "
|
|
1695
|
+
await emitStaticClientChunks(config, path5.join(config.outPath, "static", "assets"));
|
|
1883
1696
|
if (verbose) {
|
|
1884
1697
|
const sources = sourceCacheStats();
|
|
1885
1698
|
log.log(`source cache \u2014 ${sources.reads} reads, ${sources.hits} shared, ${sources.files} files \xB7 parses ${JSON.stringify(scanFactsStats())}`);
|
|
@@ -2054,7 +1867,7 @@ async function runBuild(root, options, lifecycle) {
|
|
|
2054
1867
|
html: rendered.value.html,
|
|
2055
1868
|
status: rendered.value.status
|
|
2056
1869
|
});
|
|
2057
|
-
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "
|
|
1870
|
+
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "static"), file));
|
|
2058
1871
|
const revalidateSeconds = combineRevalidate(segmentConfig?.revalidate, rendered.revalidateSeconds);
|
|
2059
1872
|
const defaultExpireTime = buildCompat().defaultExpireTimeSeconds();
|
|
2060
1873
|
const effectiveCacheLife = cacheLife ?? (rendered.expireSeconds !== undefined || rendered.staleSeconds !== undefined ? {
|
|
@@ -2116,8 +1929,8 @@ Route (app)`);
|
|
|
2116
1929
|
await emitProxyServerArtifacts(config, proxyModule);
|
|
2117
1930
|
if (config.compat?.next) {
|
|
2118
1931
|
const sourceApp = path5.join(config.appPath, "..", "source-app");
|
|
2119
|
-
const layoutRoot =
|
|
2120
|
-
const hasTopLevelRootLayout = ["tsx", "ts", "jsx", "js"].some((ext) =>
|
|
1932
|
+
const layoutRoot = existsSync5(sourceApp) ? sourceApp : config.appPath;
|
|
1933
|
+
const hasTopLevelRootLayout = ["tsx", "ts", "jsx", "js"].some((ext) => existsSync5(path5.join(layoutRoot, `layout.${ext}`)));
|
|
2121
1934
|
const pseudos = hasTopLevelRootLayout ? ["_not-found.html", "_global-error.html"] : ["_not-found.html"];
|
|
2122
1935
|
for (const pseudo of pseudos) {
|
|
2123
1936
|
if (!(pseudo in staticFiles)) {
|
|
@@ -2147,21 +1960,19 @@ Route (app)`);
|
|
|
2147
1960
|
};
|
|
2148
1961
|
await writeBuildManifest(config.outPath, manifest);
|
|
2149
1962
|
log.log(`wrote manifest.json (${routes.length} route${routes.length === 1 ? "" : "s"})`);
|
|
2150
|
-
await log.step("server entry", () => emitServerEntry(config.outPath));
|
|
2151
1963
|
for (const hook of getBuildExtensions().completeHooks) {
|
|
2152
1964
|
await hook({ config, manifest, log });
|
|
2153
1965
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
clientReferences: [...compiledClientReferenceFiles()]
|
|
2160
|
-
}));
|
|
2161
|
-
}
|
|
2162
|
-
if (!existsSync4(buildIndexFile(config.outPath))) {
|
|
1966
|
+
await log.step("warm module cache", () => warm.finish(log, undefined, {
|
|
1967
|
+
globalCss: globalCssSources(config),
|
|
1968
|
+
clientReferences: [...compiledClientReferenceFiles()]
|
|
1969
|
+
}));
|
|
1970
|
+
if (!existsSync5(buildIndexFile(config.outPath))) {
|
|
2163
1971
|
throw new Error("pnext build: the server compile did not complete (see the error above).");
|
|
2164
1972
|
}
|
|
1973
|
+
await log.step("standalone output", () => writeStandalone(config, standalone));
|
|
1974
|
+
if (options.adapter === "vercel")
|
|
1975
|
+
await log.step("vercel adapter output", () => writeVercelOutput(config, manifest, { verbose }));
|
|
2165
1976
|
throwIfModuleGraphFailed();
|
|
2166
1977
|
const buildDurationMs = performance.now() - startedAt;
|
|
2167
1978
|
const phases = await settleBuildParallelPhases();
|
|
@@ -2207,7 +2018,7 @@ async function logInterceptionPrerenders(config, routes) {
|
|
|
2207
2018
|
return prerenders;
|
|
2208
2019
|
}
|
|
2209
2020
|
function routeFileExportsStaticParams(file) {
|
|
2210
|
-
if (!
|
|
2021
|
+
if (!existsSync5(file))
|
|
2211
2022
|
return false;
|
|
2212
2023
|
const source = readTextSync(file);
|
|
2213
2024
|
return /\bexport\s+(?:async\s+)?function\s+generateStaticParams\b/.test(source) || /\bexport\s+const\s+generateStaticParams\b/.test(source);
|
|
@@ -2226,22 +2037,24 @@ function interceptionDisplayRoute(route, filled) {
|
|
|
2226
2037
|
}
|
|
2227
2038
|
async function writeBuildManifest(outPath, manifest) {
|
|
2228
2039
|
assertManifestServerArtifacts(outPath, manifest);
|
|
2229
|
-
const file =
|
|
2230
|
-
const temporary =
|
|
2231
|
-
await
|
|
2232
|
-
await
|
|
2040
|
+
const file = buildManifestFile(outPath);
|
|
2041
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
2042
|
+
await mkdir4(path5.dirname(file), { recursive: true });
|
|
2043
|
+
await writeFile2(temporary, serializeBuildManifest(manifest));
|
|
2044
|
+
await rename3(temporary, file);
|
|
2233
2045
|
}
|
|
2234
2046
|
function assertManifestServerArtifacts(outPath, manifest) {
|
|
2235
2047
|
const artifacts = [
|
|
2236
2048
|
...manifest.proxyModule ? [manifest.proxyModule] : [],
|
|
2237
2049
|
...manifest.actions?.map((action) => action.modulePath) ?? []
|
|
2238
2050
|
];
|
|
2051
|
+
const outRoot = path5.dirname(outPath);
|
|
2239
2052
|
for (const artifact of artifacts) {
|
|
2240
2053
|
const file = path5.resolve(outPath, artifact);
|
|
2241
|
-
if (
|
|
2054
|
+
if (!file.startsWith(`${outRoot}${path5.sep}`)) {
|
|
2242
2055
|
throw new Error(`Build manifest server artifact escapes output directory: ${artifact}`);
|
|
2243
2056
|
}
|
|
2244
|
-
if (!
|
|
2057
|
+
if (!existsSync5(file)) {
|
|
2245
2058
|
throw new Error(`Build manifest server artifact is missing: ${artifact}`);
|
|
2246
2059
|
}
|
|
2247
2060
|
}
|
|
@@ -2333,7 +2146,7 @@ async function renderShellWithCacheMeta(config, route, render) {
|
|
|
2333
2146
|
var DYNAMIC_EXPIRE_SECONDS = 300;
|
|
2334
2147
|
function routeDeclaresShortLivedCache(route) {
|
|
2335
2148
|
for (const file of route.sourceFiles) {
|
|
2336
|
-
if (!
|
|
2149
|
+
if (!existsSync5(file))
|
|
2337
2150
|
continue;
|
|
2338
2151
|
const source = readTextSync(file);
|
|
2339
2152
|
for (const literal of source.matchAll(/cacheLife\s*\(\s*\{[^}]*\bexpire\s*:\s*([^,}]+)/gs)) {
|
|
@@ -2515,7 +2328,7 @@ async function emitConcreteNextPageArtifacts(config, route, routePath, rendered)
|
|
|
2515
2328
|
function staleTimeFromRouteSources(route) {
|
|
2516
2329
|
let found;
|
|
2517
2330
|
for (const file of route.sourceFiles) {
|
|
2518
|
-
if (!
|
|
2331
|
+
if (!existsSync5(file))
|
|
2519
2332
|
continue;
|
|
2520
2333
|
const source = readTextSync(file);
|
|
2521
2334
|
for (const literal of source.matchAll(/cacheLife\s*\(\s*\{[^}]*\bstale\s*:\s*([^,}]+)/gs)) {
|
|
@@ -2533,7 +2346,7 @@ function staleTimeFromRouteSources(route) {
|
|
|
2533
2346
|
}
|
|
2534
2347
|
function readTextSync(file) {
|
|
2535
2348
|
try {
|
|
2536
|
-
return
|
|
2349
|
+
return existsSync5(file) && statSync2(file).isFile() ? readFileSync3(file, "utf8") : "";
|
|
2537
2350
|
} catch {
|
|
2538
2351
|
return "";
|
|
2539
2352
|
}
|
|
@@ -2791,7 +2604,7 @@ function routeSourcesUseHttpFallback(root, route) {
|
|
|
2791
2604
|
for (const file of route.sourceFiles) {
|
|
2792
2605
|
if (!file.startsWith(root) || file.includes(`${path5.sep}node_modules${path5.sep}`))
|
|
2793
2606
|
continue;
|
|
2794
|
-
if (!
|
|
2607
|
+
if (!existsSync5(file))
|
|
2795
2608
|
continue;
|
|
2796
2609
|
const source = readTextSync(file);
|
|
2797
2610
|
if (/\b(?:notFound|forbidden|unauthorized)\s*\(\s*\)/.test(source))
|
|
@@ -2803,7 +2616,7 @@ function routeSourcesUseRequestApi(root, route) {
|
|
|
2803
2616
|
for (const file of route.sourceFiles) {
|
|
2804
2617
|
if (!file.startsWith(root) || file.includes(`${path5.sep}node_modules${path5.sep}`))
|
|
2805
2618
|
continue;
|
|
2806
|
-
if (!
|
|
2619
|
+
if (!existsSync5(file))
|
|
2807
2620
|
continue;
|
|
2808
2621
|
const source = readTextSync(file).replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
2809
2622
|
if (/\b(?:connection|cookies|headers|draftMode)\s*\(\s*\)/.test(source))
|
|
@@ -2813,7 +2626,7 @@ function routeSourcesUseRequestApi(root, route) {
|
|
|
2813
2626
|
}
|
|
2814
2627
|
function routeSourcesHaveDynamicHead(route) {
|
|
2815
2628
|
for (const file of route.sourceFiles) {
|
|
2816
|
-
if (!
|
|
2629
|
+
if (!existsSync5(file))
|
|
2817
2630
|
continue;
|
|
2818
2631
|
const source = readTextSync(file);
|
|
2819
2632
|
const match = /export\s+(?:async\s+)?function\s+(?:generateMetadata|generateViewport)\s*\([^)]*\)\s*(?::[^{]+)?\{/.exec(source);
|
|
@@ -2890,11 +2703,11 @@ async function renderNotFoundDocuments({
|
|
|
2890
2703
|
};
|
|
2891
2704
|
await documentCss;
|
|
2892
2705
|
if (await shouldBuildGlobalNotFound(config)) {
|
|
2893
|
-
await log.step("global not-found", async () => writeText(path5.join(config.outPath, "
|
|
2706
|
+
await log.step("global not-found", async () => writeText(path5.join(config.outPath, "static", "404.html"), await render()));
|
|
2894
2707
|
}
|
|
2895
2708
|
if (!config.compat?.next)
|
|
2896
2709
|
return;
|
|
2897
|
-
if (
|
|
2710
|
+
if (existsSync5(path5.join(config.outPath, "static", "404.html")))
|
|
2898
2711
|
return;
|
|
2899
2712
|
return defaultNotFoundDocument();
|
|
2900
2713
|
}
|
|
@@ -2902,7 +2715,7 @@ async function shouldBuildGlobalNotFound(config) {
|
|
|
2902
2715
|
const file = ["tsx", "ts", "jsx", "js"].flatMap((ext) => [
|
|
2903
2716
|
path5.join(config.appPath, `global-not-found.${ext}`),
|
|
2904
2717
|
path5.join(config.appPath, `not-found.${ext}`)
|
|
2905
|
-
]).find((candidate) =>
|
|
2718
|
+
]).find((candidate) => existsSync5(candidate));
|
|
2906
2719
|
if (!file)
|
|
2907
2720
|
return false;
|
|
2908
2721
|
return !/\bexport\s+const\s+dynamic\s*=\s*['"]force-dynamic['"]/.test(await readText(file));
|
|
@@ -2911,21 +2724,21 @@ async function emitProxyServerArtifacts(config, proxyModule) {
|
|
|
2911
2724
|
if (!config.compat?.next || !proxyModule)
|
|
2912
2725
|
return;
|
|
2913
2726
|
const compiled = path5.resolve(config.outPath, proxyModule);
|
|
2914
|
-
if (!
|
|
2727
|
+
if (!existsSync5(compiled))
|
|
2915
2728
|
return;
|
|
2916
2729
|
const serverDir = path5.join(config.root, ".next", "server");
|
|
2917
2730
|
await mkdir4(serverDir, { recursive: true });
|
|
2918
2731
|
const middlewareFile = path5.join(serverDir, "middleware.js");
|
|
2919
|
-
await
|
|
2920
|
-
const files = ["middleware.js"].filter((name) =>
|
|
2921
|
-
await
|
|
2732
|
+
await copyFile3(compiled, middlewareFile);
|
|
2733
|
+
const files = ["middleware.js"].filter((name) => existsSync5(path5.join(serverDir, name)));
|
|
2734
|
+
await writeFile2(path5.join(serverDir, "middleware.js.nft.json"), `${JSON.stringify({ version: 1, files })}
|
|
2922
2735
|
`);
|
|
2923
2736
|
}
|
|
2924
2737
|
async function emitNextNotFoundArtifacts(config, fallback404) {
|
|
2925
2738
|
if (!config.compat?.next)
|
|
2926
2739
|
return;
|
|
2927
|
-
const source = path5.join(config.outPath, "
|
|
2928
|
-
const html =
|
|
2740
|
+
const source = path5.join(config.outPath, "static", "404.html");
|
|
2741
|
+
const html = existsSync5(source) ? readFileSync3(source, "utf8") : fallback404;
|
|
2929
2742
|
if (html === undefined)
|
|
2930
2743
|
return;
|
|
2931
2744
|
const serverDir = path5.join(config.root, ".next", "server");
|
|
@@ -2933,21 +2746,21 @@ async function emitNextNotFoundArtifacts(config, fallback404) {
|
|
|
2933
2746
|
const notFoundDir = path5.join(serverDir, "app", "_not-found");
|
|
2934
2747
|
await mkdir4(pagesDir, { recursive: true });
|
|
2935
2748
|
await mkdir4(notFoundDir, { recursive: true });
|
|
2936
|
-
await
|
|
2937
|
-
await
|
|
2938
|
-
await
|
|
2749
|
+
await writeFile2(path5.join(pagesDir, "404.html"), html);
|
|
2750
|
+
await writeFile2(path5.join(serverDir, "app", "_not-found.html"), html);
|
|
2751
|
+
await writeFile2(path5.join(serverDir, "app", "_not-found.rsc"), html);
|
|
2939
2752
|
const pagesManifestFile = path5.join(serverDir, "pages-manifest.json");
|
|
2940
2753
|
let pagesManifest = {};
|
|
2941
2754
|
try {
|
|
2942
|
-
pagesManifest = JSON.parse(
|
|
2755
|
+
pagesManifest = JSON.parse(readFileSync3(pagesManifestFile, "utf8"));
|
|
2943
2756
|
} catch {}
|
|
2944
2757
|
pagesManifest["/404"] = "pages/404.html";
|
|
2945
|
-
await
|
|
2758
|
+
await writeFile2(pagesManifestFile, `${JSON.stringify(pagesManifest, null, 2)}
|
|
2946
2759
|
`);
|
|
2947
2760
|
const clientReferenceManifest = "page_client-reference-manifest.js";
|
|
2948
|
-
await
|
|
2761
|
+
await writeFile2(path5.join(notFoundDir, clientReferenceManifest), `self.__RSC_MANIFEST={}
|
|
2949
2762
|
`);
|
|
2950
|
-
await
|
|
2763
|
+
await writeFile2(path5.join(notFoundDir, "page.js.nft.json"), `${JSON.stringify({ version: 1, files: [clientReferenceManifest] }, null, 2)}
|
|
2951
2764
|
`);
|
|
2952
2765
|
}
|
|
2953
2766
|
async function collectStaticModuleMetadata(config, routes) {
|
|
@@ -2959,7 +2772,7 @@ async function collectStaticModuleMetadata(config, routes) {
|
|
|
2959
2772
|
if (route.kind !== "page")
|
|
2960
2773
|
continue;
|
|
2961
2774
|
for (const file of findLayouts(config.appPath, route.file)) {
|
|
2962
|
-
if (
|
|
2775
|
+
if (existsSync5(file))
|
|
2963
2776
|
files.add(file);
|
|
2964
2777
|
}
|
|
2965
2778
|
files.add(route.file);
|
|
@@ -2994,8 +2807,8 @@ async function collectStaticRouteMetadata(config, routes, staticMetadataFiles) {
|
|
|
2994
2807
|
for (const params of paramSets) {
|
|
2995
2808
|
const routePath = fillRoutePath(route.route, params);
|
|
2996
2809
|
const base = route.interception ? staticMetadataForRouteFromFiles(staticMetadataFiles, config.appPath, route.file, routePath) : staticMetadataForPathFromFiles(staticMetadataFiles, routePath);
|
|
2997
|
-
const
|
|
2998
|
-
metadata[staticRouteMetadataKey(routePath)] =
|
|
2810
|
+
const resolved2 = await withDynamicMetadataRoutes(base, config.appPath, route.file, routePath, (file) => importMetadataModule(config, file));
|
|
2811
|
+
metadata[staticRouteMetadataKey(routePath)] = resolved2;
|
|
2999
2812
|
}
|
|
3000
2813
|
}
|
|
3001
2814
|
return metadata;
|
|
@@ -3052,10 +2865,10 @@ async function buildStaticRouteHandler(config, route, options = {}) {
|
|
|
3052
2865
|
const body = await settleBeforeNextTask(response.clone().arrayBuffer());
|
|
3053
2866
|
if (!body)
|
|
3054
2867
|
continue;
|
|
3055
|
-
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "
|
|
2868
|
+
const relative = toPosixPath(path5.relative(path5.join(config.outPath, "static"), file));
|
|
3056
2869
|
if (!skipPhysicalWrite) {
|
|
3057
2870
|
await mkdir4(path5.dirname(file), { recursive: true });
|
|
3058
|
-
await
|
|
2871
|
+
await writeFile2(file, new Uint8Array(body));
|
|
3059
2872
|
}
|
|
3060
2873
|
const revalidateSeconds = combineRevalidate(route.segmentConfig?.revalidate, rendered.revalidateSeconds);
|
|
3061
2874
|
staticFiles[relative] = {
|
|
@@ -3087,7 +2900,7 @@ function settleBeforeNextTask(value) {
|
|
|
3087
2900
|
});
|
|
3088
2901
|
}
|
|
3089
2902
|
async function handlerHasEntirelyCachedIo(route) {
|
|
3090
|
-
if (route.synthetic || !
|
|
2903
|
+
if (route.synthetic || !existsSync5(route.file))
|
|
3091
2904
|
return false;
|
|
3092
2905
|
const source = await readText(route.file);
|
|
3093
2906
|
if (route.metadataRoute && metadataDefaultUsesCache(source))
|
|
@@ -3128,7 +2941,7 @@ function metadataDefaultUsesCache(source) {
|
|
|
3128
2941
|
return /\bexport\s+default\s+(?:async\s+)?function\b[^(]*\([^)]*\)\s*(?::[^{]*)?\{\s*(?:\/\/[^\n]*\n\s*|\/\*[\s\S]*?\*\/\s*)*['"]use cache['"]/.test(source);
|
|
3129
2942
|
}
|
|
3130
2943
|
async function usesUnstableCache(route) {
|
|
3131
|
-
if (route.synthetic || !
|
|
2944
|
+
if (route.synthetic || !existsSync5(route.file))
|
|
3132
2945
|
return false;
|
|
3133
2946
|
const source = await readText(route.file);
|
|
3134
2947
|
const localNames = [];
|
|
@@ -3154,7 +2967,7 @@ async function staticHandlerDynamicUsage(route) {
|
|
|
3154
2967
|
if (route.segmentConfig?.dynamic === "force-static" || route.segmentConfig?.dynamic === "error") {
|
|
3155
2968
|
return;
|
|
3156
2969
|
}
|
|
3157
|
-
if (route.synthetic || !
|
|
2970
|
+
if (route.synthetic || !existsSync5(route.file))
|
|
3158
2971
|
return;
|
|
3159
2972
|
const source = await readText(route.file);
|
|
3160
2973
|
if (/\b(?:request|req)\.url\b/.test(source))
|
|
@@ -3262,8 +3075,8 @@ function routeMetadataImageFiles(appPath, routeFile) {
|
|
|
3262
3075
|
let dir = path5.dirname(routeFile);
|
|
3263
3076
|
const root = path5.resolve(appPath);
|
|
3264
3077
|
while (dir.startsWith(root)) {
|
|
3265
|
-
if (
|
|
3266
|
-
for (const entry of
|
|
3078
|
+
if (existsSync5(dir)) {
|
|
3079
|
+
for (const entry of readdirSync3(dir)) {
|
|
3267
3080
|
if (/^(opengraph-image|twitter-image)\d*\.(tsx?|jsx?|mjs|png|jpe?g|gif|webp|svg)$/.test(entry)) {
|
|
3268
3081
|
return true;
|
|
3269
3082
|
}
|
|
@@ -3284,7 +3097,7 @@ async function copyStaticMetadataFiles(config, staticFiles, metadataFiles = disc
|
|
|
3284
3097
|
continue;
|
|
3285
3098
|
}
|
|
3286
3099
|
await mkdir4(path5.dirname(target), { recursive: true });
|
|
3287
|
-
await
|
|
3100
|
+
await copyFile3(metadataFile.file, target);
|
|
3288
3101
|
staticFiles[metadataFile.outputPath] = {
|
|
3289
3102
|
status: 200,
|
|
3290
3103
|
headers: [
|
|
@@ -3296,7 +3109,7 @@ async function copyStaticMetadataFiles(config, staticFiles, metadataFiles = disc
|
|
|
3296
3109
|
}
|
|
3297
3110
|
function staticHtmlPath(outPath, routePath, flatLayout = false) {
|
|
3298
3111
|
if (routePath === "/")
|
|
3299
|
-
return path5.join(outPath, "
|
|
3112
|
+
return path5.join(outPath, "static", "index.html");
|
|
3300
3113
|
const normalized = routePath.replace(/^\/|\/$/g, "");
|
|
3301
3114
|
if (flatLayout)
|
|
3302
3115
|
return safePublicPath(outPath, `${normalized}.html`);
|
|
@@ -3360,13 +3173,13 @@ function staticRouteHandlerPath(outPath, routePath) {
|
|
|
3360
3173
|
return safePublicPath(outPath, routePath.replace(/^\/+/, "") || "index");
|
|
3361
3174
|
}
|
|
3362
3175
|
function staticOutputCollision(outPath, file) {
|
|
3363
|
-
const publicPath = path5.join(outPath, "
|
|
3364
|
-
if (
|
|
3176
|
+
const publicPath = path5.join(outPath, "static");
|
|
3177
|
+
if (existsSync5(file) && statSync2(file).isDirectory()) {
|
|
3365
3178
|
return `${toPosixPath(path5.relative(publicPath, file))} already exists as a directory`;
|
|
3366
3179
|
}
|
|
3367
3180
|
let dir = path5.dirname(file);
|
|
3368
3181
|
while (dir !== publicPath && dir !== path5.dirname(dir)) {
|
|
3369
|
-
if (
|
|
3182
|
+
if (existsSync5(dir)) {
|
|
3370
3183
|
if (!statSync2(dir).isDirectory()) {
|
|
3371
3184
|
return `${toPosixPath(path5.relative(publicPath, dir))} already exists as a file`;
|
|
3372
3185
|
}
|
|
@@ -3407,8 +3220,8 @@ async function requestApiBailoutReason(route) {
|
|
|
3407
3220
|
function ownSourceFiles(route) {
|
|
3408
3221
|
const frameworkRoot3 = path5.resolve(fileURLToPath3(Bun.pathToFileURL(__PNEXT_PACKAGE_ROOT__ + "/src/cli/build.ts").href), "..", "..");
|
|
3409
3222
|
return route.sourceFiles.filter((file) => {
|
|
3410
|
-
const
|
|
3411
|
-
return !
|
|
3223
|
+
const resolved2 = path5.resolve(file);
|
|
3224
|
+
return !resolved2.includes(`${path5.sep}node_modules${path5.sep}`) && !resolved2.startsWith(frameworkRoot3 + path5.sep);
|
|
3412
3225
|
});
|
|
3413
3226
|
}
|
|
3414
3227
|
async function schedulesDeferredWork(route) {
|
|
@@ -3501,7 +3314,7 @@ function realFilePath(file) {
|
|
|
3501
3314
|
}
|
|
3502
3315
|
}
|
|
3503
3316
|
function safePublicPath(outPath, ...segments) {
|
|
3504
|
-
const publicPath = path5.join(outPath, "
|
|
3317
|
+
const publicPath = path5.join(outPath, "static");
|
|
3505
3318
|
const file = path5.join(publicPath, ...segments);
|
|
3506
3319
|
const relative = path5.relative(publicPath, file);
|
|
3507
3320
|
if (relative.startsWith("..") || path5.isAbsolute(relative)) {
|
|
@@ -3519,7 +3332,7 @@ async function copyPartytownLib(config) {
|
|
|
3519
3332
|
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
3333
|
return;
|
|
3521
3334
|
}
|
|
3522
|
-
const target = path5.join(config.outPath, "
|
|
3335
|
+
const target = path5.join(config.outPath, "static", "_next", "static", "~partytown");
|
|
3523
3336
|
await mkdir4(target, { recursive: true });
|
|
3524
3337
|
await copyPublicDir(libDir, target);
|
|
3525
3338
|
}
|
|
@@ -3529,7 +3342,7 @@ function resolvePartytownLibDir(root) {
|
|
|
3529
3342
|
try {
|
|
3530
3343
|
const pkgJson = requireFromRoot.resolve(`${pkg}/package.json`);
|
|
3531
3344
|
const libDir = path5.join(path5.dirname(pkgJson), "lib");
|
|
3532
|
-
if (
|
|
3345
|
+
if (existsSync5(libDir) && statSync2(libDir).isDirectory())
|
|
3533
3346
|
return libDir;
|
|
3534
3347
|
} catch {}
|
|
3535
3348
|
}
|
|
@@ -3540,7 +3353,7 @@ async function copyPublicDir(from, to) {
|
|
|
3540
3353
|
for (const relative of files) {
|
|
3541
3354
|
const target = path5.join(to, relative);
|
|
3542
3355
|
await mkdir4(path5.dirname(target), { recursive: true });
|
|
3543
|
-
await
|
|
3356
|
+
await copyFile3(path5.join(from, relative), target);
|
|
3544
3357
|
}
|
|
3545
3358
|
return files;
|
|
3546
3359
|
}
|